@milaboratories/pl-drivers 1.3.23 → 1.3.24

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.ts","../src/clients/upload.ts","../src/proto/google/protobuf/duration.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.ts","../src/clients/progress.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.ts","../src/helpers/download.ts","../src/helpers/validate.ts","../src/clients/download.ts","../src/proto/google/protobuf/timestamp.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.ts","../src/clients/ls_api.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.ts","../src/clients/logs.ts","../src/clients/helpers.ts","../src/drivers/helpers/helpers.ts","../src/drivers/helpers/files_cache.ts","../src/drivers/logs.ts","../src/drivers/download_and_logs_blob.ts","../src/drivers/types.ts","../src/drivers/upload.ts","../src/drivers/logs_stream.ts","../src/drivers/download_url.ts","../src/drivers/helpers/ls_list_entry.ts","../src/drivers/helpers/ls_storage_entry.ts","../src/drivers/virtual_storages.ts","../src/drivers/ls.ts"],"sourcesContent":["// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi\n */\nexport interface uploadapi {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init\n */\nexport interface uploadapi_Init {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Request\n */\nexport interface uploadapi_Init_Request {\n /**\n * Id of upload resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Response\n */\nexport interface uploadapi_Init_Response {\n /**\n * Number of parts in this upload.\n * For parallel upload support, client can generate any number of part upload URLs\n * at the moment and upload them in parallel.\n * <parts_count> keeps the number of chunks supported by this upload.\n * The parts count is calculated from the planned size of the upload, controller\n * configuration and underlying storage restrictions.\n *\n * @generated from protobuf field: uint64 parts_count = 1;\n */\n partsCount: bigint;\n /**\n * List of IDs of parts that were already uploaded by client.\n * Helps client to recover upload and skip already done parts\n * after being interrupted in the middle of the upload\n * (say, because of the restart).\n * Parts enumeration starts from 1.\n *\n * @generated from protobuf field: repeated uint64 uploaded_parts = 2;\n */\n uploadedParts: bigint[];\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress\n */\nexport interface uploadapi_UpdateProgress {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request\n */\nexport interface uploadapi_UpdateProgress_Request {\n /**\n * Id of upload resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * Amount of bytes, uploaded since the earlier call to UpdateProgress.\n * This value is just blindly added to the 'bytes_processed' of progress report,\n * so other clients can see the upload progress.\n * If client uploads the data in several streams (several chunks in parallel), it\n * can safely send progress updates individually for each of the streams, just counting\n * bytes uploaded by particular stream.\n *\n * Negative value can be used to report about upload retry: when upload was interrupted,\n * part of the uploaded data is lost and require re-upload.\n *\n * @generated from protobuf field: int64 bytes_processed = 2;\n */\n bytesProcessed: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\n */\nexport interface uploadapi_UpdateProgress_Response {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL\n */\nexport interface uploadapi_GetPartURL {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request\n */\nexport interface uploadapi_GetPartURL_Request {\n /**\n * Id of upload resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * Part to be uploaded. It is responsibility of the Client to watch after already uploaded parts:\n * - client can request an URL for the same part twice (request -> request) without errors;\n * - client can request an URL for alrady uploaded part (request -> upload -> request) without errors.\n *\n * Parts enumeration starts from 1.\n *\n * @generated from protobuf field: uint64 part_number = 2;\n */\n partNumber: bigint;\n /**\n * Size of the part uploaded by client earlier. Allows controller to count upload progress\n * based on client's input.\n * Client is free to never sent this value (send zeroes in each request).\n *\n * @generated from protobuf field: uint64 uploaded_part_size = 3;\n */\n uploadedPartSize: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader\n */\nexport interface uploadapi_GetPartURL_HTTPHeader {\n /**\n * @generated from protobuf field: string Name = 1 [json_name = \"Name\"];\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2 [json_name = \"Value\"];\n */\n value: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response\n */\nexport interface uploadapi_GetPartURL_Response {\n /**\n * URL for chunk upload\n *\n * @generated from protobuf field: string upload_url = 1;\n */\n uploadUrl: string;\n /**\n * HTTP method to use for chunk upload, say 'PUT' or 'POST'.\n *\n * @generated from protobuf field: string method = 2;\n */\n method: string;\n /**\n * List of headers with their values, MANDATORY to be sent by the client for the upload.\n * The destination service (the one, that will handle upload request for specific part)\n * may reject the request if it would not keep the given headers.\n *\n * @generated from protobuf field: repeated MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader headers = 3;\n */\n headers: uploadapi_GetPartURL_HTTPHeader[];\n /**\n * The number of the _first_ byte in the chunk.\n * Absolute position from the start of the file ( file.seek(<chunk_start>, SEEK_START) ).\n * The client is expected to send [<chunk_start>; <chunk_end>) range.\n *\n * @generated from protobuf field: uint64 chunk_start = 4;\n */\n chunkStart: bigint;\n /**\n * The number of the byte _after_ the last to be sent in the chunk.\n * Absolute position from the start of the file.\n * The client is expected to send [<chunk_start>; <chunk_end>) range.\n *\n * @generated from protobuf field: uint64 chunk_end = 5;\n */\n chunkEnd: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize\n */\nexport interface uploadapi_Finalize {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Request\n */\nexport interface uploadapi_Finalize_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Response\n */\nexport interface uploadapi_Finalize_Response {}\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi$Type extends MessageType<uploadapi> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi', []);\n }\n create(value?: PartialMessage<uploadapi>): uploadapi {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi\n ): uploadapi {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi\n */\nexport const uploadapi = new uploadapi$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Init$Type extends MessageType<uploadapi_Init> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Init', []);\n }\n create(value?: PartialMessage<uploadapi_Init>): uploadapi_Init {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Init>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Init\n ): uploadapi_Init {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_Init,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Init\n */\nexport const uploadapi_Init = new uploadapi_Init$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Init_Request$Type extends MessageType<uploadapi_Init_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Init.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_Init_Request>\n ): uploadapi_Init_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Init_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Init_Request\n ): uploadapi_Init_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_Init_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Request\n */\nexport const uploadapi_Init_Request = new uploadapi_Init_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Init_Response$Type extends MessageType<uploadapi_Init_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Init.Response', [\n {\n no: 1,\n name: 'parts_count',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'uploaded_parts',\n kind: 'scalar',\n repeat: 1 /*RepeatType.PACKED*/,\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_Init_Response>\n ): uploadapi_Init_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.partsCount = 0n;\n message.uploadedParts = [];\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Init_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Init_Response\n ): uploadapi_Init_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 parts_count */ 1:\n message.partsCount = reader.uint64().toBigInt();\n break;\n case /* repeated uint64 uploaded_parts */ 2:\n if (wireType === WireType.LengthDelimited)\n for (let e = reader.int32() + reader.pos; reader.pos < e; )\n message.uploadedParts.push(reader.uint64().toBigInt());\n else message.uploadedParts.push(reader.uint64().toBigInt());\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_Init_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 parts_count = 1; */\n if (message.partsCount !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.partsCount);\n /* repeated uint64 uploaded_parts = 2; */\n if (message.uploadedParts.length) {\n writer.tag(2, WireType.LengthDelimited).fork();\n for (let i = 0; i < message.uploadedParts.length; i++)\n writer.uint64(message.uploadedParts[i]);\n writer.join();\n }\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Response\n */\nexport const uploadapi_Init_Response = new uploadapi_Init_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_UpdateProgress$Type extends MessageType<uploadapi_UpdateProgress> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.UpdateProgress', []);\n }\n create(\n value?: PartialMessage<uploadapi_UpdateProgress>\n ): uploadapi_UpdateProgress {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_UpdateProgress\n ): uploadapi_UpdateProgress {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_UpdateProgress,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress\n */\nexport const uploadapi_UpdateProgress = new uploadapi_UpdateProgress$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_UpdateProgress_Request$Type extends MessageType<uploadapi_UpdateProgress_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'bytes_processed',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_UpdateProgress_Request>\n ): uploadapi_UpdateProgress_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.bytesProcessed = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_UpdateProgress_Request\n ): uploadapi_UpdateProgress_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 bytes_processed */ 2:\n message.bytesProcessed = reader.int64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_UpdateProgress_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 bytes_processed = 2; */\n if (message.bytesProcessed !== 0n)\n writer.tag(2, WireType.Varint).int64(message.bytesProcessed);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request\n */\nexport const uploadapi_UpdateProgress_Request =\n new uploadapi_UpdateProgress_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_UpdateProgress_Response$Type extends MessageType<uploadapi_UpdateProgress_Response> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response',\n []\n );\n }\n create(\n value?: PartialMessage<uploadapi_UpdateProgress_Response>\n ): uploadapi_UpdateProgress_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_UpdateProgress_Response\n ): uploadapi_UpdateProgress_Response {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_UpdateProgress_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\n */\nexport const uploadapi_UpdateProgress_Response =\n new uploadapi_UpdateProgress_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL$Type extends MessageType<uploadapi_GetPartURL> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL', []);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL>): uploadapi_GetPartURL {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL\n ): uploadapi_GetPartURL {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL\n */\nexport const uploadapi_GetPartURL = new uploadapi_GetPartURL$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL_Request$Type extends MessageType<uploadapi_GetPartURL_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'part_number',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'uploaded_part_size',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_GetPartURL_Request>\n ): uploadapi_GetPartURL_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.partNumber = 0n;\n message.uploadedPartSize = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL_Request\n ): uploadapi_GetPartURL_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* uint64 part_number */ 2:\n message.partNumber = reader.uint64().toBigInt();\n break;\n case /* uint64 uploaded_part_size */ 3:\n message.uploadedPartSize = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* uint64 part_number = 2; */\n if (message.partNumber !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.partNumber);\n /* uint64 uploaded_part_size = 3; */\n if (message.uploadedPartSize !== 0n)\n writer.tag(3, WireType.Varint).uint64(message.uploadedPartSize);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request\n */\nexport const uploadapi_GetPartURL_Request =\n new uploadapi_GetPartURL_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL_HTTPHeader$Type extends MessageType<uploadapi_GetPartURL_HTTPHeader> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader', [\n {\n no: 1,\n name: 'Name',\n kind: 'scalar',\n jsonName: 'Name',\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 2,\n name: 'Value',\n kind: 'scalar',\n jsonName: 'Value',\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_GetPartURL_HTTPHeader>\n ): uploadapi_GetPartURL_HTTPHeader {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.name = '';\n message.value = '';\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_HTTPHeader>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL_HTTPHeader\n ): uploadapi_GetPartURL_HTTPHeader {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string Name = 1 [json_name = \"Name\"];*/ 1:\n message.name = reader.string();\n break;\n case /* string Value = 2 [json_name = \"Value\"];*/ 2:\n message.value = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL_HTTPHeader,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string Name = 1 [json_name = \"Name\"]; */\n if (message.name !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2 [json_name = \"Value\"]; */\n if (message.value !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.value);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader\n */\nexport const uploadapi_GetPartURL_HTTPHeader =\n new uploadapi_GetPartURL_HTTPHeader$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL_Response$Type extends MessageType<uploadapi_GetPartURL_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response', [\n { no: 1, name: 'upload_url', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: 'method', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n {\n no: 3,\n name: 'headers',\n kind: 'message',\n repeat: 1 /*RepeatType.PACKED*/,\n T: () => uploadapi_GetPartURL_HTTPHeader\n },\n {\n no: 4,\n name: 'chunk_start',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 5,\n name: 'chunk_end',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_GetPartURL_Response>\n ): uploadapi_GetPartURL_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.uploadUrl = '';\n message.method = '';\n message.headers = [];\n message.chunkStart = 0n;\n message.chunkEnd = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL_Response\n ): uploadapi_GetPartURL_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string upload_url */ 1:\n message.uploadUrl = reader.string();\n break;\n case /* string method */ 2:\n message.method = reader.string();\n break;\n case /* repeated MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader headers */ 3:\n message.headers.push(\n uploadapi_GetPartURL_HTTPHeader.internalBinaryRead(\n reader,\n reader.uint32(),\n options\n )\n );\n break;\n case /* uint64 chunk_start */ 4:\n message.chunkStart = reader.uint64().toBigInt();\n break;\n case /* uint64 chunk_end */ 5:\n message.chunkEnd = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string upload_url = 1; */\n if (message.uploadUrl !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.uploadUrl);\n /* string method = 2; */\n if (message.method !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.method);\n /* repeated MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader headers = 3; */\n for (let i = 0; i < message.headers.length; i++)\n uploadapi_GetPartURL_HTTPHeader\n .internalBinaryWrite(\n message.headers[i],\n writer.tag(3, WireType.LengthDelimited).fork(),\n options\n )\n .join();\n /* uint64 chunk_start = 4; */\n if (message.chunkStart !== 0n)\n writer.tag(4, WireType.Varint).uint64(message.chunkStart);\n /* uint64 chunk_end = 5; */\n if (message.chunkEnd !== 0n)\n writer.tag(5, WireType.Varint).uint64(message.chunkEnd);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response\n */\nexport const uploadapi_GetPartURL_Response =\n new uploadapi_GetPartURL_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Finalize$Type extends MessageType<uploadapi_Finalize> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Finalize', []);\n }\n create(value?: PartialMessage<uploadapi_Finalize>): uploadapi_Finalize {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Finalize>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Finalize\n ): uploadapi_Finalize {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_Finalize,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize\n */\nexport const uploadapi_Finalize = new uploadapi_Finalize$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Finalize_Request$Type extends MessageType<uploadapi_Finalize_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Finalize.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_Finalize_Request>\n ): uploadapi_Finalize_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Finalize_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Finalize_Request\n ): uploadapi_Finalize_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_Finalize_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Request\n */\nexport const uploadapi_Finalize_Request = new uploadapi_Finalize_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Finalize_Response$Type extends MessageType<uploadapi_Finalize_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Finalize.Response', []);\n }\n create(\n value?: PartialMessage<uploadapi_Finalize_Response>\n ): uploadapi_Finalize_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Finalize_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Finalize_Response\n ): uploadapi_Finalize_Response {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_Finalize_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Response\n */\nexport const uploadapi_Finalize_Response =\n new uploadapi_Finalize_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport const Upload = new ServiceType(\n 'MiLaboratories.Controller.Shared.Upload',\n [\n {\n name: 'Init',\n options: {},\n I: uploadapi_Init_Request,\n O: uploadapi_Init_Response\n },\n {\n name: 'GetPartURL',\n options: {},\n I: uploadapi_GetPartURL_Request,\n O: uploadapi_GetPartURL_Response\n },\n {\n name: 'UpdateProgress',\n options: {},\n I: uploadapi_UpdateProgress_Request,\n O: uploadapi_UpdateProgress_Response\n },\n {\n name: 'Finalize',\n options: {},\n I: uploadapi_Finalize_Request,\n O: uploadapi_Finalize_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Upload } from './protocol';\nimport type { uploadapi_Finalize_Response } from './protocol';\nimport type { uploadapi_Finalize_Request } from './protocol';\nimport type { uploadapi_UpdateProgress_Response } from './protocol';\nimport type { uploadapi_UpdateProgress_Request } from './protocol';\nimport type { uploadapi_GetPartURL_Response } from './protocol';\nimport type { uploadapi_GetPartURL_Request } from './protocol';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { uploadapi_Init_Response } from './protocol';\nimport type { uploadapi_Init_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Upload provides access to data upload feature, allowing clients to uplad data to Platforma.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport interface IUploadClient {\n /**\n *\n * Init upload, making controller to do all required preparation steps.\n *\n *\n * @generated from protobuf rpc: Init(MiLaboratories.Controller.Shared.uploadapi.Init.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Init.Response);\n */\n init(\n input: uploadapi_Init_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Init_Request, uploadapi_Init_Response>;\n /**\n *\n * GetPartURL provides URL for uploading chunk of the data.\n * Clients are expected to put their data directly to the given location.\n *\n *\n * @generated from protobuf rpc: GetPartURL(MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request) returns (MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response);\n */\n getPartURL(\n input: uploadapi_GetPartURL_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response>;\n /**\n *\n * UpdateProgress of the upload, so other clients can see how it is going.\n *\n *\n * @generated from protobuf rpc: UpdateProgress(MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request) returns (MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response);\n */\n updateProgress(\n input: uploadapi_UpdateProgress_Request,\n options?: RpcOptions\n ): UnaryCall<\n uploadapi_UpdateProgress_Request,\n uploadapi_UpdateProgress_Response\n >;\n /**\n *\n * Finalize informs Controller that the upload process is done.\n * Returns an error, if the total size of all uploaded chunks is not equal to\n * size of the upload given in Init.\n *\n *\n * @generated from protobuf rpc: Finalize(MiLaboratories.Controller.Shared.uploadapi.Finalize.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Finalize.Response);\n */\n finalize(\n input: uploadapi_Finalize_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Finalize_Request, uploadapi_Finalize_Response>;\n}\n/**\n *\n * Upload provides access to data upload feature, allowing clients to uplad data to Platforma.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport class UploadClient implements IUploadClient, ServiceInfo {\n typeName = Upload.typeName;\n methods = Upload.methods;\n options = Upload.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n *\n * Init upload, making controller to do all required preparation steps.\n *\n *\n * @generated from protobuf rpc: Init(MiLaboratories.Controller.Shared.uploadapi.Init.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Init.Response);\n */\n init(\n input: uploadapi_Init_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Init_Request, uploadapi_Init_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_Init_Request, uploadapi_Init_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n *\n * GetPartURL provides URL for uploading chunk of the data.\n * Clients are expected to put their data directly to the given location.\n *\n *\n * @generated from protobuf rpc: GetPartURL(MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request) returns (MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response);\n */\n getPartURL(\n input: uploadapi_GetPartURL_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response> {\n const method = this.methods[1],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n uploadapi_GetPartURL_Request,\n uploadapi_GetPartURL_Response\n >('unary', this._transport, method, opt, input);\n }\n /**\n *\n * UpdateProgress of the upload, so other clients can see how it is going.\n *\n *\n * @generated from protobuf rpc: UpdateProgress(MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request) returns (MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response);\n */\n updateProgress(\n input: uploadapi_UpdateProgress_Request,\n options?: RpcOptions\n ): UnaryCall<\n uploadapi_UpdateProgress_Request,\n uploadapi_UpdateProgress_Response\n > {\n const method = this.methods[2],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n uploadapi_UpdateProgress_Request,\n uploadapi_UpdateProgress_Response\n >('unary', this._transport, method, opt, input);\n }\n /**\n *\n * Finalize informs Controller that the upload process is done.\n * Returns an error, if the total size of all uploaded chunks is not equal to\n * size of the upload given in Init.\n *\n *\n * @generated from protobuf rpc: Finalize(MiLaboratories.Controller.Shared.uploadapi.Finalize.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Finalize.Response);\n */\n finalize(\n input: uploadapi_Finalize_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Finalize_Request, uploadapi_Finalize_Response> {\n const method = this.methods[3],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n uploadapi_Finalize_Request,\n uploadapi_Finalize_Response\n >('unary', this._transport, method, opt, input);\n }\n}\n","import * as fs from 'node:fs/promises';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { PlClient, addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { UploadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client';\nimport { MiLogger } from '@milaboratories/ts-helpers';\nimport { Dispatcher, request } from 'undici';\nimport { uploadapi_GetPartURL_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class MTimeError extends Error {}\n\nexport class UnexpectedEOF extends Error {}\n\nexport class NetworkError extends Error {}\n\nexport class NoFileForUploading extends Error {}\n\n/** Low-level client for grpc uploadapi.\n * The user should pass here a concrete BlobUpload/<storageId> resource,\n * it can be got from handle field of BlobUpload. */\nexport class ClientUpload {\n private readonly grpcClient: UploadClient;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n public readonly httpClient: Dispatcher,\n _: PlClient,\n public readonly logger: MiLogger\n ) {\n this.grpcClient = new UploadClient(this.grpcTransport);\n }\n\n close() {}\n\n public async initUpload({ id, type }: ResourceInfo, options?: RpcOptions): Promise<bigint[]> {\n const init = await this.grpcClient.init({ resourceId: id }, addRTypeToMetadata(type, options));\n return this.partsToUpload(init.response);\n }\n\n public async partUpload(\n { id, type }: ResourceInfo,\n path: string,\n partNumber: bigint,\n partsOverall: number,\n expectedMTimeUnix: bigint,\n options?: RpcOptions\n ) {\n const info = await this.grpcClient.getPartURL(\n {\n resourceId: id,\n partNumber: partNumber,\n uploadedPartSize: 0n // we update progress as a separate call later.\n },\n addRTypeToMetadata(type, options)\n ).response;\n\n const { chunk, mTime } = await this.readChunk(path, info.chunkStart, info.chunkEnd);\n if (mTime > expectedMTimeUnix) {\n throw new MTimeError(\n 'file was modified, expected mtime: ' + expectedMTimeUnix + ', got: ' + mTime + '.'\n );\n }\n\n const resp = await request(info.uploadUrl, this.prepareUploadOpts(info, chunk));\n\n const body = await resp.body.text();\n this.logger.info(\n `uploaded chunk ${partNumber} from ${partsOverall} of resource: ${id},` +\n ` response: '${body.toString()}', ` +\n `status code: ${resp.statusCode}`\n );\n\n if (resp.statusCode != 200) {\n throw new NetworkError(\n `response is not ok, status code: ${resp.statusCode},` +\n ` body: ${body}, headers: ${resp.headers}, url: ${info.uploadUrl}`\n );\n }\n\n await this.grpcClient.updateProgress(\n {\n resourceId: id,\n bytesProcessed: info.chunkEnd - info.chunkStart\n },\n addRTypeToMetadata(type, options)\n );\n }\n\n public async finalizeUpload({ id, type }: ResourceInfo, options?: RpcOptions) {\n return await this.grpcClient.finalize({ resourceId: id }, addRTypeToMetadata(type, options));\n }\n\n private async readChunk(\n path: string,\n chunkStart: bigint,\n chunkEnd: bigint\n ): Promise<{ chunk: Buffer; mTime: bigint }> {\n let f: fs.FileHandle | undefined;\n try {\n f = await fs.open(path);\n const len = Number(chunkEnd - chunkStart);\n const pos = Number(chunkStart);\n const b = Buffer.alloc(len);\n const bytesRead = await this.readBytesFromPosition(f, b, len, pos);\n\n const stat = await fs.stat(path);\n\n return {\n chunk: b.subarray(0, bytesRead),\n mTime: BigInt(Math.floor(stat.mtimeMs / 1000))\n };\n } catch (e: any) {\n if (e.code == 'ENOENT')\n throw new NoFileForUploading(`there is no file ${path} for uploading`);\n throw e;\n } finally {\n f?.close();\n }\n }\n\n /** Read len bytes from a given position. The reason the method exists\n is that FileHandle.read can read less bytes than it's needed. */\n async readBytesFromPosition(f: fs.FileHandle, b: Buffer, len: number, position: number) {\n let bytesReadTotal = 0;\n while (bytesReadTotal < len) {\n const { bytesRead } = await f.read(\n b,\n bytesReadTotal,\n len - bytesReadTotal,\n position + bytesReadTotal\n );\n if (bytesRead === 0) {\n throw new UnexpectedEOF('file ended earlier than expected.');\n }\n bytesReadTotal += bytesRead;\n }\n\n return bytesReadTotal;\n }\n\n /** Calculates parts that need to be uploaded from the parts that were\n * already uploaded. */\n private partsToUpload(info: { partsCount: bigint; uploadedParts: bigint[] }): bigint[] {\n const toUpload: bigint[] = [];\n const uploaded = new Set(info.uploadedParts);\n\n for (let i = 1n; i <= info.partsCount; i++) {\n if (!uploaded.has(i)) toUpload.push(i);\n }\n\n return toUpload;\n }\n\n private prepareUploadOpts(info: uploadapi_GetPartURL_Response, chunk: Buffer): any {\n const headers = info.headers.map(({ name, value }) => [name, value]);\n\n return {\n dispatcher: this.httpClient,\n body: chunk,\n headers: Object.fromEntries(headers),\n method: info.method.toUpperCase() as Dispatcher.HttpMethod\n };\n }\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"google/protobuf/duration.proto\" (package \"google.protobuf\", syntax proto3)\n// tslint:disable\n//\n// Protocol Buffers - Google's data interchange format\n// Copyright 2008 Google Inc. All rights reserved.\n// https://developers.google.com/protocol-buffers/\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { typeofJsonValue } from '@protobuf-ts/runtime';\nimport type { JsonValue } from '@protobuf-ts/runtime';\nimport type { JsonReadOptions } from '@protobuf-ts/runtime';\nimport type { JsonWriteOptions } from '@protobuf-ts/runtime';\nimport { PbLong } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * A Duration represents a signed, fixed-length span of time represented\n * as a count of seconds and fractions of seconds at nanosecond\n * resolution. It is independent of any calendar and concepts like \"day\"\n * or \"month\". It is related to Timestamp in that the difference between\n * two Timestamp values is a Duration and it can be added or subtracted\n * from a Timestamp. Range is approximately +-10,000 years.\n *\n * # Examples\n *\n * Example 1: Compute Duration from two Timestamps in pseudo code.\n *\n * Timestamp start = ...;\n * Timestamp end = ...;\n * Duration duration = ...;\n *\n * duration.seconds = end.seconds - start.seconds;\n * duration.nanos = end.nanos - start.nanos;\n *\n * if (duration.seconds < 0 && duration.nanos > 0) {\n * duration.seconds += 1;\n * duration.nanos -= 1000000000;\n * } else if (duration.seconds > 0 && duration.nanos < 0) {\n * duration.seconds -= 1;\n * duration.nanos += 1000000000;\n * }\n *\n * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.\n *\n * Timestamp start = ...;\n * Duration duration = ...;\n * Timestamp end = ...;\n *\n * end.seconds = start.seconds + duration.seconds;\n * end.nanos = start.nanos + duration.nanos;\n *\n * if (end.nanos < 0) {\n * end.seconds -= 1;\n * end.nanos += 1000000000;\n * } else if (end.nanos >= 1000000000) {\n * end.seconds += 1;\n * end.nanos -= 1000000000;\n * }\n *\n * Example 3: Compute Duration from datetime.timedelta in Python.\n *\n * td = datetime.timedelta(days=3, minutes=10)\n * duration = Duration()\n * duration.FromTimedelta(td)\n *\n * # JSON Mapping\n *\n * In JSON format, the Duration type is encoded as a string rather than an\n * object, where the string ends in the suffix \"s\" (indicating seconds) and\n * is preceded by the number of seconds, with nanoseconds expressed as\n * fractional seconds. For example, 3 seconds with 0 nanoseconds should be\n * encoded in JSON format as \"3s\", while 3 seconds and 1 nanosecond should\n * be expressed in JSON format as \"3.000000001s\", and 3 seconds and 1\n * microsecond should be expressed in JSON format as \"3.000001s\".\n *\n *\n *\n * @generated from protobuf message google.protobuf.Duration\n */\nexport interface Duration {\n /**\n * Signed seconds of the span of time. Must be from -315,576,000,000\n * to +315,576,000,000 inclusive. Note: these bounds are computed from:\n * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years\n *\n * @generated from protobuf field: int64 seconds = 1;\n */\n seconds: bigint;\n /**\n * Signed fractions of a second at nanosecond resolution of the span\n * of time. Durations less than one second are represented with a 0\n * `seconds` field and a positive or negative `nanos` field. For durations\n * of one second or more, a non-zero value for the `nanos` field must be\n * of the same sign as the `seconds` field. Must be from -999,999,999\n * to +999,999,999 inclusive.\n *\n * @generated from protobuf field: int32 nanos = 2;\n */\n nanos: number;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass Duration$Type extends MessageType<Duration> {\n constructor() {\n super('google.protobuf.Duration', [\n {\n no: 1,\n name: 'seconds',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'nanos', kind: 'scalar', T: 5 /*ScalarType.INT32*/ }\n ]);\n }\n /**\n * Encode `Duration` to JSON string like \"3.000001s\".\n */\n internalJsonWrite(message: Duration, options: JsonWriteOptions): JsonValue {\n let s = PbLong.from(message.seconds).toNumber();\n if (s > 315576000000 || s < -315576000000)\n throw new Error('Duration value out of range.');\n let text = message.seconds.toString();\n if (s === 0 && message.nanos < 0) text = '-' + text;\n if (message.nanos !== 0) {\n let nanosStr = Math.abs(message.nanos).toString();\n nanosStr = '0'.repeat(9 - nanosStr.length) + nanosStr;\n if (nanosStr.substring(3) === '000000')\n nanosStr = nanosStr.substring(0, 3);\n else if (nanosStr.substring(6) === '000')\n nanosStr = nanosStr.substring(0, 6);\n text += '.' + nanosStr;\n }\n return text + 's';\n }\n /**\n * Decode `Duration` from JSON string like \"3.000001s\"\n */\n internalJsonRead(\n json: JsonValue,\n options: JsonReadOptions,\n target?: Duration\n ): Duration {\n if (typeof json !== 'string')\n throw new Error(\n 'Unable to parse Duration from JSON ' +\n typeofJsonValue(json) +\n '. Expected string.'\n );\n let match = json.match(/^(-?)([0-9]+)(?:\\.([0-9]+))?s/);\n if (match === null)\n throw new Error(\n 'Unable to parse Duration from JSON string. Invalid format.'\n );\n if (!target) target = this.create();\n let [, sign, secs, nanos] = match;\n let longSeconds = PbLong.from(sign + secs);\n if (\n longSeconds.toNumber() > 315576000000 ||\n longSeconds.toNumber() < -315576000000\n )\n throw new Error(\n 'Unable to parse Duration from JSON string. Value out of range.'\n );\n target.seconds = longSeconds.toBigInt();\n if (typeof nanos == 'string') {\n let nanosStr = sign + nanos + '0'.repeat(9 - nanos.length);\n target.nanos = parseInt(nanosStr);\n }\n return target;\n }\n create(value?: PartialMessage<Duration>): Duration {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.seconds = 0n;\n message.nanos = 0;\n if (value !== undefined)\n reflectionMergePartial<Duration>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: Duration\n ): Duration {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* int64 seconds */ 1:\n message.seconds = reader.int64().toBigInt();\n break;\n case /* int32 nanos */ 2:\n message.nanos = reader.int32();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: Duration,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* int64 seconds = 1; */\n if (message.seconds !== 0n)\n writer.tag(1, WireType.Varint).int64(message.seconds);\n /* int32 nanos = 2; */\n if (message.nanos !== 0)\n writer.tag(2, WireType.Varint).int32(message.nanos);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message google.protobuf.Duration\n */\nexport const Duration = new Duration$Type();\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\nimport { Duration } from '../../../../../../../google/protobuf/duration';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI\n */\nexport interface ProgressAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.Report\n */\nexport interface ProgressAPI_Report {\n /**\n * @generated from protobuf field: float progress = 1;\n */\n progress: number;\n /**\n * @generated from protobuf field: uint64 bytes_processed = 2;\n */\n bytesProcessed: bigint;\n /**\n * @generated from protobuf field: uint64 bytes_total = 3;\n */\n bytesTotal: bigint;\n /**\n * @generated from protobuf field: bool done = 4;\n */\n done: boolean;\n /**\n * Name of current progress stage (if any)\n *\n * @generated from protobuf field: string name = 5;\n */\n name: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus\n */\nexport interface ProgressAPI_GetStatus {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request\n */\nexport interface ProgressAPI_GetStatus_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response\n */\nexport interface ProgressAPI_GetStatus_Response {\n /**\n * @generated from protobuf field: MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1;\n */\n report?: ProgressAPI_Report;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus\n */\nexport interface ProgressAPI_RealtimeStatus {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\n */\nexport interface ProgressAPI_RealtimeStatus_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * @generated from protobuf field: google.protobuf.Duration update_interval = 2;\n */\n updateInterval?: Duration;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\n */\nexport interface ProgressAPI_RealtimeStatus_Response {\n /**\n * @generated from protobuf field: MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1;\n */\n report?: ProgressAPI_Report;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI$Type extends MessageType<ProgressAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI', []);\n }\n create(value?: PartialMessage<ProgressAPI>): ProgressAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI\n ): ProgressAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: ProgressAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI\n */\nexport const ProgressAPI = new ProgressAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_Report$Type extends MessageType<ProgressAPI_Report> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.Report', [\n { no: 1, name: 'progress', kind: 'scalar', T: 2 /*ScalarType.FLOAT*/ },\n {\n no: 2,\n name: 'bytes_processed',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'bytes_total',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 4, name: 'done', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },\n { no: 5, name: 'name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_Report>): ProgressAPI_Report {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.progress = 0;\n message.bytesProcessed = 0n;\n message.bytesTotal = 0n;\n message.done = false;\n message.name = '';\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_Report>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_Report\n ): ProgressAPI_Report {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* float progress */ 1:\n message.progress = reader.float();\n break;\n case /* uint64 bytes_processed */ 2:\n message.bytesProcessed = reader.uint64().toBigInt();\n break;\n case /* uint64 bytes_total */ 3:\n message.bytesTotal = reader.uint64().toBigInt();\n break;\n case /* bool done */ 4:\n message.done = reader.bool();\n break;\n case /* string name */ 5:\n message.name = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_Report,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* float progress = 1; */\n if (message.progress !== 0)\n writer.tag(1, WireType.Bit32).float(message.progress);\n /* uint64 bytes_processed = 2; */\n if (message.bytesProcessed !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.bytesProcessed);\n /* uint64 bytes_total = 3; */\n if (message.bytesTotal !== 0n)\n writer.tag(3, WireType.Varint).uint64(message.bytesTotal);\n /* bool done = 4; */\n if (message.done !== false)\n writer.tag(4, WireType.Varint).bool(message.done);\n /* string name = 5; */\n if (message.name !== '')\n writer.tag(5, WireType.LengthDelimited).string(message.name);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.Report\n */\nexport const ProgressAPI_Report = new ProgressAPI_Report$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_GetStatus$Type extends MessageType<ProgressAPI_GetStatus> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.GetStatus', []);\n }\n create(value?: PartialMessage<ProgressAPI_GetStatus>): ProgressAPI_GetStatus {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_GetStatus\n ): ProgressAPI_GetStatus {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: ProgressAPI_GetStatus,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus\n */\nexport const ProgressAPI_GetStatus = new ProgressAPI_GetStatus$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_GetStatus_Request$Type extends MessageType<ProgressAPI_GetStatus_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<ProgressAPI_GetStatus_Request>\n ): ProgressAPI_GetStatus_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_GetStatus_Request\n ): ProgressAPI_GetStatus_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_GetStatus_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request\n */\nexport const ProgressAPI_GetStatus_Request =\n new ProgressAPI_GetStatus_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_GetStatus_Response$Type extends MessageType<ProgressAPI_GetStatus_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response', [\n { no: 1, name: 'report', kind: 'message', T: () => ProgressAPI_Report }\n ]);\n }\n create(\n value?: PartialMessage<ProgressAPI_GetStatus_Response>\n ): ProgressAPI_GetStatus_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_GetStatus_Response\n ): ProgressAPI_GetStatus_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* MiLaboratories.Controller.Shared.ProgressAPI.Report report */ 1:\n message.report = ProgressAPI_Report.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.report\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_GetStatus_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(\n message.report,\n writer.tag(1, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response\n */\nexport const ProgressAPI_GetStatus_Response =\n new ProgressAPI_GetStatus_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_RealtimeStatus$Type extends MessageType<ProgressAPI_RealtimeStatus> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus', []);\n }\n create(\n value?: PartialMessage<ProgressAPI_RealtimeStatus>\n ): ProgressAPI_RealtimeStatus {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_RealtimeStatus\n ): ProgressAPI_RealtimeStatus {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: ProgressAPI_RealtimeStatus,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus\n */\nexport const ProgressAPI_RealtimeStatus = new ProgressAPI_RealtimeStatus$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_RealtimeStatus_Request$Type extends MessageType<ProgressAPI_RealtimeStatus_Request> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request',\n [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'update_interval', kind: 'message', T: () => Duration }\n ]\n );\n }\n create(\n value?: PartialMessage<ProgressAPI_RealtimeStatus_Request>\n ): ProgressAPI_RealtimeStatus_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_RealtimeStatus_Request\n ): ProgressAPI_RealtimeStatus_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* google.protobuf.Duration update_interval */ 2:\n message.updateInterval = Duration.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.updateInterval\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_RealtimeStatus_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* google.protobuf.Duration update_interval = 2; */\n if (message.updateInterval)\n Duration.internalBinaryWrite(\n message.updateInterval,\n writer.tag(2, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\n */\nexport const ProgressAPI_RealtimeStatus_Request =\n new ProgressAPI_RealtimeStatus_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_RealtimeStatus_Response$Type extends MessageType<ProgressAPI_RealtimeStatus_Response> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response',\n [{ no: 1, name: 'report', kind: 'message', T: () => ProgressAPI_Report }]\n );\n }\n create(\n value?: PartialMessage<ProgressAPI_RealtimeStatus_Response>\n ): ProgressAPI_RealtimeStatus_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_RealtimeStatus_Response\n ): ProgressAPI_RealtimeStatus_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* MiLaboratories.Controller.Shared.ProgressAPI.Report report */ 1:\n message.report = ProgressAPI_Report.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.report\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_RealtimeStatus_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(\n message.report,\n writer.tag(1, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\n */\nexport const ProgressAPI_RealtimeStatus_Response =\n new ProgressAPI_RealtimeStatus_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport const Progress = new ServiceType(\n 'MiLaboratories.Controller.Shared.Progress',\n [\n {\n name: 'GetStatus',\n options: {\n 'google.api.http': { get: '/resources/{resource_id}/get-progress' }\n },\n I: ProgressAPI_GetStatus_Request,\n O: ProgressAPI_GetStatus_Response\n },\n {\n name: 'RealtimeStatus',\n serverStreaming: true,\n options: {},\n I: ProgressAPI_RealtimeStatus_Request,\n O: ProgressAPI_RealtimeStatus_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Progress } from './protocol';\nimport type { ProgressAPI_RealtimeStatus_Response } from './protocol';\nimport type { ProgressAPI_RealtimeStatus_Request } from './protocol';\nimport type { ServerStreamingCall } from '@protobuf-ts/runtime-rpc';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { ProgressAPI_GetStatus_Response } from './protocol';\nimport type { ProgressAPI_GetStatus_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Progress provides access to progress of any long-running process associated with resource.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport interface IProgressClient {\n /**\n * @generated from protobuf rpc: GetStatus(MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request) returns (MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response);\n */\n getStatus(\n input: ProgressAPI_GetStatus_Request,\n options?: RpcOptions\n ): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response>;\n /**\n * @generated from protobuf rpc: RealtimeStatus(MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request) returns (stream MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response);\n */\n realtimeStatus(\n input: ProgressAPI_RealtimeStatus_Request,\n options?: RpcOptions\n ): ServerStreamingCall<\n ProgressAPI_RealtimeStatus_Request,\n ProgressAPI_RealtimeStatus_Response\n >;\n}\n/**\n *\n * Progress provides access to progress of any long-running process associated with resource.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport class ProgressClient implements IProgressClient, ServiceInfo {\n typeName = Progress.typeName;\n methods = Progress.methods;\n options = Progress.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * @generated from protobuf rpc: GetStatus(MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request) returns (MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response);\n */\n getStatus(\n input: ProgressAPI_GetStatus_Request,\n options?: RpcOptions\n ): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n ProgressAPI_GetStatus_Request,\n ProgressAPI_GetStatus_Response\n >('unary', this._transport, method, opt, input);\n }\n /**\n * @generated from protobuf rpc: RealtimeStatus(MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request) returns (stream MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response);\n */\n realtimeStatus(\n input: ProgressAPI_RealtimeStatus_Request,\n options?: RpcOptions\n ): ServerStreamingCall<\n ProgressAPI_RealtimeStatus_Request,\n ProgressAPI_RealtimeStatus_Response\n > {\n const method = this.methods[1],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n ProgressAPI_RealtimeStatus_Request,\n ProgressAPI_RealtimeStatus_Response\n >('serverStreaming', this._transport, method, opt, input);\n }\n}\n","import { ProgressClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { Duration } from '../proto/google/protobuf/duration';\nimport { PlClient, addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { MiLogger, notEmpty } from '@milaboratories/ts-helpers';\nimport { Dispatcher } from 'undici';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport type ProgressStatus = {\n done: boolean;\n progress: number;\n bytesProcessed?: string;\n bytesTotal?: string;\n};\n\n// ClientProgress holds a grpc connection to the platform\n// but for Progress API service.\n// When blobs are transfered, one can got a status of transfering\n// using this API.\nexport class ClientProgress {\n public readonly grpcClient: ProgressClient;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n _: Dispatcher,\n public readonly client: PlClient,\n public readonly logger: MiLogger\n ) {\n this.grpcClient = new ProgressClient(this.grpcTransport);\n }\n\n close() {}\n\n /** getStatus gets a progress status by given rId and rType. */\n async getStatus({ id, type }: ResourceInfo, options?: RpcOptions): Promise<ProgressStatus> {\n const status = await this.grpcClient.getStatus(\n { resourceId: id },\n addRTypeToMetadata(type, options)\n );\n\n const report = notEmpty(status.response.report);\n\n return {\n done: report.done,\n progress: report.progress,\n bytesProcessed: String(report.bytesProcessed),\n bytesTotal: String(report.bytesTotal)\n };\n }\n\n // realtimeStatus returns a async generator that takes statuses from\n // GRPC stream every updateIntervalMs milliseconds.\n async *realtimeStatus(\n { id, type }: ResourceInfo,\n updateIntervalMs: number = 100,\n options?: RpcOptions\n ) {\n options = addRTypeToMetadata(type, options);\n\n const secs = Math.floor(updateIntervalMs / 1000);\n const nanos = (updateIntervalMs - secs * 1000) * 1000000;\n const updateInterval = Duration.create({\n seconds: BigInt(secs),\n nanos: nanos\n });\n\n try {\n const { responses } = this.grpcClient.realtimeStatus(\n {\n resourceId: id,\n updateInterval: updateInterval\n },\n options\n );\n\n yield* responses;\n } catch (e) {\n this.logger.warn('Failed to get realtime status' + e);\n throw e;\n }\n }\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI\n */\nexport interface DownloadAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL\n */\nexport interface DownloadAPI_GetDownloadURL {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\n */\nexport interface DownloadAPI_GetDownloadURL_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\n */\nexport interface DownloadAPI_GetDownloadURL_HTTPHeader {\n /**\n * @generated from protobuf field: string Name = 1 [json_name = \"Name\"];\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2 [json_name = \"Value\"];\n */\n value: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\n */\nexport interface DownloadAPI_GetDownloadURL_Response {\n /**\n * @generated from protobuf field: string download_url = 1;\n */\n downloadUrl: string;\n /**\n * @generated from protobuf field: repeated MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader headers = 2;\n */\n headers: DownloadAPI_GetDownloadURL_HTTPHeader[];\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI$Type extends MessageType<DownloadAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.DownloadAPI', []);\n }\n create(value?: PartialMessage<DownloadAPI>): DownloadAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI\n ): DownloadAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: DownloadAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI\n */\nexport const DownloadAPI = new DownloadAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL$Type extends MessageType<DownloadAPI_GetDownloadURL> {\n constructor() {\n super('MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL', []);\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL>\n ): DownloadAPI_GetDownloadURL {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL\n ): DownloadAPI_GetDownloadURL {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL\n */\nexport const DownloadAPI_GetDownloadURL = new DownloadAPI_GetDownloadURL$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL_Request$Type extends MessageType<DownloadAPI_GetDownloadURL_Request> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request',\n [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]\n );\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL_Request>\n ): DownloadAPI_GetDownloadURL_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL_Request\n ): DownloadAPI_GetDownloadURL_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\n */\nexport const DownloadAPI_GetDownloadURL_Request =\n new DownloadAPI_GetDownloadURL_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL_HTTPHeader$Type extends MessageType<DownloadAPI_GetDownloadURL_HTTPHeader> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader',\n [\n {\n no: 1,\n name: 'Name',\n kind: 'scalar',\n jsonName: 'Name',\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 2,\n name: 'Value',\n kind: 'scalar',\n jsonName: 'Value',\n T: 9 /*ScalarType.STRING*/\n }\n ]\n );\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL_HTTPHeader>\n ): DownloadAPI_GetDownloadURL_HTTPHeader {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.name = '';\n message.value = '';\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_HTTPHeader>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL_HTTPHeader\n ): DownloadAPI_GetDownloadURL_HTTPHeader {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string Name = 1 [json_name = \"Name\"];*/ 1:\n message.name = reader.string();\n break;\n case /* string Value = 2 [json_name = \"Value\"];*/ 2:\n message.value = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL_HTTPHeader,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string Name = 1 [json_name = \"Name\"]; */\n if (message.name !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2 [json_name = \"Value\"]; */\n if (message.value !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.value);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\n */\nexport const DownloadAPI_GetDownloadURL_HTTPHeader =\n new DownloadAPI_GetDownloadURL_HTTPHeader$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL_Response$Type extends MessageType<DownloadAPI_GetDownloadURL_Response> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response',\n [\n {\n no: 1,\n name: 'download_url',\n kind: 'scalar',\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 2,\n name: 'headers',\n kind: 'message',\n repeat: 1 /*RepeatType.PACKED*/,\n T: () => DownloadAPI_GetDownloadURL_HTTPHeader\n }\n ]\n );\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL_Response>\n ): DownloadAPI_GetDownloadURL_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.downloadUrl = '';\n message.headers = [];\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL_Response\n ): DownloadAPI_GetDownloadURL_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string download_url */ 1:\n message.downloadUrl = reader.string();\n break;\n case /* repeated MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader headers */ 2:\n message.headers.push(\n DownloadAPI_GetDownloadURL_HTTPHeader.internalBinaryRead(\n reader,\n reader.uint32(),\n options\n )\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string download_url = 1; */\n if (message.downloadUrl !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.downloadUrl);\n /* repeated MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader headers = 2; */\n for (let i = 0; i < message.headers.length; i++)\n DownloadAPI_GetDownloadURL_HTTPHeader.internalBinaryWrite(\n message.headers[i],\n writer.tag(2, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\n */\nexport const DownloadAPI_GetDownloadURL_Response =\n new DownloadAPI_GetDownloadURL_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport const Download = new ServiceType(\n 'MiLaboratories.Controller.Shared.Download',\n [\n {\n name: 'GetDownloadURL',\n options: {\n 'google.api.http': { get: '/resources/{resource_id}/get-download-url' }\n },\n I: DownloadAPI_GetDownloadURL_Request,\n O: DownloadAPI_GetDownloadURL_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Download } from './protocol';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { DownloadAPI_GetDownloadURL_Response } from './protocol';\nimport type { DownloadAPI_GetDownloadURL_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Download provides access to any data, that can be downloaded via network.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport interface IDownloadClient {\n /**\n * @generated from protobuf rpc: GetDownloadURL(MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request) returns (MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response);\n */\n getDownloadURL(\n input: DownloadAPI_GetDownloadURL_Request,\n options?: RpcOptions\n ): UnaryCall<\n DownloadAPI_GetDownloadURL_Request,\n DownloadAPI_GetDownloadURL_Response\n >;\n}\n/**\n *\n * Download provides access to any data, that can be downloaded via network.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport class DownloadClient implements IDownloadClient, ServiceInfo {\n typeName = Download.typeName;\n methods = Download.methods;\n options = Download.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * @generated from protobuf rpc: GetDownloadURL(MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request) returns (MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response);\n */\n getDownloadURL(\n input: DownloadAPI_GetDownloadURL_Request,\n options?: RpcOptions\n ): UnaryCall<\n DownloadAPI_GetDownloadURL_Request,\n DownloadAPI_GetDownloadURL_Response\n > {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n DownloadAPI_GetDownloadURL_Request,\n DownloadAPI_GetDownloadURL_Response\n >('unary', this._transport, method, opt, input);\n }\n}\n","import { Dispatcher, request } from 'undici';\nimport { Readable } from 'node:stream';\nimport { ReadableStream } from 'node:stream/web';\nimport { text } from 'node:stream/consumers';\n\nexport interface DownloadResponse {\n content: ReadableStream;\n size: number;\n}\n\n/** Throws when a status code of the downloading URL was in range [400, 500). */\nexport class NetworkError400 extends Error {}\n\nexport class DownloadHelper {\n constructor(public readonly httpClient: Dispatcher) {}\n\n async downloadRemoteFile(\n url: string,\n reqHeaders: Record<string, string>,\n signal?: AbortSignal\n ): Promise<DownloadResponse> {\n const { statusCode, body, headers } = await request(url, {\n dispatcher: this.httpClient,\n headers: reqHeaders,\n signal\n });\n\n const webBody = Readable.toWeb(body);\n\n if (statusCode != 200) {\n const textBody = await text(webBody);\n const beginning = textBody.substring(0, Math.min(textBody.length, 1000));\n\n if (400 <= statusCode && statusCode < 500) {\n throw new NetworkError400(\n `Http error: statusCode: ${statusCode} url: ${url.toString()}, beginning of body: ${beginning}`\n );\n }\n\n throw new Error(`Http error: statusCode: ${statusCode} url: ${url.toString()}`);\n }\n\n return {\n content: webBody,\n size: Number(headers['content-length'])\n };\n }\n}\n","import path from 'node:path';\n\nexport function validateAbsolute(p: string): string {\n if (!path.isAbsolute(p)) throw new Error(`Path ${p} is not absolute.`);\n return p;\n}\n","import { Readable } from 'node:stream';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { DownloadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { MiLogger } from '@milaboratories/ts-helpers';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { Dispatcher } from 'undici';\nimport {\n DownloadAPI_GetDownloadURL_HTTPHeader,\n DownloadAPI_GetDownloadURL_Response\n} from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\nimport { DownloadHelper, DownloadResponse } from '../helpers/download';\nimport { LocalStorageProjection } from '../drivers/types';\nimport { validateAbsolute } from '../helpers/validate';\n\nconst storageProtocol = 'storage://';\n\nexport class UnknownStorageError extends Error {}\n\nexport class WrongLocalFileUrl extends Error {}\n\n/** Gets URLs for downloading from pl-core, parses them and reads or downloads\n * files locally and from the web. */\nexport class ClientDownload {\n public readonly grpcClient: DownloadClient;\n private readonly downloadHelper: DownloadHelper;\n private readonly localStorageIdsToRoot: Map<string, string>;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger,\n /** Pl storages available locally */\n localProjections: LocalStorageProjection[]\n ) {\n for (const lp of localProjections) if (lp.localPath !== '') validateAbsolute(lp.localPath);\n this.grpcClient = new DownloadClient(this.grpcTransport);\n this.downloadHelper = new DownloadHelper(httpClient);\n this.localStorageIdsToRoot = new Map(\n localProjections.map((lp) => [lp.storageId, lp.localPath])\n );\n }\n\n close() {}\n\n async getUrl(\n { id, type }: ResourceInfo,\n options?: RpcOptions,\n signal?: AbortSignal\n ): Promise<DownloadAPI_GetDownloadURL_Response> {\n const withAbort = options ?? {};\n withAbort.abort = signal;\n\n return await this.grpcClient.getDownloadURL(\n { resourceId: id },\n addRTypeToMetadata(type, withAbort)\n ).response;\n }\n\n async downloadBlob(\n info: ResourceInfo,\n options?: RpcOptions,\n signal?: AbortSignal\n ): Promise<DownloadResponse> {\n const { downloadUrl, headers } = await this.getUrl(info, options, signal);\n\n this.logger.info(`download from url ${downloadUrl}`);\n\n return this.isLocal(downloadUrl)\n ? await this.readLocalFile(downloadUrl)\n : await this.downloadHelper.downloadRemoteFile(\n downloadUrl,\n headersFromProto(headers),\n signal\n );\n }\n\n private isLocal = (url: string) => url.startsWith(storageProtocol);\n\n async readLocalFile(url: string): Promise<DownloadResponse> {\n const fullPath = parseLocalFileUrl(url, this.localStorageIdsToRoot);\n const stat = await fsp.stat(fullPath);\n const size = stat.size;\n\n return {\n content: Readable.toWeb(fs.createReadStream(fullPath)),\n size\n };\n }\n}\n\nexport function parseLocalFileUrl(url: string, localStorageIdsToRoot: Map<string, string>): string {\n const parsed = new URL(url);\n if (parsed.pathname == '')\n throw new WrongLocalFileUrl(`url for local filepath ${url} does not match url scheme`);\n\n const storageId = parsed.host;\n const storageRoot = localStorageIdsToRoot.get(storageId);\n if (storageRoot === undefined)\n throw new UnknownStorageError(`Unknown storage location: ${storageId}`);\n\n const localPath = decodeURIComponent(parsed.pathname.slice(1));\n const fullPath = storageRoot === '' ? localPath : path.join(storageRoot, localPath);\n\n return fullPath;\n}\n\nexport function headersFromProto(\n headers: DownloadAPI_GetDownloadURL_HTTPHeader[]\n): Record<string, string> {\n return Object.fromEntries(headers.map(({ name, value }) => [name, value]));\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"google/protobuf/timestamp.proto\" (package \"google.protobuf\", syntax proto3)\n// tslint:disable\n//\n// Protocol Buffers - Google's data interchange format\n// Copyright 2008 Google Inc. All rights reserved.\n// https://developers.google.com/protocol-buffers/\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { typeofJsonValue } from '@protobuf-ts/runtime';\nimport type { JsonValue } from '@protobuf-ts/runtime';\nimport type { JsonReadOptions } from '@protobuf-ts/runtime';\nimport type { JsonWriteOptions } from '@protobuf-ts/runtime';\nimport { PbLong } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * A Timestamp represents a point in time independent of any time zone or local\n * calendar, encoded as a count of seconds and fractions of seconds at\n * nanosecond resolution. The count is relative to an epoch at UTC midnight on\n * January 1, 1970, in the proleptic Gregorian calendar which extends the\n * Gregorian calendar backwards to year one.\n *\n * All minutes are 60 seconds long. Leap seconds are \"smeared\" so that no leap\n * second table is needed for interpretation, using a [24-hour linear\n * smear](https://developers.google.com/time/smear).\n *\n * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By\n * restricting to that range, we ensure that we can convert to and from [RFC\n * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.\n *\n * # Examples\n *\n * Example 1: Compute Timestamp from POSIX `time()`.\n *\n * Timestamp timestamp;\n * timestamp.set_seconds(time(NULL));\n * timestamp.set_nanos(0);\n *\n * Example 2: Compute Timestamp from POSIX `gettimeofday()`.\n *\n * struct timeval tv;\n * gettimeofday(&tv, NULL);\n *\n * Timestamp timestamp;\n * timestamp.set_seconds(tv.tv_sec);\n * timestamp.set_nanos(tv.tv_usec * 1000);\n *\n * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.\n *\n * FILETIME ft;\n * GetSystemTimeAsFileTime(&ft);\n * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;\n *\n * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z\n * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.\n * Timestamp timestamp;\n * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));\n * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));\n *\n * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.\n *\n * long millis = System.currentTimeMillis();\n *\n * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)\n * .setNanos((int) ((millis % 1000) * 1000000)).build();\n *\n *\n * Example 5: Compute Timestamp from Java `Instant.now()`.\n *\n * Instant now = Instant.now();\n *\n * Timestamp timestamp =\n * Timestamp.newBuilder().setSeconds(now.getEpochSecond())\n * .setNanos(now.getNano()).build();\n *\n *\n * Example 6: Compute Timestamp from current time in Python.\n *\n * timestamp = Timestamp()\n * timestamp.GetCurrentTime()\n *\n * # JSON Mapping\n *\n * In JSON format, the Timestamp type is encoded as a string in the\n * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the\n * format is \"{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z\"\n * where {year} is always expressed using four digits while {month}, {day},\n * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional\n * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),\n * are optional. The \"Z\" suffix indicates the timezone (\"UTC\"); the timezone\n * is required. A proto3 JSON serializer should always use UTC (as indicated by\n * \"Z\") when printing the Timestamp type and a proto3 JSON parser should be\n * able to accept both UTC and other timezones (as indicated by an offset).\n *\n * For example, \"2017-01-15T01:30:15.01Z\" encodes 15.01 seconds past\n * 01:30 UTC on January 15, 2017.\n *\n * In JavaScript, one can convert a Date object to this format using the\n * standard\n * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)\n * method. In Python, a standard `datetime.datetime` object can be converted\n * to this format using\n * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with\n * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use\n * the Joda Time's [`ISODateTimeFormat.dateTime()`](\n * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D\n * ) to obtain a formatter capable of generating timestamps in this format.\n *\n *\n *\n * @generated from protobuf message google.protobuf.Timestamp\n */\nexport interface Timestamp {\n /**\n * Represents seconds of UTC time since Unix epoch\n * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to\n * 9999-12-31T23:59:59Z inclusive.\n *\n * @generated from protobuf field: int64 seconds = 1;\n */\n seconds: bigint;\n /**\n * Non-negative fractions of a second at nanosecond resolution. Negative\n * second values with fractions must still have non-negative nanos values\n * that count forward in time. Must be from 0 to 999,999,999\n * inclusive.\n *\n * @generated from protobuf field: int32 nanos = 2;\n */\n nanos: number;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass Timestamp$Type extends MessageType<Timestamp> {\n constructor() {\n super('google.protobuf.Timestamp', [\n {\n no: 1,\n name: 'seconds',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'nanos', kind: 'scalar', T: 5 /*ScalarType.INT32*/ }\n ]);\n }\n /**\n * Creates a new `Timestamp` for the current time.\n */\n now(): Timestamp {\n const msg = this.create();\n const ms = Date.now();\n msg.seconds = PbLong.from(Math.floor(ms / 1000)).toBigInt();\n msg.nanos = (ms % 1000) * 1000000;\n return msg;\n }\n /**\n * Converts a `Timestamp` to a JavaScript Date.\n */\n toDate(message: Timestamp): Date {\n return new Date(\n PbLong.from(message.seconds).toNumber() * 1000 +\n Math.ceil(message.nanos / 1000000)\n );\n }\n /**\n * Converts a JavaScript Date to a `Timestamp`.\n */\n fromDate(date: Date): Timestamp {\n const msg = this.create();\n const ms = date.getTime();\n msg.seconds = PbLong.from(Math.floor(ms / 1000)).toBigInt();\n msg.nanos = (ms % 1000) * 1000000;\n return msg;\n }\n /**\n * In JSON format, the `Timestamp` type is encoded as a string\n * in the RFC 3339 format.\n */\n internalJsonWrite(message: Timestamp, options: JsonWriteOptions): JsonValue {\n let ms = PbLong.from(message.seconds).toNumber() * 1000;\n if (\n ms < Date.parse('0001-01-01T00:00:00Z') ||\n ms > Date.parse('9999-12-31T23:59:59Z')\n )\n throw new Error(\n 'Unable to encode Timestamp to JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.'\n );\n if (message.nanos < 0)\n throw new Error(\n 'Unable to encode invalid Timestamp to JSON. Nanos must not be negative.'\n );\n let z = 'Z';\n if (message.nanos > 0) {\n let nanosStr = (message.nanos + 1000000000).toString().substring(1);\n if (nanosStr.substring(3) === '000000')\n z = '.' + nanosStr.substring(0, 3) + 'Z';\n else if (nanosStr.substring(6) === '000')\n z = '.' + nanosStr.substring(0, 6) + 'Z';\n else z = '.' + nanosStr + 'Z';\n }\n return new Date(ms).toISOString().replace('.000Z', z);\n }\n /**\n * In JSON format, the `Timestamp` type is encoded as a string\n * in the RFC 3339 format.\n */\n internalJsonRead(\n json: JsonValue,\n options: JsonReadOptions,\n target?: Timestamp\n ): Timestamp {\n if (typeof json !== 'string')\n throw new Error(\n 'Unable to parse Timestamp from JSON ' + typeofJsonValue(json) + '.'\n );\n let matches = json.match(\n /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/\n );\n if (!matches)\n throw new Error('Unable to parse Timestamp from JSON. Invalid format.');\n let ms = Date.parse(\n matches[1] +\n '-' +\n matches[2] +\n '-' +\n matches[3] +\n 'T' +\n matches[4] +\n ':' +\n matches[5] +\n ':' +\n matches[6] +\n (matches[8] ? matches[8] : 'Z')\n );\n if (Number.isNaN(ms))\n throw new Error('Unable to parse Timestamp from JSON. Invalid value.');\n if (\n ms < Date.parse('0001-01-01T00:00:00Z') ||\n ms > Date.parse('9999-12-31T23:59:59Z')\n )\n throw new globalThis.Error(\n 'Unable to parse Timestamp from JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.'\n );\n if (!target) target = this.create();\n target.seconds = PbLong.from(ms / 1000).toBigInt();\n target.nanos = 0;\n if (matches[7])\n target.nanos =\n parseInt('1' + matches[7] + '0'.repeat(9 - matches[7].length)) -\n 1000000000;\n return target;\n }\n create(value?: PartialMessage<Timestamp>): Timestamp {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.seconds = 0n;\n message.nanos = 0;\n if (value !== undefined)\n reflectionMergePartial<Timestamp>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: Timestamp\n ): Timestamp {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* int64 seconds */ 1:\n message.seconds = reader.int64().toBigInt();\n break;\n case /* int32 nanos */ 2:\n message.nanos = reader.int32();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: Timestamp,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* int64 seconds = 1; */\n if (message.seconds !== 0n)\n writer.tag(1, WireType.Varint).int64(message.seconds);\n /* int32 nanos = 2; */\n if (message.nanos !== 0)\n writer.tag(2, WireType.Varint).int32(message.nanos);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message google.protobuf.Timestamp\n */\nexport const Timestamp = new Timestamp$Type();\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\nimport { Timestamp } from '../../../../../../../google/protobuf/timestamp';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI\n */\nexport interface LsAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.ListItem\n */\nexport interface LsAPI_ListItem {\n /**\n * name of the item in storage, without any prefixes\n *\n * @generated from protobuf field: string name = 1;\n */\n name: string;\n /**\n * size of item in bytes\n * is always zero for directories (is_dir = true)\n *\n * @generated from protobuf field: uint64 size = 2;\n */\n size: bigint;\n /**\n * is_dir is true for item, that can have subitems.\n *\n * @generated from protobuf field: bool is_dir = 3;\n */\n isDir: boolean;\n /**\n * full_name is the name of item absolute to storage root.\n * it is <directory> + <name>\n * The <delimiter>, used in names, is storage-specific and is NOT guaranteed to be '/'.\n *\n * @generated from protobuf field: string full_name = 10;\n */\n fullName: string;\n /**\n * directory, the item is located in. The value here is always a prefix of name:\n * name.HasPrefix(directory) is always true.\n *\n * @generated from protobuf field: string directory = 11;\n */\n directory: string;\n /**\n * last_modified keeps the item last modification timestamp\n *\n * @generated from protobuf field: google.protobuf.Timestamp last_modified = 12;\n */\n lastModified?: Timestamp;\n /**\n * version of item in storage.\n * When storage supports versioning or provides checksums for the data stored,\n * the <version> field keeps that data.\n * If not - it keeps the any simple combination of item attributes, that helps to\n * detect if the contents of item has changed, e.g. <size>+<mtime>.\n * Anyway, client should not try to interpret this field, but should provide it to the Platform\n * in operations with given item (like BlobImportInternal) to help Platform with deduplication.\n *\n * @generated from protobuf field: string version = 13;\n */\n version: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.List\n */\nexport interface LsAPI_List {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Request\n */\nexport interface LsAPI_List_Request {\n /**\n * resource_id of 'LS/<Storage>' resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * location to list, absolute to storage root. Only items, that have <full_name> starting\n * from <location> are included into list response.\n *\n * @generated from protobuf field: string location = 2;\n */\n location: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Response\n */\nexport interface LsAPI_List_Response {\n /**\n * List of the full (absolute to storage root) names of items from storage.\n * E.g., for 'fs' storage each name will consist of names of all directories, where the\n * item is located, and the item name itself.\n * The delimiter, used in names, is storage-specific and is NOT guaranteed to be '/'.\n *\n * @generated from protobuf field: repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items = 1;\n */\n items: LsAPI_ListItem[];\n /**\n * delimiter is path separator, used in this storage. Client can use it to parse item names into parts,\n * to extract directory names.\n *\n * @generated from protobuf field: string delimiter = 2;\n */\n delimiter: string;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI$Type extends MessageType<LsAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI', []);\n }\n create(value?: PartialMessage<LsAPI>): LsAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<LsAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI\n ): LsAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: LsAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI\n */\nexport const LsAPI = new LsAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_ListItem$Type extends MessageType<LsAPI_ListItem> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.ListItem', [\n { no: 1, name: 'name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n {\n no: 2,\n name: 'size',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 3, name: 'is_dir', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },\n { no: 10, name: 'full_name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n { no: 11, name: 'directory', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n { no: 12, name: 'last_modified', kind: 'message', T: () => Timestamp },\n { no: 13, name: 'version', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<LsAPI_ListItem>): LsAPI_ListItem {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.name = '';\n message.size = 0n;\n message.isDir = false;\n message.fullName = '';\n message.directory = '';\n message.version = '';\n if (value !== undefined)\n reflectionMergePartial<LsAPI_ListItem>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_ListItem\n ): LsAPI_ListItem {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string name */ 1:\n message.name = reader.string();\n break;\n case /* uint64 size */ 2:\n message.size = reader.uint64().toBigInt();\n break;\n case /* bool is_dir */ 3:\n message.isDir = reader.bool();\n break;\n case /* string full_name */ 10:\n message.fullName = reader.string();\n break;\n case /* string directory */ 11:\n message.directory = reader.string();\n break;\n case /* google.protobuf.Timestamp last_modified */ 12:\n message.lastModified = Timestamp.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.lastModified\n );\n break;\n case /* string version */ 13:\n message.version = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: LsAPI_ListItem,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string name = 1; */\n if (message.name !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* uint64 size = 2; */\n if (message.size !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.size);\n /* bool is_dir = 3; */\n if (message.isDir !== false)\n writer.tag(3, WireType.Varint).bool(message.isDir);\n /* string full_name = 10; */\n if (message.fullName !== '')\n writer.tag(10, WireType.LengthDelimited).string(message.fullName);\n /* string directory = 11; */\n if (message.directory !== '')\n writer.tag(11, WireType.LengthDelimited).string(message.directory);\n /* google.protobuf.Timestamp last_modified = 12; */\n if (message.lastModified)\n Timestamp.internalBinaryWrite(\n message.lastModified,\n writer.tag(12, WireType.LengthDelimited).fork(),\n options\n ).join();\n /* string version = 13; */\n if (message.version !== '')\n writer.tag(13, WireType.LengthDelimited).string(message.version);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.ListItem\n */\nexport const LsAPI_ListItem = new LsAPI_ListItem$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_List$Type extends MessageType<LsAPI_List> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.List', []);\n }\n create(value?: PartialMessage<LsAPI_List>): LsAPI_List {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<LsAPI_List>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_List\n ): LsAPI_List {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: LsAPI_List,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.List\n */\nexport const LsAPI_List = new LsAPI_List$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_List_Request$Type extends MessageType<LsAPI_List_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.List.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'location', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<LsAPI_List_Request>): LsAPI_List_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.location = '';\n if (value !== undefined)\n reflectionMergePartial<LsAPI_List_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_List_Request\n ): LsAPI_List_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* string location */ 2:\n message.location = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: LsAPI_List_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* string location = 2; */\n if (message.location !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.location);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Request\n */\nexport const LsAPI_List_Request = new LsAPI_List_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_List_Response$Type extends MessageType<LsAPI_List_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.List.Response', [\n {\n no: 1,\n name: 'items',\n kind: 'message',\n repeat: 1 /*RepeatType.PACKED*/,\n T: () => LsAPI_ListItem\n },\n { no: 2, name: 'delimiter', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<LsAPI_List_Response>): LsAPI_List_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.items = [];\n message.delimiter = '';\n if (value !== undefined)\n reflectionMergePartial<LsAPI_List_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_List_Response\n ): LsAPI_List_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items */ 1:\n message.items.push(\n LsAPI_ListItem.internalBinaryRead(reader, reader.uint32(), options)\n );\n break;\n case /* string delimiter */ 2:\n message.delimiter = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: LsAPI_List_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items = 1; */\n for (let i = 0; i < message.items.length; i++)\n LsAPI_ListItem.internalBinaryWrite(\n message.items[i],\n writer.tag(1, WireType.LengthDelimited).fork(),\n options\n ).join();\n /* string delimiter = 2; */\n if (message.delimiter !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.delimiter);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Response\n */\nexport const LsAPI_List_Response = new LsAPI_List_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.LS\n */\nexport const LS = new ServiceType('MiLaboratories.Controller.Shared.LS', [\n { name: 'List', options: {}, I: LsAPI_List_Request, O: LsAPI_List_Response }\n]);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { LS } from './protocol';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { LsAPI_List_Response } from './protocol';\nimport type { LsAPI_List_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * LS provides access to lists of blobs (files, S3 objects and so on) is some storage.\n * This API allows clients to know, whan items are available in storages, that\n * the contorllers can access, providing clients with the ability to start indexation\n * on, say, existing sequence files from the corporate storage.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.LS\n */\nexport interface ILSClient {\n /**\n * @generated from protobuf rpc: List(MiLaboratories.Controller.Shared.LsAPI.List.Request) returns (MiLaboratories.Controller.Shared.LsAPI.List.Response);\n */\n list(\n input: LsAPI_List_Request,\n options?: RpcOptions\n ): UnaryCall<LsAPI_List_Request, LsAPI_List_Response>;\n}\n/**\n *\n * LS provides access to lists of blobs (files, S3 objects and so on) is some storage.\n * This API allows clients to know, whan items are available in storages, that\n * the contorllers can access, providing clients with the ability to start indexation\n * on, say, existing sequence files from the corporate storage.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.LS\n */\nexport class LSClient implements ILSClient, ServiceInfo {\n typeName = LS.typeName;\n methods = LS.methods;\n options = LS.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * @generated from protobuf rpc: List(MiLaboratories.Controller.Shared.LsAPI.List.Request) returns (MiLaboratories.Controller.Shared.LsAPI.List.Response);\n */\n list(\n input: LsAPI_List_Request,\n options?: RpcOptions\n ): UnaryCall<LsAPI_List_Request, LsAPI_List_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<LsAPI_List_Request, LsAPI_List_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n}\n","import { MiLogger } from '@milaboratories/ts-helpers';\nimport type { LsAPI_List_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol';\nimport { LSClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLs {\n private readonly grpcClient: LSClient;\n\n constructor(\n grpcTransport: GrpcTransport,\n private readonly logger: MiLogger\n ) {\n this.grpcClient = new LSClient(grpcTransport);\n }\n\n close() {}\n\n public async list(\n rInfo: ResourceInfo,\n path: string,\n options?: RpcOptions\n ): Promise<LsAPI_List_Response> {\n return await this.grpcClient.list(\n {\n resourceId: rInfo.id,\n location: path\n },\n addRTypeToMetadata(rInfo.type, options)\n ).response;\n }\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI\n */\nexport interface StreamingAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary\n */\nexport interface StreamingAPI_StreamBinary {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the data.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <chunk_size> limits the maximum size of <data> for each response message in stream.\n *\n * Default value: 32 768 (32 KiB)\n * Max value: 3900 * 1024 (3.9 MiB)\n *\n * @generated from protobuf field: optional uint32 chunk_size = 11;\n */\n chunkSize?: number;\n /**\n * <read_limit> allows client to limit total data sent from server.\n * This limit is aggregation of all data, sent in all chunks.\n * E.g. to read 2000 bytes of data in chunks of at most\n * 130 bytes, use <chunk_size> = 130; <read_limit> = 2000.\n * For storage item of appropriate size this settings will result in\n * 16 messages from server: 15 of 130 bytes and one of 50 bytes.\n *\n * @generated from protobuf field: optional int64 read_limit = 20;\n */\n readLimit?: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary\n */\nexport interface StreamingAPI_ReadBinary {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the data.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <chunk_size> limits the maximum size of <data> for response message in stream.\n *\n * Default value: 32 768 (32 KiB)\n * Max value: 3900 * 1024 (3.9 MiB)\n *\n * @generated from protobuf field: optional uint32 chunk_size = 11;\n */\n chunkSize?: number;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamText\n */\nexport interface StreamingAPI_StreamText {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the contents.\n * This offset is taken in BYTES, as it eases streaming recovery after client reconnection or controller restart.\n * Client can just use the <new_offset> value of the last response from server to continue streaming after reconnection.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <read_limit> allows client to limit total data sent from server.\n * This limit is aggregation of all data, sent in all chunks, measured\n * in lines of text.\n * E.g. to read top 1000 lines from stream source, use <read_limit> = 1000.\n * When both <read_limit> and <search>/<search_re> are set, the <read_limit> is applied first.\n * this is equivalent to 'head -n <read_limit> | grep <search>'.\n *\n * @generated from protobuf field: optional int64 read_limit = 20;\n */\n readLimit?: bigint;\n /**\n * <search> is substring for line search pattern.\n * This option makes controller to send to the client only lines, that\n * have given substring.\n *\n * @generated from protobuf field: optional string search = 21;\n */\n search?: string;\n /**\n * <search_re> is regular expression for line search pattern.\n * This option makes controller to send to the client only lines, that\n * match given regular expression.\n *\n * @generated from protobuf field: optional string search_re = 22;\n */\n searchRe?: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadText\n */\nexport interface StreamingAPI_ReadText {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the contents.\n * This offset is taken in BYTES, as it eases streaming recovery after client reconnection or controller restart.\n * Client can just use the <new_offset> value of the last response from server to continue streaming after reconnection.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <read_limit> allows client to limit total data sent from server.\n * Measured in lines of text.\n * E.g. to read top 1000 lines from stream source, use <read_limit> = 1000.\n * When both <read_limit> and <search>/<search_re> are set, the <read_limit> is applied first.\n * this is equivalent to 'head -n <read_limit> | grep <search>'.\n * At most 3.9 MiB (3900 * 1024 KiB) of data is returned in single read regardless of <read_limit> option\n * Only full lines of text are returned except for the last line from the completed source\n * (the one that is not expected to have new data, like blob in storage)\n *\n * @generated from protobuf field: optional int64 read_limit = 20;\n */\n readLimit?: bigint;\n /**\n * <search> is substring for line search pattern.\n * This option makes controller to send to the client only lines, that\n * have given substring.\n *\n * @generated from protobuf field: optional string search = 21;\n */\n search?: string;\n /**\n * <search_re> is regular expression for line search pattern.\n * This option makes controller to send to the client only lines, that\n * match given regular expression.\n *\n * @generated from protobuf field: optional string search_re = 22;\n */\n searchRe?: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.LastLines\n */\nexport interface StreamingAPI_LastLines {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the contents.\n * This offset is taken in BYTES, as it eases streaming recovery after client reconnection or controller restart.\n * By default, LastLines starts to treat the data source from the very last byte available in data stream\n * at the moment of call, but client can set the server to start from earlier position.\n *\n * @generated from protobuf field: optional int64 offset = 2;\n */\n offset?: bigint;\n /**\n * <line_count> makes streamer to return up to <line_count> lines to the client.\n * Default value: 1\n *\n * @generated from protobuf field: optional int32 line_count = 3;\n */\n lineCount?: number;\n /**\n * <search> is substring for line search pattern.\n * This option makes controller to send to the client only lines, that\n * have given substring.\n *\n * @generated from protobuf field: optional string search = 21;\n */\n search?: string;\n /**\n * <search_re> is regular expression for line search pattern.\n * This option makes controller to send to the client only lines, that\n * match given regular expression.\n *\n * @generated from protobuf field: optional string search_re = 22;\n */\n searchRe?: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.Response\n */\nexport interface StreamingAPI_Response {\n /**\n * data chunk from item, starting from the <new_offset> of the previous message in the same stream.\n *\n * @generated from protobuf field: bytes data = 1;\n */\n data: Uint8Array;\n /**\n * <size> is the actual size of the streamed item at the moment of this message.\n * This might be not a final amount of streamed data, as stream source can be updated\n * by other independent process (e.g., data is written to log file).\n * This field in combination with <new_offset> shows, how far the client is from the end\n * of the data right now.\n *\n * @generated from protobuf field: uint64 size = 2;\n */\n size: bigint;\n /**\n * <new_offset> is the new offset in bytes from the start of the streamed item,\n * including size of <data> in current response.\n * Call to Stream rpc with <offset> = <new_offset> will continue\n * streaming from the place of last received message\n * (e.g. <offset> = <new_offset> - 1 will repeat the last byte of\n * previously received <data>)\n *\n * @generated from protobuf field: uint64 new_offset = 3;\n */\n newOffset: bigint;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI$Type extends MessageType<StreamingAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI', []);\n }\n create(value?: PartialMessage<StreamingAPI>): StreamingAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI\n ): StreamingAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: StreamingAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI\n */\nexport const StreamingAPI = new StreamingAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_StreamBinary$Type extends MessageType<StreamingAPI_StreamBinary> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 11,\n name: 'chunk_size',\n kind: 'scalar',\n opt: true,\n T: 13 /*ScalarType.UINT32*/\n },\n {\n no: 20,\n name: 'read_limit',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_StreamBinary>\n ): StreamingAPI_StreamBinary {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_StreamBinary>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_StreamBinary\n ): StreamingAPI_StreamBinary {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional uint32 chunk_size */ 11:\n message.chunkSize = reader.uint32();\n break;\n case /* optional int64 read_limit */ 20:\n message.readLimit = reader.int64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_StreamBinary,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional uint32 chunk_size = 11; */\n if (message.chunkSize !== undefined)\n writer.tag(11, WireType.Varint).uint32(message.chunkSize);\n /* optional int64 read_limit = 20; */\n if (message.readLimit !== undefined)\n writer.tag(20, WireType.Varint).int64(message.readLimit);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary\n */\nexport const StreamingAPI_StreamBinary = new StreamingAPI_StreamBinary$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_ReadBinary$Type extends MessageType<StreamingAPI_ReadBinary> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 11,\n name: 'chunk_size',\n kind: 'scalar',\n opt: true,\n T: 13 /*ScalarType.UINT32*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_ReadBinary>\n ): StreamingAPI_ReadBinary {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_ReadBinary>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_ReadBinary\n ): StreamingAPI_ReadBinary {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional uint32 chunk_size */ 11:\n message.chunkSize = reader.uint32();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_ReadBinary,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional uint32 chunk_size = 11; */\n if (message.chunkSize !== undefined)\n writer.tag(11, WireType.Varint).uint32(message.chunkSize);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary\n */\nexport const StreamingAPI_ReadBinary = new StreamingAPI_ReadBinary$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_StreamText$Type extends MessageType<StreamingAPI_StreamText> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.StreamText', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 20,\n name: 'read_limit',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 21,\n name: 'search',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 22,\n name: 'search_re',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_StreamText>\n ): StreamingAPI_StreamText {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_StreamText>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_StreamText\n ): StreamingAPI_StreamText {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional int64 read_limit */ 20:\n message.readLimit = reader.int64().toBigInt();\n break;\n case /* optional string search */ 21:\n message.search = reader.string();\n break;\n case /* optional string search_re */ 22:\n message.searchRe = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_StreamText,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional int64 read_limit = 20; */\n if (message.readLimit !== undefined)\n writer.tag(20, WireType.Varint).int64(message.readLimit);\n /* optional string search = 21; */\n if (message.search !== undefined)\n writer.tag(21, WireType.LengthDelimited).string(message.search);\n /* optional string search_re = 22; */\n if (message.searchRe !== undefined)\n writer.tag(22, WireType.LengthDelimited).string(message.searchRe);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamText\n */\nexport const StreamingAPI_StreamText = new StreamingAPI_StreamText$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_ReadText$Type extends MessageType<StreamingAPI_ReadText> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.ReadText', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 20,\n name: 'read_limit',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 21,\n name: 'search',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 22,\n name: 'search_re',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_ReadText>): StreamingAPI_ReadText {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_ReadText>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_ReadText\n ): StreamingAPI_ReadText {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional int64 read_limit */ 20:\n message.readLimit = reader.int64().toBigInt();\n break;\n case /* optional string search */ 21:\n message.search = reader.string();\n break;\n case /* optional string search_re */ 22:\n message.searchRe = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_ReadText,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional int64 read_limit = 20; */\n if (message.readLimit !== undefined)\n writer.tag(20, WireType.Varint).int64(message.readLimit);\n /* optional string search = 21; */\n if (message.search !== undefined)\n writer.tag(21, WireType.LengthDelimited).string(message.search);\n /* optional string search_re = 22; */\n if (message.searchRe !== undefined)\n writer.tag(22, WireType.LengthDelimited).string(message.searchRe);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadText\n */\nexport const StreamingAPI_ReadText = new StreamingAPI_ReadText$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_LastLines$Type extends MessageType<StreamingAPI_LastLines> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.LastLines', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'line_count',\n kind: 'scalar',\n opt: true,\n T: 5 /*ScalarType.INT32*/\n },\n {\n no: 21,\n name: 'search',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 22,\n name: 'search_re',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_LastLines>\n ): StreamingAPI_LastLines {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_LastLines>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_LastLines\n ): StreamingAPI_LastLines {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* optional int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional int32 line_count */ 3:\n message.lineCount = reader.int32();\n break;\n case /* optional string search */ 21:\n message.search = reader.string();\n break;\n case /* optional string search_re */ 22:\n message.searchRe = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_LastLines,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* optional int64 offset = 2; */\n if (message.offset !== undefined)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional int32 line_count = 3; */\n if (message.lineCount !== undefined)\n writer.tag(3, WireType.Varint).int32(message.lineCount);\n /* optional string search = 21; */\n if (message.search !== undefined)\n writer.tag(21, WireType.LengthDelimited).string(message.search);\n /* optional string search_re = 22; */\n if (message.searchRe !== undefined)\n writer.tag(22, WireType.LengthDelimited).string(message.searchRe);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.LastLines\n */\nexport const StreamingAPI_LastLines = new StreamingAPI_LastLines$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_Response$Type extends MessageType<StreamingAPI_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.Response', [\n { no: 1, name: 'data', kind: 'scalar', T: 12 /*ScalarType.BYTES*/ },\n {\n no: 2,\n name: 'size',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'new_offset',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_Response>): StreamingAPI_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.data = new Uint8Array(0);\n message.size = 0n;\n message.newOffset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_Response\n ): StreamingAPI_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* bytes data */ 1:\n message.data = reader.bytes();\n break;\n case /* uint64 size */ 2:\n message.size = reader.uint64().toBigInt();\n break;\n case /* uint64 new_offset */ 3:\n message.newOffset = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* bytes data = 1; */\n if (message.data.length)\n writer.tag(1, WireType.LengthDelimited).bytes(message.data);\n /* uint64 size = 2; */\n if (message.size !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.size);\n /* uint64 new_offset = 3; */\n if (message.newOffset !== 0n)\n writer.tag(3, WireType.Varint).uint64(message.newOffset);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.Response\n */\nexport const StreamingAPI_Response = new StreamingAPI_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Streaming\n */\nexport const Streaming = new ServiceType(\n 'MiLaboratories.Controller.Shared.Streaming',\n [\n {\n name: 'StreamBinary',\n serverStreaming: true,\n options: {},\n I: StreamingAPI_StreamBinary,\n O: StreamingAPI_Response\n },\n {\n name: 'ReadBinary',\n options: {},\n I: StreamingAPI_ReadBinary,\n O: StreamingAPI_Response\n },\n {\n name: 'StreamText',\n serverStreaming: true,\n options: {},\n I: StreamingAPI_StreamText,\n O: StreamingAPI_Response\n },\n {\n name: 'ReadText',\n options: {},\n I: StreamingAPI_ReadText,\n O: StreamingAPI_Response\n },\n {\n name: 'LastLines',\n options: {},\n I: StreamingAPI_LastLines,\n O: StreamingAPI_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Streaming } from './protocol';\nimport type { StreamingAPI_LastLines } from './protocol';\nimport type { StreamingAPI_ReadText } from './protocol';\nimport type { StreamingAPI_StreamText } from './protocol';\nimport type { StreamingAPI_ReadBinary } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { StreamingAPI_Response } from './protocol';\nimport type { StreamingAPI_StreamBinary } from './protocol';\nimport type { ServerStreamingCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Streaming provides access to online data stream from item in storage. Whenever item is appended with data,\n * the caller receives this fresh data in stream from server.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Streaming\n */\nexport interface IStreamingClient {\n /**\n * StreamBinary provides stream of binary file. Each response message keeps\n * one single chunk of binary data from data source. See StreamingAPI.Binary message\n * for more info on available options.\n *\n * @generated from protobuf rpc: StreamBinary(MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamBinary(\n input: StreamingAPI_StreamBinary,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamBinary, StreamingAPI_Response>;\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadBinary(MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readBinary(\n input: StreamingAPI_ReadBinary,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadBinary, StreamingAPI_Response>;\n /**\n * StreamText provides stream of textual file, splitting the data by newline symbol.\n * Each response message keeps one single line of text from data source.\n *\n * @generated from protobuf rpc: StreamText(MiLaboratories.Controller.Shared.StreamingAPI.StreamText) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamText(\n input: StreamingAPI_StreamText,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamText, StreamingAPI_Response>;\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadText(MiLaboratories.Controller.Shared.StreamingAPI.ReadText) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readText(\n input: StreamingAPI_ReadText,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadText, StreamingAPI_Response>;\n /**\n * LastLines provides single message with the last lines from data source.\n * When search pattern is specified, the last lines matching the given pattern are returned.\n * The lines are returned in reversed order, as server reads data source from the end.\n * Consider it as equivalent to 'tac <file> | grep <search> | head -n <line_count>'\n * The <new_offset> returned in the response points to the _beginning_ of the last\n * line found, so client can continue reading the file backwards in subsequent calls.\n * This means, that use of this <new_offset> in ReadText() will return you the same line\n * returned last in LastLines() data.\n *\n * @generated from protobuf rpc: LastLines(MiLaboratories.Controller.Shared.StreamingAPI.LastLines) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n lastLines(\n input: StreamingAPI_LastLines,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_LastLines, StreamingAPI_Response>;\n}\n/**\n *\n * Streaming provides access to online data stream from item in storage. Whenever item is appended with data,\n * the caller receives this fresh data in stream from server.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Streaming\n */\nexport class StreamingClient implements IStreamingClient, ServiceInfo {\n typeName = Streaming.typeName;\n methods = Streaming.methods;\n options = Streaming.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * StreamBinary provides stream of binary file. Each response message keeps\n * one single chunk of binary data from data source. See StreamingAPI.Binary message\n * for more info on available options.\n *\n * @generated from protobuf rpc: StreamBinary(MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamBinary(\n input: StreamingAPI_StreamBinary,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamBinary, StreamingAPI_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamBinary, StreamingAPI_Response>(\n 'serverStreaming',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadBinary(MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readBinary(\n input: StreamingAPI_ReadBinary,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadBinary, StreamingAPI_Response> {\n const method = this.methods[1],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadBinary, StreamingAPI_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * StreamText provides stream of textual file, splitting the data by newline symbol.\n * Each response message keeps one single line of text from data source.\n *\n * @generated from protobuf rpc: StreamText(MiLaboratories.Controller.Shared.StreamingAPI.StreamText) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamText(\n input: StreamingAPI_StreamText,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamText, StreamingAPI_Response> {\n const method = this.methods[2],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamText, StreamingAPI_Response>(\n 'serverStreaming',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadText(MiLaboratories.Controller.Shared.StreamingAPI.ReadText) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readText(\n input: StreamingAPI_ReadText,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadText, StreamingAPI_Response> {\n const method = this.methods[3],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadText, StreamingAPI_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * LastLines provides single message with the last lines from data source.\n * When search pattern is specified, the last lines matching the given pattern are returned.\n * The lines are returned in reversed order, as server reads data source from the end.\n * Consider it as equivalent to 'tac <file> | grep <search> | head -n <line_count>'\n * The <new_offset> returned in the response points to the _beginning_ of the last\n * line found, so client can continue reading the file backwards in subsequent calls.\n * This means, that use of this <new_offset> in ReadText() will return you the same line\n * returned last in LastLines() data.\n *\n * @generated from protobuf rpc: LastLines(MiLaboratories.Controller.Shared.StreamingAPI.LastLines) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n lastLines(\n input: StreamingAPI_LastLines,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_LastLines, StreamingAPI_Response> {\n const method = this.methods[4],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_LastLines, StreamingAPI_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n}\n","import { StreamingClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { MiLogger, notEmpty } from '@milaboratories/ts-helpers';\nimport { Dispatcher } from 'undici';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLogs {\n public readonly grpcClient: StreamingClient;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger\n ) {\n this.grpcClient = new StreamingClient(this.grpcTransport);\n }\n\n close() {}\n\n /** Reads text back and returns the text,\n * the new offset\n * and the total size of the (currently existing) file. */\n public async lastLines(\n { id: rId, type: rType }: ResourceInfo,\n lineCount: number,\n offsetBytes: bigint = 0n, // if 0n, then start from the end.\n searchStr?: string,\n options?: RpcOptions\n ): Promise<StreamingAPI_Response> {\n return (\n await this.grpcClient.lastLines(\n {\n resourceId: rId,\n lineCount: lineCount,\n offset: offsetBytes,\n search: searchStr\n },\n addRTypeToMetadata(rType, options)\n )\n ).response;\n }\n\n /** Reads the file forward and returns the text,\n * the new offset\n * and the total size of the (currently existing) file. */\n public async readText(\n { id: rId, type: rType }: ResourceInfo,\n lineCount: number,\n offsetBytes: bigint = 0n, // if 0n, then start from the beginning.\n searchStr?: string,\n options?: RpcOptions\n ): Promise<StreamingAPI_Response> {\n return (\n await this.grpcClient.readText(\n {\n resourceId: notEmpty(rId),\n readLimit: BigInt(lineCount),\n offset: offsetBytes,\n search: searchStr\n },\n addRTypeToMetadata(rType, options)\n )\n ).response;\n }\n}\n","import { PlClient } from '@milaboratories/pl-client';\nimport { MiLogger } from '@milaboratories/ts-helpers';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport { Dispatcher } from 'undici';\nimport { ClientDownload } from './download';\nimport { ClientLogs } from './logs';\nimport { ClientProgress } from './progress';\nimport { ClientUpload } from './upload';\nimport { ClientLs } from './ls_api';\nimport { LocalStorageProjection } from '../drivers/types';\n\nexport function createDownloadClient(\n logger: MiLogger,\n client: PlClient,\n localProjections: LocalStorageProjection[]\n) {\n return client.getDriver({\n name: 'DownloadBlob',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientDownload(grpcTransport, httpDispatcher, logger, localProjections)\n });\n}\n\nexport function createLogsClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'StreamLogs',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientLogs(grpcTransport, httpDispatcher, logger)\n });\n}\n\nexport function createUploadProgressClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadProgress',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientProgress(grpcTransport, httpDispatcher, client, logger)\n });\n}\n\nexport function createUploadBlobClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadBlob',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientUpload(grpcTransport, httpDispatcher, client, logger)\n });\n}\n\nexport function createLsFilesClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'LsFiles',\n init: (_client: PlClient, grpcTransport: GrpcTransport, _httpDispatcher: Dispatcher) =>\n new ClientLs(grpcTransport, logger)\n });\n}\n","import type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { ClientLogs } from '../../clients/logs';\nimport {\n PlClient,\n ResourceId,\n BasicResourceData,\n isNullResourceId,\n valErr,\n getField\n} from '@milaboratories/pl-client';\nimport { scheduler } from 'node:timers/promises';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\n// TODO: remove this when we switch to refreshState.\n\n/** It's an Updater but for tasks that happens in a while loop with sleeping between. */\nexport class LongUpdater {\n private updater: Updater;\n\n constructor(\n private readonly onUpdate: () => Promise<boolean>,\n private readonly sleepMs: number\n ) {\n this.updater = new Updater(async () => {\n while (true) {\n const done = await this.onUpdate();\n if (done) return;\n await scheduler.wait(this.sleepMs);\n }\n });\n }\n\n schedule = () => this.updater.schedule();\n}\n\n/** Updater incorporates a pattern when someone wants to run a callback\n * that updates something only when it's not already running. */\nexport class Updater {\n private updating: Promise<void> | undefined;\n\n constructor(private readonly onUpdate: () => Promise<void>) {}\n\n schedule() {\n if (this.updating == undefined) {\n this.updating = (async () => {\n try {\n await this.onUpdate();\n } catch (e) {\n console.log(`error while updating in Updater: ${e}`);\n } finally {\n this.updating = undefined;\n }\n })();\n }\n }\n}\n\n// TODO: remove all the code below to the computable that calculates Mixcr logs.\n\nexport async function getStream(\n client: PlClient,\n streamManagerId: ResourceId\n): Promise<BasicResourceData | undefined> {\n return client.withReadTx('LogsDriverGetStream', async (tx) => {\n const sm = await tx.getResourceData(streamManagerId, true);\n const stream = await valErr(tx, getField(sm, 'stream'));\n if (stream.error != '') {\n throw new Error(`while getting stream: ${stream.error}`);\n }\n if (isNullResourceId(stream.valueId)) return undefined;\n\n return await tx.getResourceData(stream.valueId, false);\n });\n}\n\nexport type MixcrProgressResponse = { found: false } | ({ found: true } & MixcrProgressLine);\n\nexport type MixcrProgressLine = {\n stage: string; // Building pre-clones from tag groups\n progress: string; // 35.3%\n eta: string; // ETA: 00:00:07\n};\n\n/** Is set by a template code.\n * Mixcr adds this prefix to every log line that contains a progress. */\nconst mixcrProgressPrefix = '8C7#F1328%9E089B3D22';\nconst mixcrProgressRegex = /(?<stage>.*):\\s*(?<progress>[\\d.]+%)\\s.*(?<eta>ETA:.*)/g;\n\nexport function lineToProgress(line: string): MixcrProgressLine | undefined {\n const noPrefix = line.replace(mixcrProgressPrefix, '');\n const parsed = noPrefix.match(mixcrProgressRegex);\n\n if (parsed == null || parsed.length != 4) {\n return undefined;\n }\n\n const [_, stage, progress, eta] = parsed;\n\n return {\n stage, // For example, 'Building pre-clones from tag groups'\n progress, // 35.3%\n eta // ETA: 00:00:07\n };\n}\n\nexport async function mixcrProgressFromLogs(\n rInfo: ResourceInfo,\n client: ClientLogs,\n options?: RpcOptions\n): Promise<MixcrProgressResponse> {\n const lastLines = await client.lastLines(rInfo, 1, 0n, mixcrProgressPrefix, options);\n if (lastLines.data == null || lastLines.data.length == 0) {\n return { found: false };\n }\n\n const line = lastLines.data.toString().split(/\\r?\\n/)[0];\n if (line == undefined) {\n return { found: false };\n }\n\n const progress = lineToProgress(line);\n if (progress === undefined) {\n return { found: false };\n }\n\n return { found: true, ...progress };\n}\n","import { CallersCounter, mapEntries, mapGet } from '@milaboratories/ts-helpers';\n\ntype PathLike = string;\n\nexport interface CachedFile {\n sizeBytes: number;\n path: PathLike;\n counter: CallersCounter;\n}\n\n/** Holds counters of how many callers need the file.\n * If some counters become zero and a cache size exceeds a soft limit,\n * remove not needed blobs one by one.\n * If all the files are needed, do nothing. */\nexport class FilesCache<T extends CachedFile> {\n private cache: Map<PathLike, T> = new Map();\n private totalSizeBytes: number = 0;\n\n constructor(private readonly softSizeBytes: number) {}\n\n existsFile(path: PathLike): boolean {\n return this.cache.get(path) != undefined;\n }\n\n getFile(path: PathLike, callerId: string): T | undefined {\n const file = this.cache.get(path);\n if (file != undefined) {\n file.counter.inc(callerId);\n }\n\n return file;\n }\n\n /** Decrements a counter in a cache and if we exceeds\n * a soft limit, removes files with zero counters. */\n removeFile(path: PathLike, callerId: string): T[] {\n mapGet(this.cache, path).counter.dec(callerId);\n return this.toDelete();\n }\n\n /** Returns what results should be deleted to comply with the soft limit. */\n toDelete(): T[] {\n if (this.totalSizeBytes <= this.softSizeBytes) return [];\n\n const result: T[] = [];\n let freedBytes = 0;\n\n mapEntries(this.cache)\n .filter(([_, file]: [string, T]) => file.counter.isZero())\n .forEach(([path, _]) => {\n if (this.totalSizeBytes - freedBytes <= this.softSizeBytes) return;\n const file = mapGet(this.cache, path);\n freedBytes += file.sizeBytes;\n result.push(file);\n });\n\n return result;\n }\n\n addCache(file: T, callerId: string) {\n const created = this.cache.get(file.path) == undefined;\n this.cache.set(file.path, file);\n file.counter.inc(callerId);\n\n if (file.sizeBytes < 0) throw new Error(`empty sizeBytes: ${file}`);\n\n if (created) this.totalSizeBytes += file.sizeBytes;\n }\n\n removeCache(file: T) {\n this.cache.delete(file.path);\n this.totalSizeBytes -= file.sizeBytes;\n }\n}\n","import { Computable, ComputableCtx } from '@milaboratories/computable';\nimport { PlTreeEntry, ResourceInfo } from '@milaboratories/pl-tree';\nimport { bigintToResourceId, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport { LogsStreamDriver } from './logs_stream';\nimport { DownloadDriver } from './download_and_logs_blob';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { ConsoleLoggerAdapter, MiLogger } from '@milaboratories/ts-helpers';\n\nexport class LogsDriver implements sdk.LogsDriver {\n constructor(\n private readonly logger: MiLogger,\n private readonly logsStreamDriver: LogsStreamDriver,\n private readonly downloadDriver: DownloadDriver\n ) {}\n\n /** Returns all logs and schedules a job that reads remain logs.\n * Notifies when a new portion of the log appeared. */\n getLastLogs(res: PlTreeEntry, lines: number): Computable<string | undefined>;\n getLastLogs(res: PlTreeEntry, lines: number, ctx: ComputableCtx): Computable<string | undefined>;\n getLastLogs(\n res: PlTreeEntry,\n lines: number,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getLastLogs(res, lines, ctx));\n\n const stream = streamManagerGetStream(ctx, res);\n if (stream === undefined) {\n ctx.markUnstable('no stream in stream manager');\n return undefined;\n }\n\n if (isBlob(stream)) return this.downloadDriver.getLastLogs(stream, lines, ctx);\n\n try {\n return this.logsStreamDriver.getLastLogs(stream, lines, ctx);\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n ctx.markUnstable(`NOT_FOUND in logs stream driver while getting last logs: ${e}`);\n return undefined;\n }\n throw e;\n }\n }\n\n /** Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLog(res: PlTreeEntry, patternToSearch: string): Computable<string | undefined>;\n getProgressLog(res: PlTreeEntry, patternToSearch: string, ctx: ComputableCtx): string | undefined;\n getProgressLog(\n res: PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx === undefined)\n return Computable.make((ctx) => this.getProgressLog(res, patternToSearch, ctx));\n\n const stream = streamManagerGetStream(ctx, res);\n if (stream === undefined) {\n ctx.markUnstable('no stream in stream manager');\n return undefined;\n }\n\n if (isBlob(stream)) return this.downloadDriver.getProgressLog(stream, patternToSearch, ctx);\n\n try {\n return this.logsStreamDriver.getProgressLog(stream, patternToSearch, ctx);\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n ctx.markUnstable(`NOT_FOUND in logs stream driver while getting a progress log: ${e}`);\n return undefined;\n }\n throw e;\n }\n }\n\n /** Returns an Id of a smart object, that can read logs directly from\n * the platform. */\n getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<sdk.AnyLogHandle | undefined>;\n getLogHandle(res: PlTreeEntry, ctx: ComputableCtx): sdk.AnyLogHandle | undefined;\n getLogHandle(\n res: PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<sdk.AnyLogHandle | undefined> | sdk.AnyLogHandle | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getLogHandle(res, ctx));\n\n const stream = streamManagerGetStream(ctx, res);\n if (stream === undefined) {\n ctx.markUnstable('no stream in stream manager');\n return undefined;\n }\n\n if (isBlob(stream)) return this.downloadDriver.getLogHandle(stream, ctx);\n\n return this.logsStreamDriver.getLogHandle(stream, ctx);\n }\n\n async lastLines(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string\n ): Promise<sdk.StreamingApiResponse> {\n if (isLiveLogHandle(handle))\n return await this.logsStreamDriver.lastLines(handle, lineCount, offsetBytes, searchStr);\n return await this.downloadDriver.lastLines(handle, lineCount, offsetBytes, searchStr);\n }\n\n async readText(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string\n ): Promise<sdk.StreamingApiResponse> {\n if (isLiveLogHandle(handle))\n return await this.logsStreamDriver.readText(handle, lineCount, offsetBytes, searchStr);\n return await this.downloadDriver.readText(handle, lineCount, offsetBytes, searchStr);\n }\n}\n\nfunction isBlob(rInfo: ResourceInfo) {\n return !rInfo.type.name.startsWith('StreamWorkdir');\n}\n\nfunction streamManagerGetStream(ctx: ComputableCtx, manager: PlTreeEntry) {\n return ctx.accessor(manager).node().traverse('stream')?.resourceInfo;\n}\n\nexport function handleToData(handle: sdk.AnyLogHandle): ResourceInfo {\n let parsed: RegExpMatchArray | null;\n\n if (isLiveLogHandle(handle)) {\n parsed = handle.match(liveHandleRegex);\n } else if (isReadyLogHandle(handle)) {\n parsed = handle.match(readyHandleRegex);\n } else throw new Error(`Log handle is malformed: ${handle}`);\n if (parsed == null) throw new Error(`Log handle wasn't parsed: ${handle}`);\n\n const { resourceType, resourceVersion, resourceId } = parsed.groups!;\n\n return {\n id: bigintToResourceId(BigInt(resourceId)),\n type: { name: resourceType, version: resourceVersion }\n };\n}\n\nexport function dataToHandle(live: boolean, rInfo: ResourceInfo): sdk.AnyLogHandle {\n if (live) {\n return `log+live://log/${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}` as sdk.LiveLogHandle;\n }\n\n return `log+ready://log/${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}` as sdk.ReadyLogHandle;\n}\n\nconst liveHandleRegex =\n /^log\\+live:\\/\\/log\\/(?<resourceType>.*)\\/(?<resourceVersion>.*)\\/(?<resourceId>.*)$/;\n\nexport function isLiveLogHandle(handle: string): handle is sdk.LiveLogHandle {\n return liveHandleRegex.test(handle);\n}\n\nconst readyHandleRegex =\n /^log\\+ready:\\/\\/log\\/(?<resourceType>.*)\\/(?<resourceVersion>.*)\\/(?<resourceId>.*)$/;\n\nexport function isReadyLogHandle(handle: string): handle is sdk.ReadyLogHandle {\n return readyHandleRegex.test(handle);\n}\n","import {\n ChangeSource,\n Computable,\n ComputableCtx,\n ComputableStableDefined,\n Watcher\n} from '@milaboratories/computable';\nimport { bigintToResourceId, ResourceId } from '@milaboratories/pl-client';\nimport {\n CallersCounter,\n MiLogger,\n TaskProcessor,\n Signer,\n ValueOrError\n} from '@milaboratories/ts-helpers';\nimport * as fsp from 'node:fs/promises';\nimport * as fs from 'fs';\nimport * as path from 'node:path';\nimport { Writable } from 'node:stream';\nimport { ClientDownload, UnknownStorageError, WrongLocalFileUrl } from '../clients/download';\nimport { ClientLogs } from '../clients/logs';\nimport * as helper from './helpers/helpers';\nimport * as readline from 'node:readline/promises';\nimport Denque from 'denque';\nimport * as os from 'node:os';\nimport { FilesCache } from './helpers/files_cache';\nimport { randomUUID } from 'node:crypto';\nimport { buffer } from 'node:stream/consumers';\nimport { Readable } from 'node:stream';\nimport {\n InferSnapshot,\n ResourceInfo,\n PlTreeEntry,\n ResourceWithMetadata,\n rsSchema,\n makeResourceSnapshot,\n treeEntryToResourceWithMetadata,\n ResourceSnapshot,\n treeEntryToResourceInfo,\n isPlTreeEntry\n} from '@milaboratories/pl-tree';\nimport {\n AnyLogHandle,\n BlobDriver,\n LocalBlobHandle,\n LocalBlobHandleAndSize,\n ReadyLogHandle,\n RemoteBlobHandle,\n RemoteBlobHandleAndSize,\n StreamingApiResponse\n} from '@milaboratories/pl-model-common';\nimport { dataToHandle, handleToData, isReadyLogHandle } from './logs';\nimport { z } from 'zod';\nimport { NetworkError400 } from '../helpers/download';\n\n/** ResourceSnapshot that can be passed to OnDemandBlob */\nexport const OnDemandBlobResourceSnapshot = rsSchema({\n kv: {\n 'ctl/file/blobInfo': z.object({\n sizeBytes: z.coerce.number()\n })\n }\n});\n\nexport type OnDemandBlobResourceSnapshot = InferSnapshot<typeof OnDemandBlobResourceSnapshot>;\n\nexport type DownloadDriverOps = {\n /**\n * A soft limit of the amount of blob storage, in bytes.\n * Once exceeded, the download driver will start deleting blobs one by one\n * when they become unneeded.\n * */\n cacheSoftSizeBytes: number;\n /**\n * Max number of concurrent downloads while calculating computable states\n * derived from this driver\n * */\n nConcurrentDownloads: number;\n};\n\n/** DownloadDriver holds a queue of downloading tasks,\n * and notifies every watcher when a file were downloaded. */\nexport class DownloadDriver implements BlobDriver {\n /** Represents a Resource Id to the path of a blob as a map. */\n private idToDownload: Map<ResourceId, Download> = new Map();\n\n /** Writes and removes files to a hard drive and holds a counter for every\n * file that should be kept. */\n private cache: FilesCache<Download>;\n\n /** Downloads files and writes them to the local dir. */\n private downloadQueue: TaskProcessor;\n\n private idToOnDemand: Map<ResourceId, OnDemandBlobHolder> = new Map();\n\n private idToLastLines: Map<ResourceId, LastLinesGetter> = new Map();\n private idToProgressLog: Map<ResourceId, LastLinesGetter> = new Map();\n\n private readonly saveDir: string;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientDownload: ClientDownload,\n private readonly clientLogs: ClientLogs,\n saveDir: string,\n private readonly signer: Signer,\n ops: DownloadDriverOps\n ) {\n this.cache = new FilesCache(ops.cacheSoftSizeBytes);\n this.downloadQueue = new TaskProcessor(this.logger, ops.nConcurrentDownloads);\n\n this.saveDir = path.resolve(saveDir);\n }\n\n /** Gets a blob by its resource id or downloads a blob and sets it in a cache.*/\n getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx: ComputableCtx\n ): LocalBlobHandleAndSize | undefined;\n getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry\n ): ComputableStableDefined<LocalBlobHandleAndSize>;\n getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<LocalBlobHandleAndSize | undefined> | LocalBlobHandleAndSize | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getDownloadedBlob(res, ctx));\n\n const rInfo = treeEntryToResourceInfo(res, ctx);\n\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(rInfo.id, callerId));\n\n const result = this.getDownloadedBlobNoCtx(ctx.watcher, rInfo as ResourceSnapshot, callerId);\n if (result == undefined) ctx.markUnstable('download blob is still undefined');\n\n return result;\n }\n\n getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry\n ): Computable<RemoteBlobHandleAndSize>;\n getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx: ComputableCtx\n ): RemoteBlobHandleAndSize;\n getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx?: ComputableCtx\n ): ComputableStableDefined<RemoteBlobHandleAndSize> | RemoteBlobHandleAndSize | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getOnDemandBlob(res, ctx));\n\n const rInfo: OnDemandBlobResourceSnapshot = isPlTreeEntry(res)\n ? makeResourceSnapshot(res, OnDemandBlobResourceSnapshot, ctx)\n : res;\n\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseOnDemandBlob(rInfo.id, callerId));\n\n const result = this.getOnDemandBlobNoCtx(ctx.watcher, rInfo, callerId);\n\n return result;\n }\n\n public getLocalPath(handle: LocalBlobHandle): string {\n return localHandleToPath(handle, this.signer);\n }\n\n public async getContent(handle: LocalBlobHandle | RemoteBlobHandle): Promise<Uint8Array> {\n if (isLocalBlobHandle(handle)) return await read(this.getLocalPath(handle));\n\n if (!isRemoteBlobHandle(handle)) throw new Error('Malformed remote handle');\n\n const result = remoteHandleToData(handle, this.signer);\n const { content } = await this.clientDownload.downloadBlob(result);\n\n return await buffer(content);\n }\n\n private getDownloadedBlobNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n callerId: string\n ): LocalBlobHandleAndSize | undefined {\n let task = this.idToDownload.get(rInfo.id);\n\n if (task === undefined) {\n // schedule the blob downloading\n const newTask = this.setNewDownloadTask(w, rInfo, callerId);\n this.downloadQueue.push({\n fn: () => this.downloadBlob(newTask, callerId),\n recoverableErrorPredicate: (_) => true\n });\n task = newTask;\n }\n\n task.attach(w, callerId);\n const result = task.getBlob();\n if (result === undefined) return undefined;\n if (result.ok) return result.value;\n throw result.error;\n }\n\n private setNewDownloadTask(w: Watcher, rInfo: ResourceSnapshot, callerId: string) {\n const fPath = this.getFilePath(rInfo.id);\n const result = new Download(\n this.clientDownload,\n rInfo,\n fPath,\n dataToLocalHandle(fPath, this.signer)\n );\n this.idToDownload.set(rInfo.id, result);\n\n return result;\n }\n\n private async downloadBlob(task: Download, callerId: string) {\n await task.download();\n if (task.getBlob()?.ok) this.cache.addCache(task, callerId);\n }\n\n private getOnDemandBlobNoCtx(\n w: Watcher,\n info: OnDemandBlobResourceSnapshot,\n callerId: string\n ): RemoteBlobHandleAndSize {\n let blob = this.idToOnDemand.get(info.id);\n\n if (blob === undefined) {\n blob = new OnDemandBlobHolder(\n info.kv['ctl/file/blobInfo'].sizeBytes,\n dataToRemoteHandle(info, this.signer)\n );\n this.idToOnDemand.set(info.id, blob);\n }\n\n blob.attach(w, callerId);\n\n return blob.getHandle();\n }\n\n /** Returns all logs and schedules a job that reads remain logs.\n * Notifies when a new portion of the log appeared. */\n getLastLogs(res: ResourceInfo | PlTreeEntry, lines: number): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx: ComputableCtx\n ): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined) return Computable.make((ctx) => this.getLastLogs(res, lines, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(r.id, callerId));\n\n const result = this.getLastLogsNoCtx(ctx.watcher, r as ResourceSnapshot, lines, callerId);\n if (result == undefined)\n ctx.markUnstable('either a file was not downloaded or logs was not read');\n\n return result;\n }\n\n private getLastLogsNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n lines: number,\n callerId: string\n ): string | undefined {\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n\n const path = localHandleToPath(blob.handle, this.signer);\n\n let logGetter = this.idToLastLines.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, lines);\n this.idToLastLines.set(rInfo.id, newLogGetter);\n logGetter = newLogGetter;\n }\n\n const result = logGetter.getOrSchedule(w);\n if (result.error) throw result.error;\n\n return result.log;\n }\n\n /** Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string\n ): Computable<string | undefined>;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx: ComputableCtx\n ): string | undefined;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined)\n return Computable.make((ctx) => this.getProgressLog(res, patternToSearch, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(r.id, callerId));\n\n const result = this.getProgressLogNoCtx(\n ctx.watcher,\n r as ResourceSnapshot,\n patternToSearch,\n callerId\n );\n if (result === undefined)\n ctx.markUnstable('either a file was not downloaded or a progress log was not read');\n\n return result;\n }\n\n private getProgressLogNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n patternToSearch: string,\n callerId: string\n ): string | undefined {\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n const path = localHandleToPath(blob.handle, this.signer);\n\n let logGetter = this.idToProgressLog.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, 1, patternToSearch);\n this.idToProgressLog.set(rInfo.id, newLogGetter);\n\n logGetter = newLogGetter;\n }\n\n const result = logGetter.getOrSchedule(w);\n if (result.error) throw result.error;\n\n return result.log;\n }\n\n /** Returns an Id of a smart object, that can read logs directly from\n * the platform. */\n getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<AnyLogHandle>;\n getLogHandle(res: ResourceInfo | PlTreeEntry, ctx: ComputableCtx): AnyLogHandle;\n getLogHandle(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<AnyLogHandle> | AnyLogHandle {\n if (ctx == undefined) return Computable.make((ctx) => this.getLogHandle(res, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n\n return this.getLogHandleNoCtx(r as ResourceSnapshot);\n }\n\n private getLogHandleNoCtx(rInfo: ResourceSnapshot): AnyLogHandle {\n return dataToHandle(false, rInfo);\n }\n\n async lastLines(\n handle: ReadyLogHandle,\n lineCount: number,\n offsetBytes?: number, // if 0n, then start from the end.\n searchStr?: string\n ): Promise<StreamingApiResponse> {\n const resp = await this.clientLogs.lastLines(\n handleToData(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr\n );\n\n return {\n live: false,\n shouldUpdateHandle: false,\n data: resp.data,\n size: Number(resp.size),\n newOffset: Number(resp.newOffset)\n };\n }\n\n async readText(\n handle: ReadyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string\n ): Promise<StreamingApiResponse> {\n const resp = await this.clientLogs.readText(\n handleToData(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr\n );\n\n return {\n live: false,\n shouldUpdateHandle: false,\n data: resp.data,\n size: Number(resp.size),\n newOffset: Number(resp.newOffset)\n };\n }\n\n private async releaseBlob(blobId: ResourceId, callerId: string) {\n const task = this.idToDownload.get(blobId);\n if (task == undefined) return;\n\n if (this.cache.existsFile(task.path)) {\n const toDelete = this.cache.removeFile(task.path, callerId);\n await Promise.all(\n toDelete.map(async (task) => {\n await fsp.rm(task.path);\n\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${task.path} was removed` +\n `from cache along with ${toDelete.map((d) => d.path)}`\n );\n })\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted) this.removeTask(task, `the task ${task.path} was removed from cache`);\n }\n }\n\n private removeTask(task: Download, reason: string) {\n task.abort(reason);\n task.change.markChanged();\n this.idToDownload.delete(task.rInfo.id);\n this.idToLastLines.delete(task.rInfo.id);\n this.idToProgressLog.delete(task.rInfo.id);\n }\n\n private async releaseOnDemandBlob(blobId: ResourceId, callerId: string) {\n const deleted = this.idToOnDemand.get(blobId)?.release(callerId) ?? false;\n if (deleted) this.idToOnDemand.delete(blobId);\n }\n\n /** Removes all files from a hard drive. */\n async releaseAll() {\n this.downloadQueue.stop();\n\n this.idToDownload.forEach((task, blobId) => {\n this.idToDownload.delete(blobId);\n task.change.markChanged();\n });\n }\n\n private getFilePath(rId: ResourceId): string {\n return path.resolve(path.join(this.saveDir, String(BigInt(rId))));\n }\n}\n\nclass OnDemandBlobHolder {\n private readonly change = new ChangeSource();\n private readonly counter = new CallersCounter();\n\n constructor(\n private readonly size: number,\n private readonly handle: RemoteBlobHandle\n ) {}\n\n getHandle(): RemoteBlobHandleAndSize {\n return { handle: this.handle, size: this.size };\n }\n\n attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n this.change.attachWatcher(w);\n }\n\n release(callerId: string): boolean {\n return this.counter.dec(callerId);\n }\n}\n\nclass LastLinesGetter {\n private updater: helper.Updater;\n private log: string | undefined;\n private readonly change: ChangeSource = new ChangeSource();\n private error: any | undefined = undefined;\n\n constructor(\n private readonly path: string,\n private readonly lines: number,\n private readonly patternToSearch?: string\n ) {\n this.updater = new helper.Updater(async () => this.update());\n }\n\n getOrSchedule(w: Watcher): {\n log: string | undefined;\n error?: any | undefined;\n } {\n this.change.attachWatcher(w);\n\n this.updater.schedule();\n\n return {\n log: this.log,\n error: this.error\n };\n }\n\n async update(): Promise<void> {\n try {\n const newLogs = await getLastLines(this.path, this.lines, this.patternToSearch);\n\n if (this.log != newLogs) this.change.markChanged();\n this.log = newLogs;\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n // No resource\n this.log = '';\n this.error = e;\n this.change.markChanged();\n return;\n }\n\n throw e;\n }\n }\n}\n\nasync function fileOrDirExists(path: string): Promise<boolean> {\n try {\n await fsp.access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function read(path: string): Promise<Uint8Array> {\n return await buffer(Readable.toWeb(fs.createReadStream(path)));\n}\n\n/** Gets last lines from a file by reading the file from the top and keeping\n * last N lines in a window queue. */\nfunction getLastLines(fPath: PathLike, nLines: number, patternToSearch?: string): Promise<string> {\n const inStream = fs.createReadStream(fPath);\n const outStream = new Writable();\n\n return new Promise((resolve, reject) => {\n const rl = readline.createInterface(inStream, outStream);\n\n const lines = new Denque();\n rl.on('line', function (line) {\n if (patternToSearch != undefined && !line.includes(patternToSearch)) return;\n\n lines.push(line);\n if (lines.length > nLines) {\n lines.shift();\n }\n });\n\n rl.on('error', reject);\n\n rl.on('close', function () {\n // last EOL is for keeping backward compat with platforma implementation.\n resolve(lines.toArray().join(os.EOL) + os.EOL);\n });\n });\n}\n\nexport class Download {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n readonly signalCtl = new AbortController();\n error: any | undefined;\n done = false;\n sizeBytes = 0;\n\n constructor(\n readonly clientDownload: ClientDownload,\n readonly rInfo: ResourceSnapshot,\n readonly path: string,\n readonly handle: LocalBlobHandle\n ) {}\n\n attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n if (!this.done) this.change.attachWatcher(w);\n }\n\n async download() {\n try {\n // TODO: move size bytes inside fileExists check like in download_url.\n const { content, size } = await this.clientDownload.downloadBlob(this.rInfo);\n\n if (!(await fileOrDirExists(path.dirname(this.path))))\n await fsp.mkdir(path.dirname(this.path), { recursive: true });\n\n // check in case we already have a file by this resource id\n // in the directory. It can happen when we forgot to call removeAll\n // in the previous launch.\n if (await fileOrDirExists(this.path)) {\n await content.cancel(`the file already existed`); // we don't need the blob\n } else {\n const fileToWrite = Writable.toWeb(fs.createWriteStream(this.path));\n await content.pipeTo(fileToWrite);\n }\n\n this.setDone(size);\n } catch (e: any) {\n if (\n e instanceof DownloadAborted ||\n e instanceof NetworkError400 ||\n e instanceof UnknownStorageError ||\n e instanceof WrongLocalFileUrl ||\n e.code == 'ENOENT' // file that we downloads from was moved or deleted.\n ) {\n this.setError(e);\n // Just in case we were half-way extracting an archive.\n await fsp.rm(this.path);\n return;\n }\n\n throw e;\n }\n }\n\n getBlob(): ValueOrError<LocalBlobHandleAndSize> | undefined {\n if (this.done)\n return {\n ok: true,\n value: {\n handle: this.handle,\n size: this.sizeBytes\n }\n };\n\n if (this.error)\n return {\n ok: false,\n error: this.error\n };\n\n return undefined;\n }\n\n private setDone(sizeBytes: number) {\n this.done = true;\n this.sizeBytes = sizeBytes;\n this.change.markChanged();\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new DownloadAborted(reason));\n }\n\n private setError(e: any) {\n this.error = e;\n this.change.markChanged();\n }\n}\n\ntype PathLike = string;\n\nclass DownloadAborted extends Error {}\n\n// https://regex101.com/r/kfnBVX/1\nconst localHandleRegex = /^blob\\+local:\\/\\/download\\/(?<path>.*)#(?<signature>.*)$/;\n\nfunction isLocalBlobHandle(handle: string): handle is LocalBlobHandle {\n return Boolean(handle.match(localHandleRegex));\n}\n\nfunction localHandleToPath(handle: LocalBlobHandle, signer: Signer): string {\n const parsed = handle.match(localHandleRegex);\n\n if (parsed === null) throw new Error(`Local handle is malformed: ${handle}, matches: ${parsed}`);\n\n const { path, signature } = parsed.groups!;\n\n signer.verify(path, signature, `Signature verification failed for: ${handle}`);\n\n return path;\n}\n\nfunction dataToLocalHandle(path: string, signer: Signer): LocalBlobHandle {\n return `blob+local://download/${path}#${signer.sign(path)}` as LocalBlobHandle;\n}\n\n// https://regex101.com/r/rvbPZt/1\nconst remoteHandleRegex =\n /^blob\\+remote:\\/\\/download\\/(?<content>(?<resourceType>.*)\\/(?<resourceVersion>.*)\\/(?<resourceId>.*))#(?<signature>.*)$/;\n\nfunction isRemoteBlobHandle(handle: string): handle is RemoteBlobHandle {\n return Boolean(handle.match(remoteHandleRegex));\n}\n\nfunction remoteHandleToData(handle: RemoteBlobHandle, signer: Signer): ResourceInfo {\n const parsed = handle.match(remoteHandleRegex);\n if (parsed === null) throw new Error(`Remote handle is malformed: ${handle}, matches: ${parsed}`);\n\n const { content, resourceType, resourceVersion, resourceId, signature } = parsed.groups!;\n\n signer.verify(content, signature, `Signature verification failed for ${handle}`);\n\n return {\n id: bigintToResourceId(BigInt(resourceId)),\n type: { name: resourceType, version: resourceVersion }\n };\n}\n\nfunction dataToRemoteHandle(rInfo: OnDemandBlobResourceSnapshot, signer: Signer): RemoteBlobHandle {\n const content = `${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}`;\n return `blob+remote://download/${content}#${signer.sign(content)}` as RemoteBlobHandle;\n}\n","import { z } from 'zod';\n\nexport const ImportFileHandleUploadData = z.object({\n /** Local file path, to take data for upload */\n localPath: z.string(),\n /** Path signature, to check this data was generated by us */\n pathSignature: z.string(),\n /** File size in bytes */\n sizeBytes: z.string(),\n /** Modification time unix timestamp in seconds */\n modificationTime: z.string()\n});\nexport type ImportFileHandleUploadData = z.infer<typeof ImportFileHandleUploadData>;\n\nexport const ImportFileHandleIndexData = z.object({\n /** Pl storage id */\n storageId: z.string(),\n /** Path inside storage */\n path: z.string()\n});\nexport type ImportFileHandleIndexData = z.infer<typeof ImportFileHandleIndexData>;\n\nexport const ImportFileHandleData = z.union([\n ImportFileHandleUploadData,\n ImportFileHandleIndexData\n]);\nexport type ImportFileHandleData = z.infer<typeof ImportFileHandleData>;\n\n/** Defines which storages from pl are available via local paths */\nexport type LocalStorageProjection = {\n /** Pl storage id */\n readonly storageId: string;\n\n /**\n * Local path, the storage is mounted at.\n *\n * Empty string means that this storage accepts absolute paths, and operates inside the same OS.\n * This matches the behaviour how pl interprets FS storage config.\n * */\n readonly localPath: string;\n};\n\n/** Allows to add parts of local FS as virtual storages, presenting homogeneous API to UI */\nexport type VirtualLocalStorageSpec = {\n /** Virtual storage ID, must not intersect with other storage ids */\n readonly name: string;\n\n /** Local path to \"chroot\" the API in */\n readonly root: string;\n\n /** Used as hint to UI controls to, set as initial path during browsing */\n readonly initialPath: string;\n};\n","import { randomUUID } from 'node:crypto';\nimport { ResourceId, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport {\n Watcher,\n ChangeSource,\n ComputableCtx,\n Computable,\n PollingComputableHooks\n} from '@milaboratories/computable';\nimport {\n MiLogger,\n asyncPool,\n TaskProcessor,\n CallersCounter,\n Signer\n} from '@milaboratories/ts-helpers';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { ProgressStatus, ClientProgress } from '../clients/progress';\nimport { ClientUpload, MTimeError, NoFileForUploading, UnexpectedEOF } from '../clients/upload';\nimport {\n InferSnapshot,\n isPlTreeEntry,\n isPlTreeEntryAccessor,\n makeResourceSnapshot,\n PlTreeEntry,\n PlTreeEntryAccessor,\n PlTreeNodeAccessor,\n rsSchema\n} from '@milaboratories/pl-tree';\nimport { scheduler } from 'node:timers/promises';\nimport { PollingOps } from './helpers/polling_ops';\nimport { ImportFileHandleUploadData } from './types';\n\n/** Options from BlobUpload resource that have to be passed to getProgress. */\n\n/** ResourceSnapshot that can be passed to GetProgressID */\nexport const UploadResourceSnapshot = rsSchema({\n data: ImportFileHandleUploadData,\n fields: {\n blob: false\n }\n});\n\nexport const IndexResourceSnapshot = rsSchema({\n fields: {\n incarnation: false\n }\n});\n\nexport type UploadResourceSnapshot = InferSnapshot<typeof UploadResourceSnapshot>;\nexport type IndexResourceSnapshot = InferSnapshot<typeof IndexResourceSnapshot>;\n\nexport type ImportResourceSnapshot = UploadResourceSnapshot | IndexResourceSnapshot;\n\nexport function makeBlobImportSnapshot(\n entryOrAccessor: PlTreeEntry | PlTreeNodeAccessor | PlTreeEntryAccessor,\n ctx: ComputableCtx\n): ImportResourceSnapshot {\n const node = isPlTreeEntry(entryOrAccessor)\n ? ctx.accessor(entryOrAccessor).node()\n : isPlTreeEntryAccessor(entryOrAccessor)\n ? entryOrAccessor.node()\n : entryOrAccessor;\n if (node.resourceType.name.startsWith('BlobUpload'))\n return makeResourceSnapshot(node, UploadResourceSnapshot);\n else return makeResourceSnapshot(node, IndexResourceSnapshot);\n}\n\nexport type UploadDriverOps = PollingOps & {\n /** How much parts of a file can be multipart-uploaded to S3 at once. */\n nConcurrentPartUploads: number;\n /** How much upload/indexing statuses of blobs can the driver ask\n * from the platform gRPC at once. */\n nConcurrentGetProgresses: number;\n};\n\n// TODO: add abort signal to Upload Tasks.\n\n/** Uploads blobs in a queue and holds counters, so it can stop not-needed\n * uploads.\n * Handles both Index and Upload blobs,\n * the client needs to pass concrete blobs from `handle` field. */\nexport class UploadDriver {\n private readonly idToProgress: Map<ResourceId, ProgressUpdater> = new Map();\n\n /** Holds a queue that upload blobs. */\n private readonly uploadQueue: TaskProcessor;\n private readonly hooks: PollingComputableHooks;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly signer: Signer,\n private readonly clientBlob: ClientUpload,\n private readonly clientProgress: ClientProgress,\n private readonly opts: UploadDriverOps = {\n nConcurrentPartUploads: 10,\n nConcurrentGetProgresses: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000\n }\n ) {\n this.uploadQueue = new TaskProcessor(this.logger, 1, {\n type: 'exponentialWithMaxDelayBackoff',\n initialDelay: 20,\n maxDelay: 15000, // 15 seconds\n backoffMultiplier: 1.5,\n jitter: 0.5\n });\n\n this.hooks = new PollingComputableHooks(\n () => this.startUpdating(),\n () => this.stopUpdating(),\n { stopDebounce: opts.stopPollingDelay },\n (resolve, reject) => this.scheduleOnNextState(resolve, reject)\n );\n }\n\n /** Returns a progress id and schedules an upload task if it's necessary. */\n getProgressId(\n handleResource: ImportResourceSnapshot | PlTreeEntry\n ): Computable<sdk.ImportProgress>;\n getProgressId(\n handleResource: ImportResourceSnapshot | PlTreeEntry,\n ctx: ComputableCtx\n ): sdk.ImportProgress;\n getProgressId(\n handleResource: ImportResourceSnapshot | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<sdk.ImportProgress> | sdk.ImportProgress {\n if (ctx == undefined) return Computable.make((ctx) => this.getProgressId(handleResource, ctx));\n\n const rInfo: ImportResourceSnapshot = isPlTreeEntry(handleResource)\n ? makeBlobImportSnapshot(handleResource, ctx)\n : handleResource;\n\n const callerId = randomUUID();\n ctx.attacheHooks(this.hooks);\n ctx.addOnDestroy(() => this.release(rInfo.id, callerId));\n\n const result = this.getProgressIdNoCtx(ctx.watcher, rInfo, callerId);\n if (!isProgressStable(result)) {\n ctx.markUnstable(\n `upload/index progress was got, but it's not stable: ${JSON.stringify(result)}`\n );\n }\n\n return result;\n }\n\n private getProgressIdNoCtx(\n w: Watcher,\n res: ImportResourceSnapshot,\n callerId: string\n ): sdk.ImportProgress {\n const blobExists =\n 'blob' in res.fields ? res.fields.blob !== undefined : res.fields.incarnation !== undefined;\n\n const value = this.idToProgress.get(res.id);\n\n if (value != undefined) {\n value.attach(w, callerId);\n return value.mustGetProgress(blobExists);\n }\n\n const newValue = new ProgressUpdater(\n this.logger,\n this.clientBlob,\n this.clientProgress,\n this.opts.nConcurrentPartUploads,\n this.signer,\n res\n );\n\n this.idToProgress.set(res.id, newValue);\n newValue.attach(w, callerId);\n\n if (newValue.progress.isUpload && newValue.progress.isUploadSignMatch)\n this.uploadQueue.push({\n fn: () => newValue.uploadBlobTask(),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e)\n });\n\n return newValue.mustGetProgress(blobExists);\n }\n\n /** Decrement counters for the file and remove an uploading if counter == 0. */\n private async release(id: ResourceId, callerId: string) {\n const value = this.idToProgress.get(id);\n if (value === undefined) return;\n\n const deleted = value.decCounter(callerId);\n if (deleted) this.idToProgress.delete(id);\n }\n\n /** Must be called when the driver is closing. */\n public async releaseAll() {\n this.uploadQueue.stop();\n }\n\n private scheduledOnNextState: ScheduledRefresh[] = [];\n\n private scheduleOnNextState(resolve: () => void, reject: (err: any) => void): void {\n this.scheduledOnNextState.push({ resolve, reject });\n }\n\n /** Called from observer */\n private startUpdating(): void {\n this.keepRunning = true;\n if (this.currentLoop === undefined) this.currentLoop = this.mainLoop();\n }\n\n /** Called from observer */\n private stopUpdating(): void {\n this.keepRunning = false;\n }\n\n /** If true, main loop will continue polling pl state. */\n private keepRunning = false;\n /** Actual state of main loop. */\n private currentLoop: Promise<void> | undefined = undefined;\n\n private async mainLoop() {\n while (this.keepRunning) {\n const toNotify = this.scheduledOnNextState;\n this.scheduledOnNextState = [];\n\n try {\n await asyncPool(\n this.opts.nConcurrentGetProgresses,\n this.getAllNotDoneProgresses().map((p) => async () => await p.updateStatus())\n );\n\n toNotify.forEach((n) => n.resolve());\n } catch (e: any) {\n console.error(e);\n toNotify.forEach((n) => n.reject(e));\n }\n\n if (!this.keepRunning) break;\n await scheduler.wait(this.opts.pollingInterval);\n }\n\n this.currentLoop = undefined;\n }\n\n private getAllNotDoneProgresses(): Array<ProgressUpdater> {\n return Array.from(this.idToProgress.entries())\n .filter(([_, p]) => !isProgressStable(p.progress))\n .map(([_, p]) => p);\n }\n}\n\n/** Holds all info needed to upload a file and a status of uploadong\n * and indexing. Also, has a method to update a status of the progress.\n * And holds a change source. */\nclass ProgressUpdater {\n private readonly change: ChangeSource = new ChangeSource();\n private readonly counter: CallersCounter = new CallersCounter();\n\n public progress: sdk.ImportProgress;\n /** If this is upload progress this field will be defined */\n private uploadData?: ImportFileHandleUploadData;\n public uploadingTerminallyFailed?: boolean;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientBlob: ClientUpload,\n private readonly clientProgress: ClientProgress,\n private readonly nConcurrentPartsUpload: number,\n signer: Signer,\n public readonly res: ImportResourceSnapshot\n ) {\n const isUpload = res.type.name.startsWith('BlobUpload');\n let isUploadSignMatch: boolean | undefined;\n if (isUpload) {\n this.uploadData = ImportFileHandleUploadData.parse(res.data);\n isUploadSignMatch = isSignMatch(\n signer,\n this.uploadData.localPath,\n this.uploadData.pathSignature\n );\n }\n\n this.progress = {\n done: false,\n status: undefined,\n isUpload: isUpload,\n isUploadSignMatch: isUploadSignMatch,\n lastError: undefined\n };\n }\n\n public mustGetProgress(blobExists: boolean) {\n // We provide a deep copy of progress,\n // since we do not want to pass a mutable object\n // to API, it led to bugs before.\n\n // We do not use '...' cloning syntax\n // for the compiler to fail here if we change API.\n const progress: sdk.ImportProgress = {\n done: this.progress.done,\n isUpload: this.progress.isUpload,\n isUploadSignMatch: this.progress.isUploadSignMatch,\n lastError: this.progress.lastError\n };\n if (this.progress.status)\n progress.status = {\n progress: this.progress.status.progress,\n bytesProcessed: this.progress.status.bytesProcessed,\n bytesTotal: this.progress.status.bytesTotal\n };\n\n if (blobExists) {\n this.setDone(blobExists);\n return progress;\n }\n\n if (this.uploadingTerminallyFailed) {\n this.logger.error(`Uploading terminally failed: ${this.progress.lastError}`);\n throw new Error(this.progress.lastError);\n }\n\n return progress;\n }\n\n public attach(w: Watcher, callerId: string) {\n this.change.attachWatcher(w);\n this.counter.inc(callerId);\n }\n\n public decCounter(callerId: string) {\n return this.counter.dec(callerId);\n }\n\n /** Uploads a blob if it's not BlobIndex. */\n async uploadBlobTask() {\n try {\n await this.uploadBlob();\n } catch (e: any) {\n this.setLastError(e);\n\n if (isResourceWasDeletedError(e)) {\n this.logger.warn(`resource was deleted while uploading a blob: ${e}`);\n this.change.markChanged();\n this.setDone(true);\n\n return;\n }\n\n this.logger.error(`error while uploading a blob: ${e}`);\n this.change.markChanged();\n\n if (nonRecoverableError(e)) this.terminateWithError(e);\n\n throw e;\n }\n }\n\n /** Uploads a blob using client. */\n private async uploadBlob() {\n if (this.counter.isZero()) return;\n const parts = await this.clientBlob.initUpload(this.res);\n\n this.logger.info(`start to upload blob ${this.res.id}, parts count: ${parts.length}`);\n\n const partUploadFn = (part: bigint) => async () => {\n if (this.counter.isZero()) return;\n await this.clientBlob.partUpload(\n this.res,\n this.uploadData!.localPath,\n part,\n parts.length,\n BigInt(this.uploadData!.modificationTime)\n );\n };\n\n await asyncPool(this.nConcurrentPartsUpload, parts.map(partUploadFn));\n\n if (this.counter.isZero()) return;\n await this.clientBlob.finalizeUpload(this.res);\n\n this.logger.info(`uploading of resource ${this.res.id} finished.`);\n this.change.markChanged();\n }\n\n private terminateWithError(e: unknown) {\n this.progress.lastError = String(e);\n this.progress.done = false;\n this.uploadingTerminallyFailed = true;\n }\n\n private setLastError(e: unknown) {\n this.progress.lastError = String(e);\n }\n\n private setDone(done: boolean) {\n this.progress.done = done;\n if (done) this.progress.lastError = undefined;\n }\n\n async updateStatus() {\n try {\n const status = await this.clientProgress.getStatus(this.res);\n\n const oldStatus = this.progress.status;\n this.progress.status = protoToStatus(status);\n this.setDone(status.done);\n\n if (status.done || status.progress != oldStatus?.progress) this.change.markChanged();\n } catch (e: any) {\n this.setLastError(e);\n\n if (e.name == 'RpcError' && e.code == 'DEADLINE_EXCEEDED') {\n this.logger.warn(`deadline exceeded while getting a status of BlobImport`);\n return;\n }\n\n if (isResourceWasDeletedError(e)) {\n this.logger.warn(\n `resource was not found while updating a status of BlobImport: ${e}, ${stringifyWithResourceId(this.res)}`\n );\n this.change.markChanged();\n this.setDone(true);\n return;\n }\n\n this.logger.error(`error while updating a status of BlobImport: ${e}`);\n this.change.markChanged();\n this.terminateWithError(e);\n }\n }\n}\n\nfunction isProgressStable(p: sdk.ImportProgress) {\n return p.done && p.status !== undefined && p.status !== null && p.status.progress >= 1.0;\n}\n\nfunction protoToStatus(proto: ProgressStatus): sdk.ImportStatus {\n return {\n progress: proto.progress ?? 0,\n bytesProcessed: Number(proto.bytesProcessed),\n bytesTotal: Number(proto.bytesTotal)\n };\n}\n\nfunction isSignMatch(signer: Signer, path: string, signature: string): boolean {\n try {\n signer.verify(path, signature);\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction nonRecoverableError(e: any) {\n return e instanceof MTimeError || e instanceof UnexpectedEOF || e instanceof NoFileForUploading;\n}\n\nfunction isResourceWasDeletedError(e: any) {\n return (\n e.name == 'RpcError' &&\n (e.code == 'NOT_FOUND' || e.code == 'ABORTED' || e.code == 'ALREADY_EXISTS')\n );\n}\n\ntype ScheduledRefresh = {\n resolve: () => void;\n reject: (err: any) => void;\n};\n","import {\n ChangeSource,\n Computable,\n ComputableCtx,\n PollingComputableHooks,\n Watcher\n} from '@milaboratories/computable';\nimport { ResourceId, resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport { asyncPool, CallersCounter, MiLogger } from '@milaboratories/ts-helpers';\nimport { ClientLogs } from '../clients/logs';\nimport { randomUUID } from 'node:crypto';\nimport { PlTreeEntry, ResourceInfo, treeEntryToResourceInfo } from '@milaboratories/pl-tree';\nimport { dataToHandle, handleToData, isLiveLogHandle } from './logs';\nimport { scheduler } from 'node:timers/promises';\nimport { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { PollingOps } from './helpers/polling_ops';\nimport { RpcError } from '@protobuf-ts/runtime-rpc';\n\nexport type LogsStreamDriverOps = PollingOps & {\n /** Max number of concurrent requests to log streaming backend while calculating computable states */\n nConcurrentGetLogs: number;\n};\n\nexport class LogsStreamDriver implements sdk.LogsDriver {\n /** Holds a map of StreamManager Resource Id to all logs of this stream. */\n private readonly idToLastLines: Map<ResourceId, LogGetter> = new Map();\n\n /** Holds a map of StreamManager Resource Id to the last log line of this stream. */\n private readonly idToProgressLog: Map<ResourceId, LogGetter> = new Map();\n\n /** Holds a map of StreamManager Resource Id to log id smart object. */\n private readonly hooks: PollingComputableHooks;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientLogs: ClientLogs,\n private readonly opts: LogsStreamDriverOps = {\n nConcurrentGetLogs: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000\n }\n ) {\n this.hooks = new PollingComputableHooks(\n () => this.startUpdating(),\n () => this.stopUpdating(),\n { stopDebounce: opts.stopPollingDelay },\n (resolve, reject) => this.scheduleOnNextState(resolve, reject)\n );\n }\n\n getLastLogs(res: ResourceInfo | PlTreeEntry, lines: number): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx: ComputableCtx\n ): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined) return Computable.make((ctx) => this.getLastLogs(res, lines, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.attacheHooks(this.hooks);\n ctx.addOnDestroy(() => this.releaseLastLogs(r.id, callerId));\n\n const result = this.getLastLogsNoCtx(ctx.watcher, r, lines, callerId);\n ctx.markUnstable(\n 'The logs are from stream, so we consider them unstable. Final values will be got from blobs.'\n );\n\n return result;\n }\n\n private getLastLogsNoCtx(\n w: Watcher,\n rInfo: ResourceInfo,\n lines: number,\n callerId: string\n ): string | undefined {\n let logGetter = this.idToLastLines.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LogGetter(this.logger, this.clientLogs, rInfo, lines);\n this.idToLastLines.set(rInfo.id, newLogGetter);\n\n logGetter = newLogGetter;\n }\n\n logGetter.attach(w, callerId);\n const result = logGetter.getLog();\n if (result.error != undefined) throw result.error;\n\n return result.log;\n }\n\n /** Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string\n ): Computable<string | undefined>;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx: ComputableCtx\n ): string | undefined;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined)\n return Computable.make((ctx) => this.getProgressLog(res, patternToSearch, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.attacheHooks(this.hooks);\n ctx.addOnDestroy(() => this.releaseProgressLog(r.id, callerId));\n\n const result = this.getProgressLogNoCtx(ctx.watcher, r, patternToSearch, callerId);\n ctx.markUnstable(\n 'The progress log is from the stream, so we consider it unstable. Final value will be got from blobs.'\n );\n\n return result;\n }\n\n private getProgressLogNoCtx(\n w: Watcher,\n rInfo: ResourceInfo,\n patternToSearch: string,\n callerId: string\n ): string | undefined {\n let logGetter = this.idToProgressLog.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LogGetter(this.logger, this.clientLogs, rInfo, 1, patternToSearch);\n this.idToProgressLog.set(rInfo.id, newLogGetter);\n\n logGetter = newLogGetter;\n }\n\n logGetter.attach(w, callerId);\n const result = logGetter.getLog();\n if (result.error) throw result.error;\n\n return result.log;\n }\n\n getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<sdk.AnyLogHandle>;\n getLogHandle(res: ResourceInfo | PlTreeEntry, ctx: ComputableCtx): sdk.AnyLogHandle;\n getLogHandle(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<sdk.AnyLogHandle> | sdk.AnyLogHandle {\n if (ctx == undefined) return Computable.make((ctx) => this.getLogHandle(res, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n\n const result = this.getLogHandleNoCtx(r);\n \n // All logs from streams should be considered unstable,\n // final value will be got from blobs.\n ctx.markUnstable(`live_log:${resourceIdToString(r.id)}`);\n\n return result;\n }\n\n private getLogHandleNoCtx(rInfo: ResourceInfo): sdk.AnyLogHandle {\n return dataToHandle(true, rInfo);\n }\n\n async lastLines(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string | undefined\n ) {\n return await this.tryWithNotFound(handle, () =>\n this.clientLogs.lastLines(\n handleToData(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr\n )\n );\n }\n\n async readText(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string | undefined\n ) {\n return await this.tryWithNotFound(handle, () =>\n this.clientLogs.readText(handleToData(handle), lineCount, BigInt(offsetBytes ?? 0), searchStr)\n );\n }\n\n private async tryWithNotFound(\n handle: sdk.AnyLogHandle,\n method: () => Promise<StreamingAPI_Response>\n ): Promise<sdk.StreamingApiResponse> {\n if (!isLiveLogHandle(handle))\n throw new Error(`Not live log handle was passed to live log driver, handle: ${handle}`);\n\n try {\n const resp = await method();\n return {\n live: true,\n shouldUpdateHandle: false,\n data: resp.data,\n size: Number(resp.size),\n newOffset: Number(resp.newOffset)\n };\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n return { shouldUpdateHandle: true };\n }\n\n throw e;\n }\n }\n\n private async releaseLastLogs(rId: ResourceId, callerId: string) {\n const deleted = this.idToLastLines.get(rId)?.release(callerId);\n if (deleted) this.idToLastLines.delete(rId);\n }\n\n private async releaseProgressLog(rId: ResourceId, callerId: string) {\n const deleted = this.idToProgressLog.get(rId)?.release(callerId);\n if (deleted) this.idToProgressLog.delete(rId);\n }\n\n async releaseAll() {}\n\n private scheduledOnNextState: ScheduledRefresh[] = [];\n\n private scheduleOnNextState(resolve: () => void, reject: (err: any) => void): void {\n this.scheduledOnNextState.push({ resolve, reject });\n }\n\n /** Called from observer */\n private startUpdating(): void {\n this.keepRunning = true;\n if (this.currentLoop === undefined) this.currentLoop = this.mainLoop();\n }\n\n /** Called from observer */\n private stopUpdating(): void {\n this.keepRunning = false;\n }\n\n /** If true, main loop will continue polling pl state. */\n private keepRunning = false;\n /** Actual state of main loop. */\n private currentLoop: Promise<void> | undefined = undefined;\n\n private async mainLoop() {\n while (this.keepRunning) {\n const toNotify = this.scheduledOnNextState;\n this.scheduledOnNextState = [];\n\n try {\n const logs = this.getAllLogs();\n await asyncPool(\n this.opts.nConcurrentGetLogs,\n logs.map((getter) => async () => await getter.update())\n );\n\n toNotify.forEach((n) => n.resolve());\n } catch (e: any) {\n console.error(e);\n toNotify.forEach((n) => n.reject(e));\n }\n\n if (!this.keepRunning) break;\n await scheduler.wait(this.opts.pollingInterval);\n }\n\n this.currentLoop = undefined;\n }\n\n private getAllLogs(): Array<LogGetter> {\n return Array.from(this.idToLastLines.entries())\n .concat(Array.from(this.idToProgressLog.entries()))\n .map(([_, getter]) => getter);\n }\n}\n\n/** A job that gets last lines from a StreamWorkdir resource. */\nclass LogGetter {\n private logs: string | undefined;\n private error: any | undefined = undefined;\n\n private readonly change: ChangeSource = new ChangeSource();\n private readonly counter: CallersCounter = new CallersCounter();\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientLogs: ClientLogs,\n private readonly rInfo: ResourceInfo,\n private readonly lines: number,\n private readonly patternToSearch?: string\n ) {}\n\n getLog(): {\n log: string | undefined;\n error?: any | undefined;\n } {\n return {\n log: this.logs,\n error: this.error\n };\n }\n\n attach(w: Watcher, callerId: string) {\n this.change.attachWatcher(w);\n this.counter.inc(callerId);\n }\n\n release(callerId: string): boolean {\n return this.counter.dec(callerId);\n }\n\n async update() {\n try {\n const resp = await this.clientLogs.lastLines(\n this.rInfo,\n this.lines,\n 0n,\n this.patternToSearch\n );\n\n const newLogs = resp.data.toString();\n\n if (this.logs != newLogs) this.change.markChanged();\n this.logs = newLogs;\n this.error = undefined;\n\n return;\n } catch (e: any) {\n e as RpcError;\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n // No resource\n this.logs = '';\n this.error = e;\n this.change.markChanged();\n return;\n }\n\n this.logger.error(\n `Stream log lines for ${stringifyWithResourceId(this.rInfo.id)} failed, reason: ${e}`\n );\n throw e;\n }\n }\n}\n\ntype ScheduledRefresh = {\n resolve: () => void;\n reject: (err: any) => void;\n};\n","import {\n CallersCounter,\n MiLogger,\n TaskProcessor,\n notEmpty,\n fileExists\n} from '@milaboratories/ts-helpers';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Writable, Transform } from 'node:stream';\nimport { ChangeSource, Computable, ComputableCtx, Watcher } from '@milaboratories/computable';\nimport { randomUUID, createHash } from 'node:crypto';\nimport * as zlib from 'node:zlib';\nimport * as tar from 'tar-fs';\nimport { FilesCache } from './helpers/files_cache';\nimport { Dispatcher } from 'undici';\nimport { DownloadHelper, NetworkError400 } from '../helpers/download';\n\nexport interface DownloadUrlSyncReader {\n /** Returns a Computable that (when the time will come)\n * downloads an archive from an URL,\n * extracts it to the local dir and returns a path to that dir. */\n getPath(url: URL): Computable<PathResult | undefined>;\n}\n\nexport interface PathResult {\n /** Path to the downloadable blob, might be undefined when the error happened. */\n path?: string;\n /** Error that happened when the archive were downloaded. */\n error?: string;\n}\n\nexport type DownloadUrlDriverOps = {\n cacheSoftSizeBytes: number;\n withGunzip: boolean;\n nConcurrentDownloads: number;\n};\n\n/** Downloads .tar or .tar.gz archives by given URLs\n * and extracts them into saveDir. */\nexport class DownloadUrlDriver implements DownloadUrlSyncReader {\n private readonly downloadHelper: DownloadHelper;\n\n private urlToDownload: Map<string, Download> = new Map();\n private downloadQueue: TaskProcessor;\n\n /** Writes and removes files to a hard drive and holds a counter for every\n * file that should be kept. */\n private cache: FilesCache<Download>;\n\n constructor(\n private readonly logger: MiLogger,\n httpClient: Dispatcher,\n private readonly saveDir: string,\n private readonly opts: DownloadUrlDriverOps = {\n cacheSoftSizeBytes: 50 * 1024 * 1024,\n withGunzip: true,\n nConcurrentDownloads: 50\n }\n ) {\n this.downloadQueue = new TaskProcessor(this.logger, this.opts.nConcurrentDownloads);\n this.cache = new FilesCache(this.opts.cacheSoftSizeBytes);\n this.downloadHelper = new DownloadHelper(httpClient);\n }\n\n /** Use to get a path result inside a computable context */\n getPath(url: URL, ctx: ComputableCtx): PathResult | undefined;\n\n /** Returns a Computable that do the work */\n getPath(url: URL): Computable<PathResult | undefined>;\n\n getPath(\n url: URL,\n ctx?: ComputableCtx\n ): Computable<PathResult | undefined> | PathResult | undefined {\n // wrap result as computable, if we were not given an existing computable context\n if (ctx === undefined) return Computable.make((c) => this.getPath(url, c));\n\n const callerId = randomUUID();\n\n // read as ~ golang's defer\n ctx.addOnDestroy(() => this.releasePath(url, callerId));\n\n const result = this.getPathNoCtx(url, ctx.watcher, callerId);\n if (result?.path === undefined)\n ctx.markUnstable(\n `a path to the downloaded and untared archive might be undefined. The current result: ${result}`\n );\n\n return result;\n }\n\n getPathNoCtx(url: URL, w: Watcher, callerId: string) {\n const key = url.toString();\n const task = this.urlToDownload.get(key);\n\n if (task != undefined) {\n task.attach(w, callerId);\n return task.getPath();\n }\n\n const newTask = this.setNewTask(w, url, callerId);\n this.downloadQueue.push({\n fn: async () => this.downloadUrl(newTask, callerId),\n recoverableErrorPredicate: (e) => true\n });\n\n return newTask.getPath();\n }\n\n /** Downloads and extracts a tar archive if it wasn't downloaded yet. */\n async downloadUrl(task: Download, callerId: string) {\n await task.download(this.downloadHelper, this.opts.withGunzip);\n // Might be undefined if a error happened\n if (task.getPath()?.path != undefined) this.cache.addCache(task, callerId);\n }\n\n /** Removes a directory and aborts a downloading task when all callers\n * are not interested in it. */\n async releasePath(url: URL, callerId: string): Promise<void> {\n const key = url.toString();\n const task = this.urlToDownload.get(key);\n if (task == undefined) return;\n\n if (this.cache.existsFile(task.path)) {\n const toDelete = this.cache.removeFile(task.path, callerId);\n\n await Promise.all(\n toDelete.map(async (task) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${JSON.stringify(task)} was removed` +\n `from cache along with ${JSON.stringify(toDelete)}`\n );\n })\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted) this.removeTask(task, `the task ${JSON.stringify(task)} was removed from cache`);\n }\n }\n\n /** Removes all files from a hard drive. */\n async releaseAll() {\n this.downloadQueue.stop();\n\n await Promise.all(\n Array.from(this.urlToDownload.entries()).map(async ([id, task]) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(task, `the task ${task} was released when the driver was closed`);\n })\n );\n }\n\n private setNewTask(w: Watcher, url: URL, callerId: string) {\n const result = new Download(this.getFilePath(url), url);\n result.attach(w, callerId);\n this.urlToDownload.set(url.toString(), result);\n\n return result;\n }\n\n private removeTask(task: Download, reason: string) {\n task.abort(reason);\n task.change.markChanged();\n this.urlToDownload.delete(task.url.toString());\n }\n\n private getFilePath(url: URL): string {\n const sha256 = createHash('sha256').update(url.toString()).digest('hex');\n return path.join(this.saveDir, sha256);\n }\n}\n\nclass Download {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n readonly signalCtl = new AbortController();\n error: string | undefined;\n done = false;\n sizeBytes = 0;\n\n constructor(\n readonly path: string,\n readonly url: URL\n ) {}\n\n attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n if (!this.done) this.change.attachWatcher(w);\n }\n\n async download(clientDownload: DownloadHelper, withGunzip: boolean) {\n try {\n const sizeBytes = await this.downloadAndUntar(\n clientDownload,\n withGunzip,\n this.signalCtl.signal\n );\n this.setDone(sizeBytes);\n } catch (e: any) {\n if (e instanceof URLAborted || e instanceof NetworkError400) {\n this.setError(e);\n // Just in case we were half-way extracting an archive.\n await rmRFDir(this.path);\n return;\n }\n\n throw e;\n }\n }\n\n private async downloadAndUntar(\n clientDownload: DownloadHelper,\n withGunzip: boolean,\n signal: AbortSignal\n ): Promise<number> {\n if (await fileExists(this.path)) {\n return await dirSize(this.path);\n }\n\n const resp = await clientDownload.downloadRemoteFile(this.url.toString(), {}, signal);\n let content = resp.content;\n\n if (withGunzip) {\n const gunzip = Transform.toWeb(zlib.createGunzip());\n content = content.pipeThrough(gunzip, { signal });\n }\n const untar = Writable.toWeb(tar.extract(this.path));\n await content.pipeTo(untar, { signal });\n\n return resp.size;\n }\n\n getPath(): PathResult | undefined {\n if (this.done) return { path: notEmpty(this.path) };\n\n if (this.error) return { error: this.error };\n\n return undefined;\n }\n\n private setDone(sizeBytes: number) {\n this.done = true;\n this.sizeBytes = sizeBytes;\n this.change.markChanged();\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new URLAborted(reason));\n }\n\n private setError(e: any) {\n this.error = String(e);\n this.change.markChanged();\n }\n}\n\nclass URLAborted extends Error {}\n\n/** Gets a directory size by calculating sizes recursively. */\nasync function dirSize(dir: string): Promise<number> {\n const files = await fsp.readdir(dir, { withFileTypes: true });\n const sizes = await Promise.all(\n files.map(async (file) => {\n const fPath = path.join(dir, file.name);\n\n if (file.isDirectory()) return await dirSize(fPath);\n\n const stat = await fsp.stat(fPath);\n return stat.size;\n })\n );\n\n return sizes.reduce((sum, size) => sum + size, 0);\n}\n\n/** Do rm -rf on dir. */\nasync function rmRFDir(path: string) {\n await fsp.rm(path, { recursive: true, force: true });\n}\n","import { MiLogger, notEmpty, Signer } from '@milaboratories/ts-helpers';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { Timestamp } from '../../proto/google/protobuf/timestamp';\nimport { Dirent, Stats } from 'node:fs';\nimport { z } from 'zod';\nimport { ImportFileHandleIndexData, ImportFileHandleUploadData } from '../types';\n\n/** A duck-typing interface for grpc results. */\nexport interface ListResponse {\n items: ListItem[];\n delimiter: string;\n}\n/** @deprecated */\nexport interface ListItem {\n isDir: boolean;\n name: string;\n fullName: string;\n lastModified?: Timestamp;\n size: bigint;\n directory: string;\n}\n\n/** @deprecated */\nexport function toLsEntries(info: {\n storageName: string;\n list: ListResponse;\n signer: Signer;\n remote: boolean;\n}): sdk.ListFilesResult {\n const parent = info.list.items.length > 0 ? info.list.items[0]?.directory : undefined;\n\n return {\n parent: parent,\n entries: info.list.items.map((item) => toLsEntry(item, info))\n };\n}\n\n/** @deprecated */\nfunction toLsEntry(\n item: ListItem,\n info: {\n storageName: string;\n list: ListResponse;\n signer: Signer;\n remote: boolean;\n }\n): sdk.LsEntry {\n if (item.isDir)\n return {\n type: 'dir',\n name: item.name,\n fullPath: item.fullName\n };\n\n return {\n type: 'file',\n name: item.name,\n fullPath: item.fullName,\n handle: toFileHandle({ item: item, ...info })\n };\n}\n\n/** @deprecated */\nexport function toFileHandle(info: {\n storageName: string;\n item: ListItem;\n signer: Signer;\n remote: boolean;\n}): sdk.ImportFileHandle {\n if (info.remote) {\n return createIndexImportHandle(info.storageName, info.item.fullName);\n }\n\n return createUploadImportHandle(\n info.item.fullName,\n info.signer,\n info.item.size,\n notEmpty(info.item.lastModified).seconds\n );\n}\n\nexport function createIndexImportHandle(\n storageName: string,\n path: string\n): sdk.ImportFileHandleIndex {\n const data: ImportFileHandleIndexData = {\n storageId: storageName,\n path: path\n };\n\n return `index://index/${encodeURIComponent(JSON.stringify(data))}`;\n}\n\nexport function createUploadImportHandle(\n localPath: string,\n signer: Signer,\n sizeBytes: bigint,\n modificationTimeSeconds: bigint\n): sdk.ImportFileHandleUpload {\n const data: ImportFileHandleUploadData = {\n localPath,\n pathSignature: signer.sign(localPath),\n sizeBytes: String(sizeBytes),\n modificationTime: String(modificationTimeSeconds)\n };\n\n return `upload://upload/${encodeURIComponent(JSON.stringify(data))}`;\n}\n\nexport function parseUploadHandle(handle: sdk.ImportFileHandleUpload): ImportFileHandleUploadData {\n const url = new URL(handle);\n return ImportFileHandleUploadData.parse(\n JSON.parse(decodeURIComponent(url.pathname.substring(1)))\n );\n}\n\nexport function parseIndexHandle(handle: sdk.ImportFileHandleIndex): ImportFileHandleIndexData {\n const url = new URL(handle);\n return ImportFileHandleIndexData.parse(JSON.parse(decodeURIComponent(url.pathname.substring(1))));\n}\n\nexport function toListItem(\n logger: MiLogger,\n info: {\n directory: string;\n fullName: string;\n dirent: Dirent;\n stat: Stats;\n }\n): ListItem | undefined {\n if (!(info.dirent.isFile() || info.dirent.isDirectory())) {\n logger.warn(`tried to get non-dir and non-file ${info.dirent.name}, skip it`);\n return;\n }\n\n return {\n directory: info.directory,\n isDir: info.dirent.isDirectory(),\n name: info.dirent.name,\n fullName: info.fullName,\n lastModified: {\n seconds: BigInt(Math.floor(info.stat.mtimeMs / 1000)),\n nanos: 0\n },\n size: BigInt(info.stat.size)\n };\n}\n","import * as sdk from '@milaboratories/pl-model-common';\nimport { bigintToResourceId, ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { assertNever } from '@milaboratories/ts-helpers';\n\nexport type StorageHandleData = RemoteStorageHandleData | LocalStorageHandleData;\n\n/**\n * Gets a storage handle and gives an underlying data from it.\n */\nexport function parseStorageHandle(handle: sdk.StorageHandle): StorageHandleData {\n if (isRemoteStorageHandle(handle)) {\n return parseRemoteStorageHandle(handle);\n } else if (isLocalStorageHandle(handle)) {\n return parseLocalStorageHandle(handle);\n }\n\n assertNever(handle);\n}\n\n//\n// Local storage:\n//\n\nexport type LocalStorageHandleData = {\n isRemote: false;\n name: string;\n rootPath: string;\n};\n\nconst localHandleRegex = /^local:\\/\\/(?<name>.*)\\/(?<path>.*)$/;\n\nexport function isLocalStorageHandle(handle: sdk.StorageHandle): handle is sdk.StorageHandleLocal {\n return localHandleRegex.test(handle);\n}\n\nexport function createLocalStorageHandle(name: string, path: string): sdk.StorageHandleLocal {\n return `local://${name}/${encodeURIComponent(path)}`;\n}\n\nfunction parseLocalStorageHandle(handle: string): LocalStorageHandleData {\n const parsed = handle.match(localHandleRegex);\n if (parsed == null) throw new Error(`Local list handle wasn't parsed: ${handle}`);\n\n const { name, path } = parsed.groups!;\n\n return {\n rootPath: decodeURIComponent(path),\n name,\n isRemote: false\n };\n}\n\n//\n// Remote storage:\n//\n\nexport type RemoteStorageHandleData = {\n isRemote: true;\n name: string;\n id: ResourceId;\n type: ResourceType;\n};\n\nconst remoteHandleRegex = /^remote:\\/\\/(?<name>.*)\\/(?<resourceId>.*)$/;\n\nexport function isRemoteStorageHandle(\n handle: sdk.StorageHandle\n): handle is sdk.StorageHandleRemote {\n return remoteHandleRegex.test(handle);\n}\n\nexport function createRemoteStorageHandle(name: string, rId: ResourceId): sdk.StorageHandleRemote {\n return `remote://${name}/${BigInt(rId)}`;\n}\n\nfunction parseRemoteStorageHandle(handle: string): RemoteStorageHandleData {\n const parsed = handle.match(remoteHandleRegex);\n if (parsed == null) throw new Error(`Remote list handle wasn't parsed: ${handle}`);\n const { name, resourceId } = parsed.groups!;\n\n return {\n id: bigintToResourceId(BigInt(resourceId)),\n type: storageType(name),\n name,\n isRemote: true\n };\n}\n\nfunction storageType(name: string): ResourceType {\n return { name: `LS/${name}`, version: '1' };\n}\n","import path from 'path';\nimport os from 'os';\nimport util from 'util';\nimport { exec } from 'child_process';\nimport { VirtualLocalStorageSpec } from './types';\n\nexport async function DefaultVirtualLocalStorages(): Promise<VirtualLocalStorageSpec[]> {\n const home = os.homedir();\n if (path.sep == '/')\n return [\n {\n name: 'local',\n root: '/',\n initialPath: home\n }\n ];\n else {\n // determine the drive on which user's home folder is stored\n const homeRoot = path.parse(home).root; // e.g. C:\\\n const homeDrive = homeRoot.replaceAll(':\\\\', ''); // e.g. C drive.\n\n // code below inspired by\n // https://stackoverflow.com/a/52411712/769192\n\n try {\n const wmic = await util.promisify(exec)('wmic logicaldisk get name');\n // parsing wmic output\n const drives = wmic.stdout\n .split('\\r\\n')\n .filter((line) => line.includes(':'))\n .map((line) => line.trim().replaceAll(':', ''));\n\n return drives.map((drive) => {\n const isHomeDrive = drive == homeDrive;\n return {\n name: `local_disk_${drive}`,\n root: `${drive}:\\\\`,\n initialPath: isHomeDrive ? home : `${drive}:\\\\`\n };\n });\n } catch (e: any) {\n return [\n {\n name: `local_disk_${homeDrive}`,\n root: `${homeDrive}:\\\\`,\n initialPath: home\n }\n ];\n }\n }\n}\n","import { isNotNullResourceId, PlClient, ResourceData, ResourceId } from '@milaboratories/pl-client';\nimport { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport {\n isImportFileHandleIndex,\n LocalImportFileHandle,\n LsEntry,\n OpenDialogOps,\n OpenMultipleFilesResponse,\n OpenSingleFileResponse,\n TableRange\n} from '@milaboratories/pl-model-common';\nimport { ClientLs } from '../clients/ls_api';\nimport * as path from 'node:path';\nimport * as fsp from 'node:fs/promises';\nimport {\n createIndexImportHandle,\n createUploadImportHandle,\n parseIndexHandle,\n parseUploadHandle\n} from './helpers/ls_list_entry';\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle\n} from './helpers/ls_storage_entry';\nimport { LocalStorageProjection, VirtualLocalStorageSpec } from './types';\nimport { createLsFilesClient } from '../clients/helpers';\nimport { validateAbsolute } from '../helpers/validate';\nimport { DefaultVirtualLocalStorages } from './virtual_storages';\n\n/**\n * Extends public and safe SDK's driver API with methods used internally in the middle\n * layer and in tests.\n */\nexport interface InternalLsDriver extends sdk.LsDriver {\n /**\n * Given local path, generates well-structured and signed upload handle.\n * To be used in tests and in implementation of the native file selection UI API.\n * */\n getLocalFileHandle(localPath: string): Promise<sdk.LocalImportFileHandle>;\n}\n\nexport type OpenFileDialogCallback = (\n multipleFiles: boolean,\n ops?: OpenDialogOps\n) => Promise<undefined | string[]>;\n\nexport class LsDriver implements InternalLsDriver {\n private constructor(\n private readonly logger: MiLogger,\n private readonly lsClient: ClientLs,\n /** Pl storage id, to resource id. The resource id can be used to make LS GRPC calls to. */\n private readonly storageIdToResourceId: Record<string, ResourceId>,\n private readonly signer: Signer,\n /** Virtual storages by name */\n private readonly virtualStoragesMap: Map<string, VirtualLocalStorageSpec>,\n /** Local projections by storageId */\n private readonly localProjectionsMap: Map<string, LocalStorageProjection>,\n private readonly openFileDialogCallback: OpenFileDialogCallback\n ) {}\n\n public async getLocalFileContent(\n file: LocalImportFileHandle,\n range?: TableRange\n ): Promise<Uint8Array> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n if (range) throw new Error('Range request not yet supported.');\n return await fsp.readFile(localPath);\n }\n\n public async getLocalFileSize(file: LocalImportFileHandle): Promise<number> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n const stat = await fsp.stat(localPath);\n return stat.size;\n }\n\n public async showOpenMultipleFilesDialog(\n ops?: OpenDialogOps\n ): Promise<OpenMultipleFilesResponse> {\n const result = await this.openFileDialogCallback(true, ops);\n if (result === undefined) return {};\n return {\n files: await Promise.all(result.map((localPath) => this.getLocalFileHandle(localPath)))\n };\n }\n\n public async showOpenSingleFileDialog(ops?: OpenDialogOps): Promise<OpenSingleFileResponse> {\n const result = await this.openFileDialogCallback(false, ops);\n if (result === undefined) return {};\n return {\n file: await this.getLocalFileHandle(result[0])\n };\n }\n\n /**\n * Resolves local handle to local file path.\n *\n * @param handle handle to be resolved\n * @private\n */\n private async tryResolveLocalFileHandle(handle: LocalImportFileHandle): Promise<string> {\n if (isImportFileHandleIndex(handle)) {\n const handleData = parseIndexHandle(handle);\n const localProjection = this.localProjectionsMap.get(handleData.storageId);\n if (!localProjection)\n throw new Error(`Storage ${handleData.storageId} is not mounted locally.`);\n return path.join(localProjection.localPath, handleData.path);\n } else {\n const handleData = parseUploadHandle(handle);\n // checking it is a valid local handle from out machine\n this.signer.verify(\n handleData.localPath,\n handleData.pathSignature,\n 'Failed to validate local file handle signature.'\n );\n\n const localPath = handleData.localPath;\n\n const stat = await fsp.stat(localPath, { bigint: true });\n if (String(stat.mtimeMs / 1000n) !== handleData.modificationTime)\n throw new Error('File has changed since the handle was created.');\n\n return localPath;\n }\n }\n\n public async getLocalFileHandle(\n localPath: string\n ): Promise<sdk.ImportFileHandle & LocalImportFileHandle> {\n validateAbsolute(localPath);\n\n // Checking if local path is directly reachable by pl, because it is in one of the\n // locally mounted storages\n for (const lp of this.localProjectionsMap.values()) {\n // note: empty lp.localPath will match any address\n if (localPath.startsWith(lp.localPath)) {\n // Just in case:\n // > path.relative(\"/a/b\", \"/a/b/c\");\n // 'c'\n const pathWithinStorage =\n lp.localPath === '' ? localPath : path.relative(lp.localPath, localPath);\n return createIndexImportHandle(\n lp.storageId,\n pathWithinStorage\n ) as sdk.ImportFileHandleIndex & LocalImportFileHandle;\n }\n }\n\n // we get here if none of the local projections matched the path\n\n const stat = await fsp.stat(localPath, { bigint: true });\n return createUploadImportHandle(\n localPath,\n this.signer,\n stat.size,\n stat.mtimeMs / 1000n // integer division\n ) as sdk.ImportFileHandleUpload & LocalImportFileHandle;\n }\n\n public async getStorageList(): Promise<sdk.StorageEntry[]> {\n const virtualStorages = [...this.virtualStoragesMap.values()].map((s) => ({\n name: s.name,\n handle: createLocalStorageHandle(s.name, s.root),\n initialFullPath: s.initialPath\n }));\n\n const otherStorages = Object.entries(this.storageIdToResourceId!).map(\n ([storageId, resourceId]) => ({\n name: storageId,\n handle: createRemoteStorageHandle(storageId, resourceId),\n initialFullPath: '', // we don't have any additional information from where to start browsing remote storages\n isInitialPathHome: false\n })\n );\n\n // root must be a storage so we can index any file,\n // but for UI it's enough\n // to have local virtual storage on *nix,\n // and local_disk_${drive} on Windows.\n const noRoot = otherStorages.filter((it) => it.name !== 'root');\n\n return [...virtualStorages, ...noRoot];\n }\n\n public async listFiles(\n storageHandle: sdk.StorageHandle,\n fullPath: string\n ): Promise<sdk.ListFilesResult> {\n const storageData = parseStorageHandle(storageHandle);\n\n if (storageData.isRemote) {\n const response = await this.lsClient.list(storageData, fullPath);\n return {\n entries: response.items.map((e) => ({\n type: e.isDir ? 'dir' : 'file',\n name: e.name,\n fullPath: e.fullName,\n handle: createIndexImportHandle(storageData.name, e.fullName)\n }))\n };\n } else {\n if (path.sep === '/' && fullPath === '') fullPath = '/';\n\n if (storageData.rootPath === '') {\n validateAbsolute(fullPath);\n }\n const lsRoot = path.isAbsolute(fullPath)\n ? fullPath\n : path.join(storageData.rootPath, fullPath);\n\n const entries: LsEntry[] = [];\n for await (const dirent of await fsp.opendir(lsRoot)) {\n if (!dirent.isFile() && !dirent.isDirectory()) continue;\n\n // We cannot use no dirent.fullPath no dirent.parentPath,\n // since the former is deprecated\n // and the later works differently on different versions.\n const absolutePath = path.join(lsRoot, dirent.name);\n\n entries.push({\n type: dirent.isFile() ? 'file' : 'dir',\n name: dirent.name,\n fullPath: absolutePath,\n handle: await this.getLocalFileHandle(absolutePath)\n });\n }\n\n return { entries };\n }\n }\n\n public async fileToImportHandle(file: sdk.FileLike): Promise<sdk.ImportFileHandle> {\n throw new Error(\n 'Not implemented. This method must be implemented and intercepted in desktop preload script.'\n );\n }\n\n public static async init(\n logger: MiLogger,\n client: PlClient,\n signer: Signer,\n /** Pl storages available locally */\n localProjections: LocalStorageProjection[],\n openFileDialogCallback: OpenFileDialogCallback,\n virtualStorages?: VirtualLocalStorageSpec[]\n ): Promise<LsDriver> {\n const lsClient = createLsFilesClient(client, logger);\n\n if (!virtualStorages) virtualStorages = await DefaultVirtualLocalStorages();\n\n // validating inputs\n for (const vp of virtualStorages) validateAbsolute(vp.root);\n for (const lp of localProjections) if (lp.localPath !== '') validateAbsolute(lp.localPath);\n\n // creating indexed maps for quick access\n const virtualStoragesMap = new Map(virtualStorages.map((s) => [s.name, s]));\n const localProjectionsMap = new Map(localProjections.map((s) => [s.storageId, s]));\n\n // validating there is no intersection\n if (\n new Set([...virtualStoragesMap.keys(), ...localProjectionsMap.keys()]).size !==\n virtualStoragesMap.size + localProjectionsMap.size\n )\n throw new Error(\n 'Intersection between local projection storage ids and virtual storages names detected.'\n );\n\n return new LsDriver(\n logger,\n lsClient,\n await doGetAvailableStorageIds(client),\n signer,\n virtualStoragesMap,\n localProjectionsMap,\n openFileDialogCallback\n );\n }\n}\n\nasync function doGetAvailableStorageIds(client: PlClient): Promise<Record<string, ResourceId>> {\n return client.withReadTx('GetAvailableStorageIds', async (tx) => {\n const lsProviderId = await tx.getResourceByName('LSProvider');\n const provider = await tx.getResourceData(lsProviderId, true);\n\n return providerToStorageIds(provider);\n });\n}\n\nfunction providerToStorageIds(provider: ResourceData) {\n return Object.fromEntries(\n provider.fields\n .filter((f) => f.type == 'Dynamic' && isNotNullResourceId(f.value))\n .map((f) => [f.name.substring('storage/'.length), f.value as ResourceId])\n );\n}\n"],"names":["uploadapi$Type","MessageType","value","message","reflectionMergePartial","reader","length","options","target","writer","u","UnknownFieldHandler","uploadapi_Init$Type","uploadapi_Init_Request$Type","end","fieldNo","wireType","d","WireType","uploadapi_Init_Request","uploadapi_Init_Response$Type","e","i","uploadapi_Init_Response","uploadapi_UpdateProgress$Type","uploadapi_UpdateProgress_Request$Type","uploadapi_UpdateProgress_Request","uploadapi_UpdateProgress_Response$Type","uploadapi_UpdateProgress_Response","uploadapi_GetPartURL$Type","uploadapi_GetPartURL_Request$Type","uploadapi_GetPartURL_Request","uploadapi_GetPartURL_HTTPHeader$Type","uploadapi_GetPartURL_HTTPHeader","uploadapi_GetPartURL_Response$Type","uploadapi_GetPartURL_Response","uploadapi_Finalize$Type","uploadapi_Finalize_Request$Type","uploadapi_Finalize_Request","uploadapi_Finalize_Response$Type","uploadapi_Finalize_Response","Upload","ServiceType","UploadClient","_transport","__publicField","input","method","opt","stackIntercept","MTimeError","UnexpectedEOF","NetworkError","NoFileForUploading","ClientUpload","grpcTransport","httpClient","_","logger","id","type","init","addRTypeToMetadata","path","partNumber","partsOverall","expectedMTimeUnix","info","chunk","mTime","resp","request","body","chunkStart","chunkEnd","f","fs","len","pos","b","bytesRead","stat","position","bytesReadTotal","toUpload","uploaded","headers","name","Duration$Type","s","PbLong","text","nanosStr","json","typeofJsonValue","match","sign","secs","nanos","longSeconds","Duration","ProgressAPI$Type","ProgressAPI_Report$Type","ProgressAPI_Report","ProgressAPI_GetStatus$Type","ProgressAPI_GetStatus_Request$Type","ProgressAPI_GetStatus_Request","ProgressAPI_GetStatus_Response$Type","ProgressAPI_GetStatus_Response","ProgressAPI_RealtimeStatus$Type","ProgressAPI_RealtimeStatus_Request$Type","ProgressAPI_RealtimeStatus_Request","ProgressAPI_RealtimeStatus_Response$Type","ProgressAPI_RealtimeStatus_Response","Progress","ProgressClient","ClientProgress","client","status","report","notEmpty","updateIntervalMs","updateInterval","responses","DownloadAPI$Type","DownloadAPI_GetDownloadURL$Type","DownloadAPI_GetDownloadURL_Request$Type","DownloadAPI_GetDownloadURL_Request","DownloadAPI_GetDownloadURL_HTTPHeader$Type","DownloadAPI_GetDownloadURL_HTTPHeader","DownloadAPI_GetDownloadURL_Response$Type","DownloadAPI_GetDownloadURL_Response","Download","DownloadClient","NetworkError400","DownloadHelper","url","reqHeaders","signal","statusCode","webBody","Readable","textBody","beginning","validateAbsolute","p","storageProtocol","UnknownStorageError","WrongLocalFileUrl","ClientDownload","localProjections","lp","withAbort","downloadUrl","headersFromProto","fullPath","parseLocalFileUrl","size","fsp","localStorageIdsToRoot","parsed","storageId","storageRoot","localPath","Timestamp$Type","msg","ms","date","z","matches","Timestamp","LsAPI$Type","LsAPI_ListItem$Type","LsAPI_ListItem","LsAPI_List$Type","LsAPI_List_Request$Type","LsAPI_List_Request","LsAPI_List_Response$Type","LsAPI_List_Response","LS","LSClient","ClientLs","rInfo","StreamingAPI$Type","StreamingAPI_StreamBinary$Type","StreamingAPI_StreamBinary","StreamingAPI_ReadBinary$Type","StreamingAPI_ReadBinary","StreamingAPI_StreamText$Type","StreamingAPI_StreamText","StreamingAPI_ReadText$Type","StreamingAPI_ReadText","StreamingAPI_LastLines$Type","StreamingAPI_LastLines","StreamingAPI_Response$Type","StreamingAPI_Response","Streaming","StreamingClient","ClientLogs","rId","rType","lineCount","offsetBytes","searchStr","createDownloadClient","httpDispatcher","createLogsClient","createUploadProgressClient","createUploadBlobClient","createLsFilesClient","_client","_httpDispatcher","LongUpdater","onUpdate","sleepMs","Updater","scheduler","getStream","streamManagerId","tx","sm","stream","valErr","getField","isNullResourceId","mixcrProgressPrefix","mixcrProgressRegex","lineToProgress","line","stage","progress","eta","mixcrProgressFromLogs","lastLines","FilesCache","softSizeBytes","callerId","file","mapGet","result","freedBytes","mapEntries","created","LogsDriver","logsStreamDriver","downloadDriver","res","lines","ctx","Computable","streamManagerGetStream","isBlob","patternToSearch","handle","isLiveLogHandle","manager","_a","handleToData","liveHandleRegex","isReadyLogHandle","readyHandleRegex","resourceType","resourceVersion","resourceId","bigintToResourceId","dataToHandle","live","OnDemandBlobResourceSnapshot","rsSchema","DownloadDriver","clientDownload","clientLogs","saveDir","signer","ops","TaskProcessor","treeEntryToResourceInfo","randomUUID","isPlTreeEntry","makeResourceSnapshot","localHandleToPath","isLocalBlobHandle","read","isRemoteBlobHandle","remoteHandleToData","content","buffer","w","task","newTask","fPath","dataToLocalHandle","blob","OnDemandBlobHolder","dataToRemoteHandle","logGetter","newLogGetter","LastLinesGetter","r","blobId","toDelete","reason","ChangeSource","CallersCounter","helper.Updater","newLogs","getLastLines","fileOrDirExists","nLines","inStream","outStream","Writable","resolve","reject","rl","readline","Denque","os","Download$1","fileToWrite","DownloadAborted","sizeBytes","localHandleRegex","signature","remoteHandleRegex","ImportFileHandleUploadData","ImportFileHandleIndexData","ImportFileHandleData","UploadResourceSnapshot","IndexResourceSnapshot","makeBlobImportSnapshot","entryOrAccessor","node","isPlTreeEntryAccessor","UploadDriver","clientBlob","clientProgress","opts","PollingComputableHooks","handleResource","isProgressStable","blobExists","newValue","ProgressUpdater","nonRecoverableError","toNotify","asyncPool","n","nConcurrentPartsUpload","isUpload","isUploadSignMatch","isSignMatch","isResourceWasDeletedError","parts","partUploadFn","part","done","oldStatus","protoToStatus","stringifyWithResourceId","proto","LogsStreamDriver","LogGetter","resourceIdToString","logs","getter","DownloadUrlDriver","c","key","rmRFDir","sha256","createHash","withGunzip","URLAborted","fileExists","dirSize","gunzip","Transform","zlib","untar","tar","dir","files","sum","createIndexImportHandle","storageName","createUploadImportHandle","modificationTimeSeconds","data","parseUploadHandle","parseIndexHandle","parseStorageHandle","isRemoteStorageHandle","parseRemoteStorageHandle","isLocalStorageHandle","parseLocalStorageHandle","assertNever","createLocalStorageHandle","createRemoteStorageHandle","storageType","DefaultVirtualLocalStorages","home","homeDrive","util","exec","drive","isHomeDrive","LsDriver","lsClient","storageIdToResourceId","virtualStoragesMap","localProjectionsMap","openFileDialogCallback","range","isImportFileHandleIndex","handleData","localProjection","pathWithinStorage","virtualStorages","noRoot","it","storageHandle","storageData","lsRoot","entries","dirent","absolutePath","vp","doGetAvailableStorageIds","lsProviderId","provider","providerToStorageIds","isNotNullResourceId"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.ts","../src/clients/upload.ts","../src/proto/google/protobuf/duration.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.ts","../src/clients/progress.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.ts","../src/helpers/download.ts","../src/helpers/validate.ts","../src/clients/download.ts","../src/proto/google/protobuf/timestamp.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.ts","../src/clients/ls_api.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.ts","../src/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.ts","../src/clients/logs.ts","../src/clients/helpers.ts","../src/drivers/helpers/helpers.ts","../src/drivers/helpers/files_cache.ts","../src/drivers/logs.ts","../src/drivers/download_and_logs_blob.ts","../src/drivers/types.ts","../src/drivers/upload.ts","../src/drivers/logs_stream.ts","../src/drivers/download_url.ts","../src/drivers/helpers/ls_list_entry.ts","../src/drivers/helpers/ls_storage_entry.ts","../src/drivers/virtual_storages.ts","../src/drivers/ls.ts"],"sourcesContent":["// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi\n */\nexport interface uploadapi {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init\n */\nexport interface uploadapi_Init {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Request\n */\nexport interface uploadapi_Init_Request {\n /**\n * Id of upload resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Response\n */\nexport interface uploadapi_Init_Response {\n /**\n * Number of parts in this upload.\n * For parallel upload support, client can generate any number of part upload URLs\n * at the moment and upload them in parallel.\n * <parts_count> keeps the number of chunks supported by this upload.\n * The parts count is calculated from the planned size of the upload, controller\n * configuration and underlying storage restrictions.\n *\n * @generated from protobuf field: uint64 parts_count = 1;\n */\n partsCount: bigint;\n /**\n * List of IDs of parts that were already uploaded by client.\n * Helps client to recover upload and skip already done parts\n * after being interrupted in the middle of the upload\n * (say, because of the restart).\n * Parts enumeration starts from 1.\n *\n * @generated from protobuf field: repeated uint64 uploaded_parts = 2;\n */\n uploadedParts: bigint[];\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress\n */\nexport interface uploadapi_UpdateProgress {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request\n */\nexport interface uploadapi_UpdateProgress_Request {\n /**\n * Id of upload resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * Amount of bytes, uploaded since the earlier call to UpdateProgress.\n * This value is just blindly added to the 'bytes_processed' of progress report,\n * so other clients can see the upload progress.\n * If client uploads the data in several streams (several chunks in parallel), it\n * can safely send progress updates individually for each of the streams, just counting\n * bytes uploaded by particular stream.\n *\n * Negative value can be used to report about upload retry: when upload was interrupted,\n * part of the uploaded data is lost and require re-upload.\n *\n * @generated from protobuf field: int64 bytes_processed = 2;\n */\n bytesProcessed: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\n */\nexport interface uploadapi_UpdateProgress_Response {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL\n */\nexport interface uploadapi_GetPartURL {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request\n */\nexport interface uploadapi_GetPartURL_Request {\n /**\n * Id of upload resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * Part to be uploaded. It is responsibility of the Client to watch after already uploaded parts:\n * - client can request an URL for the same part twice (request -> request) without errors;\n * - client can request an URL for alrady uploaded part (request -> upload -> request) without errors.\n *\n * Parts enumeration starts from 1.\n *\n * @generated from protobuf field: uint64 part_number = 2;\n */\n partNumber: bigint;\n /**\n * Size of the part uploaded by client earlier. Allows controller to count upload progress\n * based on client's input.\n * Client is free to never sent this value (send zeroes in each request).\n *\n * @generated from protobuf field: uint64 uploaded_part_size = 3;\n */\n uploadedPartSize: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader\n */\nexport interface uploadapi_GetPartURL_HTTPHeader {\n /**\n * @generated from protobuf field: string Name = 1 [json_name = \"Name\"];\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2 [json_name = \"Value\"];\n */\n value: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response\n */\nexport interface uploadapi_GetPartURL_Response {\n /**\n * URL for chunk upload\n *\n * @generated from protobuf field: string upload_url = 1;\n */\n uploadUrl: string;\n /**\n * HTTP method to use for chunk upload, say 'PUT' or 'POST'.\n *\n * @generated from protobuf field: string method = 2;\n */\n method: string;\n /**\n * List of headers with their values, MANDATORY to be sent by the client for the upload.\n * The destination service (the one, that will handle upload request for specific part)\n * may reject the request if it would not keep the given headers.\n *\n * @generated from protobuf field: repeated MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader headers = 3;\n */\n headers: uploadapi_GetPartURL_HTTPHeader[];\n /**\n * The number of the _first_ byte in the chunk.\n * Absolute position from the start of the file ( file.seek(<chunk_start>, SEEK_START) ).\n * The client is expected to send [<chunk_start>; <chunk_end>) range.\n *\n * @generated from protobuf field: uint64 chunk_start = 4;\n */\n chunkStart: bigint;\n /**\n * The number of the byte _after_ the last to be sent in the chunk.\n * Absolute position from the start of the file.\n * The client is expected to send [<chunk_start>; <chunk_end>) range.\n *\n * @generated from protobuf field: uint64 chunk_end = 5;\n */\n chunkEnd: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize\n */\nexport interface uploadapi_Finalize {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Request\n */\nexport interface uploadapi_Finalize_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Response\n */\nexport interface uploadapi_Finalize_Response {}\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi$Type extends MessageType<uploadapi> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi', []);\n }\n create(value?: PartialMessage<uploadapi>): uploadapi {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi\n ): uploadapi {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi\n */\nexport const uploadapi = new uploadapi$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Init$Type extends MessageType<uploadapi_Init> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Init', []);\n }\n create(value?: PartialMessage<uploadapi_Init>): uploadapi_Init {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Init>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Init\n ): uploadapi_Init {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_Init,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Init\n */\nexport const uploadapi_Init = new uploadapi_Init$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Init_Request$Type extends MessageType<uploadapi_Init_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Init.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_Init_Request>\n ): uploadapi_Init_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Init_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Init_Request\n ): uploadapi_Init_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_Init_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Request\n */\nexport const uploadapi_Init_Request = new uploadapi_Init_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Init_Response$Type extends MessageType<uploadapi_Init_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Init.Response', [\n {\n no: 1,\n name: 'parts_count',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'uploaded_parts',\n kind: 'scalar',\n repeat: 1 /*RepeatType.PACKED*/,\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_Init_Response>\n ): uploadapi_Init_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.partsCount = 0n;\n message.uploadedParts = [];\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Init_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Init_Response\n ): uploadapi_Init_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 parts_count */ 1:\n message.partsCount = reader.uint64().toBigInt();\n break;\n case /* repeated uint64 uploaded_parts */ 2:\n if (wireType === WireType.LengthDelimited)\n for (let e = reader.int32() + reader.pos; reader.pos < e; )\n message.uploadedParts.push(reader.uint64().toBigInt());\n else message.uploadedParts.push(reader.uint64().toBigInt());\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_Init_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 parts_count = 1; */\n if (message.partsCount !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.partsCount);\n /* repeated uint64 uploaded_parts = 2; */\n if (message.uploadedParts.length) {\n writer.tag(2, WireType.LengthDelimited).fork();\n for (let i = 0; i < message.uploadedParts.length; i++)\n writer.uint64(message.uploadedParts[i]);\n writer.join();\n }\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Init.Response\n */\nexport const uploadapi_Init_Response = new uploadapi_Init_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_UpdateProgress$Type extends MessageType<uploadapi_UpdateProgress> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.UpdateProgress', []);\n }\n create(\n value?: PartialMessage<uploadapi_UpdateProgress>\n ): uploadapi_UpdateProgress {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_UpdateProgress\n ): uploadapi_UpdateProgress {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_UpdateProgress,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress\n */\nexport const uploadapi_UpdateProgress = new uploadapi_UpdateProgress$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_UpdateProgress_Request$Type extends MessageType<uploadapi_UpdateProgress_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'bytes_processed',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_UpdateProgress_Request>\n ): uploadapi_UpdateProgress_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.bytesProcessed = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_UpdateProgress_Request\n ): uploadapi_UpdateProgress_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 bytes_processed */ 2:\n message.bytesProcessed = reader.int64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_UpdateProgress_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 bytes_processed = 2; */\n if (message.bytesProcessed !== 0n)\n writer.tag(2, WireType.Varint).int64(message.bytesProcessed);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request\n */\nexport const uploadapi_UpdateProgress_Request =\n new uploadapi_UpdateProgress_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_UpdateProgress_Response$Type extends MessageType<uploadapi_UpdateProgress_Response> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response',\n []\n );\n }\n create(\n value?: PartialMessage<uploadapi_UpdateProgress_Response>\n ): uploadapi_UpdateProgress_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_UpdateProgress_Response\n ): uploadapi_UpdateProgress_Response {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_UpdateProgress_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\n */\nexport const uploadapi_UpdateProgress_Response =\n new uploadapi_UpdateProgress_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL$Type extends MessageType<uploadapi_GetPartURL> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL', []);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL>): uploadapi_GetPartURL {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL\n ): uploadapi_GetPartURL {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL\n */\nexport const uploadapi_GetPartURL = new uploadapi_GetPartURL$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL_Request$Type extends MessageType<uploadapi_GetPartURL_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'part_number',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'uploaded_part_size',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_GetPartURL_Request>\n ): uploadapi_GetPartURL_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.partNumber = 0n;\n message.uploadedPartSize = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL_Request\n ): uploadapi_GetPartURL_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* uint64 part_number */ 2:\n message.partNumber = reader.uint64().toBigInt();\n break;\n case /* uint64 uploaded_part_size */ 3:\n message.uploadedPartSize = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* uint64 part_number = 2; */\n if (message.partNumber !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.partNumber);\n /* uint64 uploaded_part_size = 3; */\n if (message.uploadedPartSize !== 0n)\n writer.tag(3, WireType.Varint).uint64(message.uploadedPartSize);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request\n */\nexport const uploadapi_GetPartURL_Request =\n new uploadapi_GetPartURL_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL_HTTPHeader$Type extends MessageType<uploadapi_GetPartURL_HTTPHeader> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader', [\n {\n no: 1,\n name: 'Name',\n kind: 'scalar',\n jsonName: 'Name',\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 2,\n name: 'Value',\n kind: 'scalar',\n jsonName: 'Value',\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_GetPartURL_HTTPHeader>\n ): uploadapi_GetPartURL_HTTPHeader {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.name = '';\n message.value = '';\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_HTTPHeader>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL_HTTPHeader\n ): uploadapi_GetPartURL_HTTPHeader {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string Name = 1 [json_name = \"Name\"];*/ 1:\n message.name = reader.string();\n break;\n case /* string Value = 2 [json_name = \"Value\"];*/ 2:\n message.value = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL_HTTPHeader,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string Name = 1 [json_name = \"Name\"]; */\n if (message.name !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2 [json_name = \"Value\"]; */\n if (message.value !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.value);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader\n */\nexport const uploadapi_GetPartURL_HTTPHeader =\n new uploadapi_GetPartURL_HTTPHeader$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_GetPartURL_Response$Type extends MessageType<uploadapi_GetPartURL_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response', [\n { no: 1, name: 'upload_url', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: 'method', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n {\n no: 3,\n name: 'headers',\n kind: 'message',\n repeat: 1 /*RepeatType.PACKED*/,\n T: () => uploadapi_GetPartURL_HTTPHeader\n },\n {\n no: 4,\n name: 'chunk_start',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 5,\n name: 'chunk_end',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_GetPartURL_Response>\n ): uploadapi_GetPartURL_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.uploadUrl = '';\n message.method = '';\n message.headers = [];\n message.chunkStart = 0n;\n message.chunkEnd = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_GetPartURL_Response\n ): uploadapi_GetPartURL_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string upload_url */ 1:\n message.uploadUrl = reader.string();\n break;\n case /* string method */ 2:\n message.method = reader.string();\n break;\n case /* repeated MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader headers */ 3:\n message.headers.push(\n uploadapi_GetPartURL_HTTPHeader.internalBinaryRead(\n reader,\n reader.uint32(),\n options\n )\n );\n break;\n case /* uint64 chunk_start */ 4:\n message.chunkStart = reader.uint64().toBigInt();\n break;\n case /* uint64 chunk_end */ 5:\n message.chunkEnd = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_GetPartURL_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string upload_url = 1; */\n if (message.uploadUrl !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.uploadUrl);\n /* string method = 2; */\n if (message.method !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.method);\n /* repeated MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader headers = 3; */\n for (let i = 0; i < message.headers.length; i++)\n uploadapi_GetPartURL_HTTPHeader\n .internalBinaryWrite(\n message.headers[i],\n writer.tag(3, WireType.LengthDelimited).fork(),\n options\n )\n .join();\n /* uint64 chunk_start = 4; */\n if (message.chunkStart !== 0n)\n writer.tag(4, WireType.Varint).uint64(message.chunkStart);\n /* uint64 chunk_end = 5; */\n if (message.chunkEnd !== 0n)\n writer.tag(5, WireType.Varint).uint64(message.chunkEnd);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response\n */\nexport const uploadapi_GetPartURL_Response =\n new uploadapi_GetPartURL_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Finalize$Type extends MessageType<uploadapi_Finalize> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Finalize', []);\n }\n create(value?: PartialMessage<uploadapi_Finalize>): uploadapi_Finalize {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Finalize>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Finalize\n ): uploadapi_Finalize {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_Finalize,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize\n */\nexport const uploadapi_Finalize = new uploadapi_Finalize$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Finalize_Request$Type extends MessageType<uploadapi_Finalize_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Finalize.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<uploadapi_Finalize_Request>\n ): uploadapi_Finalize_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Finalize_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Finalize_Request\n ): uploadapi_Finalize_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: uploadapi_Finalize_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Request\n */\nexport const uploadapi_Finalize_Request = new uploadapi_Finalize_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass uploadapi_Finalize_Response$Type extends MessageType<uploadapi_Finalize_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.uploadapi.Finalize.Response', []);\n }\n create(\n value?: PartialMessage<uploadapi_Finalize_Response>\n ): uploadapi_Finalize_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<uploadapi_Finalize_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: uploadapi_Finalize_Response\n ): uploadapi_Finalize_Response {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: uploadapi_Finalize_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Response\n */\nexport const uploadapi_Finalize_Response =\n new uploadapi_Finalize_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport const Upload = new ServiceType(\n 'MiLaboratories.Controller.Shared.Upload',\n [\n {\n name: 'Init',\n options: {},\n I: uploadapi_Init_Request,\n O: uploadapi_Init_Response\n },\n {\n name: 'GetPartURL',\n options: {},\n I: uploadapi_GetPartURL_Request,\n O: uploadapi_GetPartURL_Response\n },\n {\n name: 'UpdateProgress',\n options: {},\n I: uploadapi_UpdateProgress_Request,\n O: uploadapi_UpdateProgress_Response\n },\n {\n name: 'Finalize',\n options: {},\n I: uploadapi_Finalize_Request,\n O: uploadapi_Finalize_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Upload } from './protocol';\nimport type { uploadapi_Finalize_Response } from './protocol';\nimport type { uploadapi_Finalize_Request } from './protocol';\nimport type { uploadapi_UpdateProgress_Response } from './protocol';\nimport type { uploadapi_UpdateProgress_Request } from './protocol';\nimport type { uploadapi_GetPartURL_Response } from './protocol';\nimport type { uploadapi_GetPartURL_Request } from './protocol';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { uploadapi_Init_Response } from './protocol';\nimport type { uploadapi_Init_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Upload provides access to data upload feature, allowing clients to uplad data to Platforma.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport interface IUploadClient {\n /**\n *\n * Init upload, making controller to do all required preparation steps.\n *\n *\n * @generated from protobuf rpc: Init(MiLaboratories.Controller.Shared.uploadapi.Init.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Init.Response);\n */\n init(\n input: uploadapi_Init_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Init_Request, uploadapi_Init_Response>;\n /**\n *\n * GetPartURL provides URL for uploading chunk of the data.\n * Clients are expected to put their data directly to the given location.\n *\n *\n * @generated from protobuf rpc: GetPartURL(MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request) returns (MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response);\n */\n getPartURL(\n input: uploadapi_GetPartURL_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response>;\n /**\n *\n * UpdateProgress of the upload, so other clients can see how it is going.\n *\n *\n * @generated from protobuf rpc: UpdateProgress(MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request) returns (MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response);\n */\n updateProgress(\n input: uploadapi_UpdateProgress_Request,\n options?: RpcOptions\n ): UnaryCall<\n uploadapi_UpdateProgress_Request,\n uploadapi_UpdateProgress_Response\n >;\n /**\n *\n * Finalize informs Controller that the upload process is done.\n * Returns an error, if the total size of all uploaded chunks is not equal to\n * size of the upload given in Init.\n *\n *\n * @generated from protobuf rpc: Finalize(MiLaboratories.Controller.Shared.uploadapi.Finalize.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Finalize.Response);\n */\n finalize(\n input: uploadapi_Finalize_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Finalize_Request, uploadapi_Finalize_Response>;\n}\n/**\n *\n * Upload provides access to data upload feature, allowing clients to uplad data to Platforma.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport class UploadClient implements IUploadClient, ServiceInfo {\n typeName = Upload.typeName;\n methods = Upload.methods;\n options = Upload.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n *\n * Init upload, making controller to do all required preparation steps.\n *\n *\n * @generated from protobuf rpc: Init(MiLaboratories.Controller.Shared.uploadapi.Init.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Init.Response);\n */\n init(\n input: uploadapi_Init_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Init_Request, uploadapi_Init_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_Init_Request, uploadapi_Init_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n *\n * GetPartURL provides URL for uploading chunk of the data.\n * Clients are expected to put their data directly to the given location.\n *\n *\n * @generated from protobuf rpc: GetPartURL(MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request) returns (MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response);\n */\n getPartURL(\n input: uploadapi_GetPartURL_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response> {\n const method = this.methods[1],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n uploadapi_GetPartURL_Request,\n uploadapi_GetPartURL_Response\n >('unary', this._transport, method, opt, input);\n }\n /**\n *\n * UpdateProgress of the upload, so other clients can see how it is going.\n *\n *\n * @generated from protobuf rpc: UpdateProgress(MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request) returns (MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response);\n */\n updateProgress(\n input: uploadapi_UpdateProgress_Request,\n options?: RpcOptions\n ): UnaryCall<\n uploadapi_UpdateProgress_Request,\n uploadapi_UpdateProgress_Response\n > {\n const method = this.methods[2],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n uploadapi_UpdateProgress_Request,\n uploadapi_UpdateProgress_Response\n >('unary', this._transport, method, opt, input);\n }\n /**\n *\n * Finalize informs Controller that the upload process is done.\n * Returns an error, if the total size of all uploaded chunks is not equal to\n * size of the upload given in Init.\n *\n *\n * @generated from protobuf rpc: Finalize(MiLaboratories.Controller.Shared.uploadapi.Finalize.Request) returns (MiLaboratories.Controller.Shared.uploadapi.Finalize.Response);\n */\n finalize(\n input: uploadapi_Finalize_Request,\n options?: RpcOptions\n ): UnaryCall<uploadapi_Finalize_Request, uploadapi_Finalize_Response> {\n const method = this.methods[3],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n uploadapi_Finalize_Request,\n uploadapi_Finalize_Response\n >('unary', this._transport, method, opt, input);\n }\n}\n","import * as fs from 'node:fs/promises';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { PlClient, addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { UploadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client';\nimport { MiLogger } from '@milaboratories/ts-helpers';\nimport { Dispatcher, request } from 'undici';\nimport { uploadapi_GetPartURL_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class MTimeError extends Error {}\n\nexport class UnexpectedEOF extends Error {}\n\nexport class NetworkError extends Error {}\n\nexport class NoFileForUploading extends Error {}\n\n/** Low-level client for grpc uploadapi.\n * The user should pass here a concrete BlobUpload/<storageId> resource,\n * it can be got from handle field of BlobUpload. */\nexport class ClientUpload {\n private readonly grpcClient: UploadClient;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n public readonly httpClient: Dispatcher,\n _: PlClient,\n public readonly logger: MiLogger\n ) {\n this.grpcClient = new UploadClient(this.grpcTransport);\n }\n\n close() {}\n\n public async initUpload({ id, type }: ResourceInfo, options?: RpcOptions): Promise<bigint[]> {\n const init = await this.grpcClient.init({ resourceId: id }, addRTypeToMetadata(type, options));\n return this.partsToUpload(init.response);\n }\n\n public async partUpload(\n { id, type }: ResourceInfo,\n path: string,\n partNumber: bigint,\n partsOverall: number,\n expectedMTimeUnix: bigint,\n options?: RpcOptions\n ) {\n const info = await this.grpcClient.getPartURL(\n {\n resourceId: id,\n partNumber: partNumber,\n uploadedPartSize: 0n // we update progress as a separate call later.\n },\n addRTypeToMetadata(type, options)\n ).response;\n\n const { chunk, mTime } = await this.readChunk(path, info.chunkStart, info.chunkEnd);\n if (mTime > expectedMTimeUnix) {\n throw new MTimeError(\n 'file was modified, expected mtime: ' + expectedMTimeUnix + ', got: ' + mTime + '.'\n );\n }\n\n const resp = await request(info.uploadUrl, this.prepareUploadOpts(info, chunk));\n\n const body = await resp.body.text();\n this.logger.info(\n `uploaded chunk ${partNumber} from ${partsOverall} of resource: ${id},` +\n ` response: '${body.toString()}', ` +\n `status code: ${resp.statusCode}`\n );\n\n if (resp.statusCode != 200) {\n throw new NetworkError(\n `response is not ok, status code: ${resp.statusCode},` +\n ` body: ${body}, headers: ${resp.headers}, url: ${info.uploadUrl}`\n );\n }\n\n await this.grpcClient.updateProgress(\n {\n resourceId: id,\n bytesProcessed: info.chunkEnd - info.chunkStart\n },\n addRTypeToMetadata(type, options)\n );\n }\n\n public async finalizeUpload({ id, type }: ResourceInfo, options?: RpcOptions) {\n return await this.grpcClient.finalize({ resourceId: id }, addRTypeToMetadata(type, options));\n }\n\n private async readChunk(\n path: string,\n chunkStart: bigint,\n chunkEnd: bigint\n ): Promise<{ chunk: Buffer; mTime: bigint }> {\n let f: fs.FileHandle | undefined;\n try {\n f = await fs.open(path);\n const len = Number(chunkEnd - chunkStart);\n const pos = Number(chunkStart);\n const b = Buffer.alloc(len);\n const bytesRead = await this.readBytesFromPosition(f, b, len, pos);\n\n const stat = await fs.stat(path);\n\n return {\n chunk: b.subarray(0, bytesRead),\n mTime: BigInt(Math.floor(stat.mtimeMs / 1000))\n };\n } catch (e: any) {\n if (e.code == 'ENOENT')\n throw new NoFileForUploading(`there is no file ${path} for uploading`);\n throw e;\n } finally {\n f?.close();\n }\n }\n\n /** Read len bytes from a given position. The reason the method exists\n is that FileHandle.read can read less bytes than it's needed. */\n async readBytesFromPosition(f: fs.FileHandle, b: Buffer, len: number, position: number) {\n let bytesReadTotal = 0;\n while (bytesReadTotal < len) {\n const { bytesRead } = await f.read(\n b,\n bytesReadTotal,\n len - bytesReadTotal,\n position + bytesReadTotal\n );\n if (bytesRead === 0) {\n throw new UnexpectedEOF('file ended earlier than expected.');\n }\n bytesReadTotal += bytesRead;\n }\n\n return bytesReadTotal;\n }\n\n /** Calculates parts that need to be uploaded from the parts that were\n * already uploaded. */\n private partsToUpload(info: { partsCount: bigint; uploadedParts: bigint[] }): bigint[] {\n const toUpload: bigint[] = [];\n const uploaded = new Set(info.uploadedParts);\n\n for (let i = 1n; i <= info.partsCount; i++) {\n if (!uploaded.has(i)) toUpload.push(i);\n }\n\n return toUpload;\n }\n\n private prepareUploadOpts(info: uploadapi_GetPartURL_Response, chunk: Buffer): any {\n const headers = info.headers.map(({ name, value }) => [name, value]);\n\n return {\n dispatcher: this.httpClient,\n body: chunk,\n headers: Object.fromEntries(headers),\n method: info.method.toUpperCase() as Dispatcher.HttpMethod\n };\n }\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"google/protobuf/duration.proto\" (package \"google.protobuf\", syntax proto3)\n// tslint:disable\n//\n// Protocol Buffers - Google's data interchange format\n// Copyright 2008 Google Inc. All rights reserved.\n// https://developers.google.com/protocol-buffers/\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { typeofJsonValue } from '@protobuf-ts/runtime';\nimport type { JsonValue } from '@protobuf-ts/runtime';\nimport type { JsonReadOptions } from '@protobuf-ts/runtime';\nimport type { JsonWriteOptions } from '@protobuf-ts/runtime';\nimport { PbLong } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * A Duration represents a signed, fixed-length span of time represented\n * as a count of seconds and fractions of seconds at nanosecond\n * resolution. It is independent of any calendar and concepts like \"day\"\n * or \"month\". It is related to Timestamp in that the difference between\n * two Timestamp values is a Duration and it can be added or subtracted\n * from a Timestamp. Range is approximately +-10,000 years.\n *\n * # Examples\n *\n * Example 1: Compute Duration from two Timestamps in pseudo code.\n *\n * Timestamp start = ...;\n * Timestamp end = ...;\n * Duration duration = ...;\n *\n * duration.seconds = end.seconds - start.seconds;\n * duration.nanos = end.nanos - start.nanos;\n *\n * if (duration.seconds < 0 && duration.nanos > 0) {\n * duration.seconds += 1;\n * duration.nanos -= 1000000000;\n * } else if (duration.seconds > 0 && duration.nanos < 0) {\n * duration.seconds -= 1;\n * duration.nanos += 1000000000;\n * }\n *\n * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.\n *\n * Timestamp start = ...;\n * Duration duration = ...;\n * Timestamp end = ...;\n *\n * end.seconds = start.seconds + duration.seconds;\n * end.nanos = start.nanos + duration.nanos;\n *\n * if (end.nanos < 0) {\n * end.seconds -= 1;\n * end.nanos += 1000000000;\n * } else if (end.nanos >= 1000000000) {\n * end.seconds += 1;\n * end.nanos -= 1000000000;\n * }\n *\n * Example 3: Compute Duration from datetime.timedelta in Python.\n *\n * td = datetime.timedelta(days=3, minutes=10)\n * duration = Duration()\n * duration.FromTimedelta(td)\n *\n * # JSON Mapping\n *\n * In JSON format, the Duration type is encoded as a string rather than an\n * object, where the string ends in the suffix \"s\" (indicating seconds) and\n * is preceded by the number of seconds, with nanoseconds expressed as\n * fractional seconds. For example, 3 seconds with 0 nanoseconds should be\n * encoded in JSON format as \"3s\", while 3 seconds and 1 nanosecond should\n * be expressed in JSON format as \"3.000000001s\", and 3 seconds and 1\n * microsecond should be expressed in JSON format as \"3.000001s\".\n *\n *\n *\n * @generated from protobuf message google.protobuf.Duration\n */\nexport interface Duration {\n /**\n * Signed seconds of the span of time. Must be from -315,576,000,000\n * to +315,576,000,000 inclusive. Note: these bounds are computed from:\n * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years\n *\n * @generated from protobuf field: int64 seconds = 1;\n */\n seconds: bigint;\n /**\n * Signed fractions of a second at nanosecond resolution of the span\n * of time. Durations less than one second are represented with a 0\n * `seconds` field and a positive or negative `nanos` field. For durations\n * of one second or more, a non-zero value for the `nanos` field must be\n * of the same sign as the `seconds` field. Must be from -999,999,999\n * to +999,999,999 inclusive.\n *\n * @generated from protobuf field: int32 nanos = 2;\n */\n nanos: number;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass Duration$Type extends MessageType<Duration> {\n constructor() {\n super('google.protobuf.Duration', [\n {\n no: 1,\n name: 'seconds',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'nanos', kind: 'scalar', T: 5 /*ScalarType.INT32*/ }\n ]);\n }\n /**\n * Encode `Duration` to JSON string like \"3.000001s\".\n */\n internalJsonWrite(message: Duration, options: JsonWriteOptions): JsonValue {\n let s = PbLong.from(message.seconds).toNumber();\n if (s > 315576000000 || s < -315576000000)\n throw new Error('Duration value out of range.');\n let text = message.seconds.toString();\n if (s === 0 && message.nanos < 0) text = '-' + text;\n if (message.nanos !== 0) {\n let nanosStr = Math.abs(message.nanos).toString();\n nanosStr = '0'.repeat(9 - nanosStr.length) + nanosStr;\n if (nanosStr.substring(3) === '000000')\n nanosStr = nanosStr.substring(0, 3);\n else if (nanosStr.substring(6) === '000')\n nanosStr = nanosStr.substring(0, 6);\n text += '.' + nanosStr;\n }\n return text + 's';\n }\n /**\n * Decode `Duration` from JSON string like \"3.000001s\"\n */\n internalJsonRead(\n json: JsonValue,\n options: JsonReadOptions,\n target?: Duration\n ): Duration {\n if (typeof json !== 'string')\n throw new Error(\n 'Unable to parse Duration from JSON ' +\n typeofJsonValue(json) +\n '. Expected string.'\n );\n let match = json.match(/^(-?)([0-9]+)(?:\\.([0-9]+))?s/);\n if (match === null)\n throw new Error(\n 'Unable to parse Duration from JSON string. Invalid format.'\n );\n if (!target) target = this.create();\n let [, sign, secs, nanos] = match;\n let longSeconds = PbLong.from(sign + secs);\n if (\n longSeconds.toNumber() > 315576000000 ||\n longSeconds.toNumber() < -315576000000\n )\n throw new Error(\n 'Unable to parse Duration from JSON string. Value out of range.'\n );\n target.seconds = longSeconds.toBigInt();\n if (typeof nanos == 'string') {\n let nanosStr = sign + nanos + '0'.repeat(9 - nanos.length);\n target.nanos = parseInt(nanosStr);\n }\n return target;\n }\n create(value?: PartialMessage<Duration>): Duration {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.seconds = 0n;\n message.nanos = 0;\n if (value !== undefined)\n reflectionMergePartial<Duration>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: Duration\n ): Duration {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* int64 seconds */ 1:\n message.seconds = reader.int64().toBigInt();\n break;\n case /* int32 nanos */ 2:\n message.nanos = reader.int32();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: Duration,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* int64 seconds = 1; */\n if (message.seconds !== 0n)\n writer.tag(1, WireType.Varint).int64(message.seconds);\n /* int32 nanos = 2; */\n if (message.nanos !== 0)\n writer.tag(2, WireType.Varint).int32(message.nanos);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message google.protobuf.Duration\n */\nexport const Duration = new Duration$Type();\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\nimport { Duration } from '../../../../../../../google/protobuf/duration';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI\n */\nexport interface ProgressAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.Report\n */\nexport interface ProgressAPI_Report {\n /**\n * @generated from protobuf field: float progress = 1;\n */\n progress: number;\n /**\n * @generated from protobuf field: uint64 bytes_processed = 2;\n */\n bytesProcessed: bigint;\n /**\n * @generated from protobuf field: uint64 bytes_total = 3;\n */\n bytesTotal: bigint;\n /**\n * @generated from protobuf field: bool done = 4;\n */\n done: boolean;\n /**\n * Name of current progress stage (if any)\n *\n * @generated from protobuf field: string name = 5;\n */\n name: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus\n */\nexport interface ProgressAPI_GetStatus {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request\n */\nexport interface ProgressAPI_GetStatus_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response\n */\nexport interface ProgressAPI_GetStatus_Response {\n /**\n * @generated from protobuf field: MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1;\n */\n report?: ProgressAPI_Report;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus\n */\nexport interface ProgressAPI_RealtimeStatus {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\n */\nexport interface ProgressAPI_RealtimeStatus_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * @generated from protobuf field: google.protobuf.Duration update_interval = 2;\n */\n updateInterval?: Duration;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\n */\nexport interface ProgressAPI_RealtimeStatus_Response {\n /**\n * @generated from protobuf field: MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1;\n */\n report?: ProgressAPI_Report;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI$Type extends MessageType<ProgressAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI', []);\n }\n create(value?: PartialMessage<ProgressAPI>): ProgressAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI\n ): ProgressAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: ProgressAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI\n */\nexport const ProgressAPI = new ProgressAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_Report$Type extends MessageType<ProgressAPI_Report> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.Report', [\n { no: 1, name: 'progress', kind: 'scalar', T: 2 /*ScalarType.FLOAT*/ },\n {\n no: 2,\n name: 'bytes_processed',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'bytes_total',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 4, name: 'done', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },\n { no: 5, name: 'name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_Report>): ProgressAPI_Report {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.progress = 0;\n message.bytesProcessed = 0n;\n message.bytesTotal = 0n;\n message.done = false;\n message.name = '';\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_Report>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_Report\n ): ProgressAPI_Report {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* float progress */ 1:\n message.progress = reader.float();\n break;\n case /* uint64 bytes_processed */ 2:\n message.bytesProcessed = reader.uint64().toBigInt();\n break;\n case /* uint64 bytes_total */ 3:\n message.bytesTotal = reader.uint64().toBigInt();\n break;\n case /* bool done */ 4:\n message.done = reader.bool();\n break;\n case /* string name */ 5:\n message.name = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_Report,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* float progress = 1; */\n if (message.progress !== 0)\n writer.tag(1, WireType.Bit32).float(message.progress);\n /* uint64 bytes_processed = 2; */\n if (message.bytesProcessed !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.bytesProcessed);\n /* uint64 bytes_total = 3; */\n if (message.bytesTotal !== 0n)\n writer.tag(3, WireType.Varint).uint64(message.bytesTotal);\n /* bool done = 4; */\n if (message.done !== false)\n writer.tag(4, WireType.Varint).bool(message.done);\n /* string name = 5; */\n if (message.name !== '')\n writer.tag(5, WireType.LengthDelimited).string(message.name);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.Report\n */\nexport const ProgressAPI_Report = new ProgressAPI_Report$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_GetStatus$Type extends MessageType<ProgressAPI_GetStatus> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.GetStatus', []);\n }\n create(value?: PartialMessage<ProgressAPI_GetStatus>): ProgressAPI_GetStatus {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_GetStatus\n ): ProgressAPI_GetStatus {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: ProgressAPI_GetStatus,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus\n */\nexport const ProgressAPI_GetStatus = new ProgressAPI_GetStatus$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_GetStatus_Request$Type extends MessageType<ProgressAPI_GetStatus_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<ProgressAPI_GetStatus_Request>\n ): ProgressAPI_GetStatus_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_GetStatus_Request\n ): ProgressAPI_GetStatus_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_GetStatus_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request\n */\nexport const ProgressAPI_GetStatus_Request =\n new ProgressAPI_GetStatus_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_GetStatus_Response$Type extends MessageType<ProgressAPI_GetStatus_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response', [\n { no: 1, name: 'report', kind: 'message', T: () => ProgressAPI_Report }\n ]);\n }\n create(\n value?: PartialMessage<ProgressAPI_GetStatus_Response>\n ): ProgressAPI_GetStatus_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_GetStatus_Response\n ): ProgressAPI_GetStatus_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* MiLaboratories.Controller.Shared.ProgressAPI.Report report */ 1:\n message.report = ProgressAPI_Report.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.report\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_GetStatus_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(\n message.report,\n writer.tag(1, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response\n */\nexport const ProgressAPI_GetStatus_Response =\n new ProgressAPI_GetStatus_Response$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_RealtimeStatus$Type extends MessageType<ProgressAPI_RealtimeStatus> {\n constructor() {\n super('MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus', []);\n }\n create(\n value?: PartialMessage<ProgressAPI_RealtimeStatus>\n ): ProgressAPI_RealtimeStatus {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_RealtimeStatus\n ): ProgressAPI_RealtimeStatus {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: ProgressAPI_RealtimeStatus,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus\n */\nexport const ProgressAPI_RealtimeStatus = new ProgressAPI_RealtimeStatus$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_RealtimeStatus_Request$Type extends MessageType<ProgressAPI_RealtimeStatus_Request> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request',\n [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'update_interval', kind: 'message', T: () => Duration }\n ]\n );\n }\n create(\n value?: PartialMessage<ProgressAPI_RealtimeStatus_Request>\n ): ProgressAPI_RealtimeStatus_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_RealtimeStatus_Request\n ): ProgressAPI_RealtimeStatus_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* google.protobuf.Duration update_interval */ 2:\n message.updateInterval = Duration.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.updateInterval\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_RealtimeStatus_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* google.protobuf.Duration update_interval = 2; */\n if (message.updateInterval)\n Duration.internalBinaryWrite(\n message.updateInterval,\n writer.tag(2, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\n */\nexport const ProgressAPI_RealtimeStatus_Request =\n new ProgressAPI_RealtimeStatus_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass ProgressAPI_RealtimeStatus_Response$Type extends MessageType<ProgressAPI_RealtimeStatus_Response> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response',\n [{ no: 1, name: 'report', kind: 'message', T: () => ProgressAPI_Report }]\n );\n }\n create(\n value?: PartialMessage<ProgressAPI_RealtimeStatus_Response>\n ): ProgressAPI_RealtimeStatus_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: ProgressAPI_RealtimeStatus_Response\n ): ProgressAPI_RealtimeStatus_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* MiLaboratories.Controller.Shared.ProgressAPI.Report report */ 1:\n message.report = ProgressAPI_Report.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.report\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: ProgressAPI_RealtimeStatus_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(\n message.report,\n writer.tag(1, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\n */\nexport const ProgressAPI_RealtimeStatus_Response =\n new ProgressAPI_RealtimeStatus_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport const Progress = new ServiceType(\n 'MiLaboratories.Controller.Shared.Progress',\n [\n {\n name: 'GetStatus',\n options: {\n 'google.api.http': { get: '/resources/{resource_id}/get-progress' }\n },\n I: ProgressAPI_GetStatus_Request,\n O: ProgressAPI_GetStatus_Response\n },\n {\n name: 'RealtimeStatus',\n serverStreaming: true,\n options: {},\n I: ProgressAPI_RealtimeStatus_Request,\n O: ProgressAPI_RealtimeStatus_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Progress } from './protocol';\nimport type { ProgressAPI_RealtimeStatus_Response } from './protocol';\nimport type { ProgressAPI_RealtimeStatus_Request } from './protocol';\nimport type { ServerStreamingCall } from '@protobuf-ts/runtime-rpc';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { ProgressAPI_GetStatus_Response } from './protocol';\nimport type { ProgressAPI_GetStatus_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Progress provides access to progress of any long-running process associated with resource.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport interface IProgressClient {\n /**\n * @generated from protobuf rpc: GetStatus(MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request) returns (MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response);\n */\n getStatus(\n input: ProgressAPI_GetStatus_Request,\n options?: RpcOptions\n ): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response>;\n /**\n * @generated from protobuf rpc: RealtimeStatus(MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request) returns (stream MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response);\n */\n realtimeStatus(\n input: ProgressAPI_RealtimeStatus_Request,\n options?: RpcOptions\n ): ServerStreamingCall<\n ProgressAPI_RealtimeStatus_Request,\n ProgressAPI_RealtimeStatus_Response\n >;\n}\n/**\n *\n * Progress provides access to progress of any long-running process associated with resource.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport class ProgressClient implements IProgressClient, ServiceInfo {\n typeName = Progress.typeName;\n methods = Progress.methods;\n options = Progress.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * @generated from protobuf rpc: GetStatus(MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request) returns (MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response);\n */\n getStatus(\n input: ProgressAPI_GetStatus_Request,\n options?: RpcOptions\n ): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n ProgressAPI_GetStatus_Request,\n ProgressAPI_GetStatus_Response\n >('unary', this._transport, method, opt, input);\n }\n /**\n * @generated from protobuf rpc: RealtimeStatus(MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request) returns (stream MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response);\n */\n realtimeStatus(\n input: ProgressAPI_RealtimeStatus_Request,\n options?: RpcOptions\n ): ServerStreamingCall<\n ProgressAPI_RealtimeStatus_Request,\n ProgressAPI_RealtimeStatus_Response\n > {\n const method = this.methods[1],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n ProgressAPI_RealtimeStatus_Request,\n ProgressAPI_RealtimeStatus_Response\n >('serverStreaming', this._transport, method, opt, input);\n }\n}\n","import { ProgressClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { Duration } from '../proto/google/protobuf/duration';\nimport { PlClient, addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { MiLogger, notEmpty } from '@milaboratories/ts-helpers';\nimport { Dispatcher } from 'undici';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport type ProgressStatus = {\n done: boolean;\n progress: number;\n bytesProcessed?: string;\n bytesTotal?: string;\n};\n\n// ClientProgress holds a grpc connection to the platform\n// but for Progress API service.\n// When blobs are transfered, one can got a status of transfering\n// using this API.\nexport class ClientProgress {\n public readonly grpcClient: ProgressClient;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n _: Dispatcher,\n public readonly client: PlClient,\n public readonly logger: MiLogger\n ) {\n this.grpcClient = new ProgressClient(this.grpcTransport);\n }\n\n close() {}\n\n /** getStatus gets a progress status by given rId and rType. */\n async getStatus({ id, type }: ResourceInfo, options?: RpcOptions): Promise<ProgressStatus> {\n const status = await this.grpcClient.getStatus(\n { resourceId: id },\n addRTypeToMetadata(type, options)\n );\n\n const report = notEmpty(status.response.report);\n\n return {\n done: report.done,\n progress: report.progress,\n bytesProcessed: String(report.bytesProcessed),\n bytesTotal: String(report.bytesTotal)\n };\n }\n\n // realtimeStatus returns a async generator that takes statuses from\n // GRPC stream every updateIntervalMs milliseconds.\n async *realtimeStatus(\n { id, type }: ResourceInfo,\n updateIntervalMs: number = 100,\n options?: RpcOptions\n ) {\n options = addRTypeToMetadata(type, options);\n\n const secs = Math.floor(updateIntervalMs / 1000);\n const nanos = (updateIntervalMs - secs * 1000) * 1000000;\n const updateInterval = Duration.create({\n seconds: BigInt(secs),\n nanos: nanos\n });\n\n try {\n const { responses } = this.grpcClient.realtimeStatus(\n {\n resourceId: id,\n updateInterval: updateInterval\n },\n options\n );\n\n yield* responses;\n } catch (e) {\n this.logger.warn('Failed to get realtime status' + e);\n throw e;\n }\n }\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI\n */\nexport interface DownloadAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL\n */\nexport interface DownloadAPI_GetDownloadURL {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\n */\nexport interface DownloadAPI_GetDownloadURL_Request {\n /**\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\n */\nexport interface DownloadAPI_GetDownloadURL_HTTPHeader {\n /**\n * @generated from protobuf field: string Name = 1 [json_name = \"Name\"];\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2 [json_name = \"Value\"];\n */\n value: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\n */\nexport interface DownloadAPI_GetDownloadURL_Response {\n /**\n * @generated from protobuf field: string download_url = 1;\n */\n downloadUrl: string;\n /**\n * @generated from protobuf field: repeated MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader headers = 2;\n */\n headers: DownloadAPI_GetDownloadURL_HTTPHeader[];\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI$Type extends MessageType<DownloadAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.DownloadAPI', []);\n }\n create(value?: PartialMessage<DownloadAPI>): DownloadAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI\n ): DownloadAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: DownloadAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI\n */\nexport const DownloadAPI = new DownloadAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL$Type extends MessageType<DownloadAPI_GetDownloadURL> {\n constructor() {\n super('MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL', []);\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL>\n ): DownloadAPI_GetDownloadURL {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL\n ): DownloadAPI_GetDownloadURL {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL\n */\nexport const DownloadAPI_GetDownloadURL = new DownloadAPI_GetDownloadURL$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL_Request$Type extends MessageType<DownloadAPI_GetDownloadURL_Request> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request',\n [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]\n );\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL_Request>\n ): DownloadAPI_GetDownloadURL_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_Request>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL_Request\n ): DownloadAPI_GetDownloadURL_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\n */\nexport const DownloadAPI_GetDownloadURL_Request =\n new DownloadAPI_GetDownloadURL_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL_HTTPHeader$Type extends MessageType<DownloadAPI_GetDownloadURL_HTTPHeader> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader',\n [\n {\n no: 1,\n name: 'Name',\n kind: 'scalar',\n jsonName: 'Name',\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 2,\n name: 'Value',\n kind: 'scalar',\n jsonName: 'Value',\n T: 9 /*ScalarType.STRING*/\n }\n ]\n );\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL_HTTPHeader>\n ): DownloadAPI_GetDownloadURL_HTTPHeader {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.name = '';\n message.value = '';\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_HTTPHeader>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL_HTTPHeader\n ): DownloadAPI_GetDownloadURL_HTTPHeader {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string Name = 1 [json_name = \"Name\"];*/ 1:\n message.name = reader.string();\n break;\n case /* string Value = 2 [json_name = \"Value\"];*/ 2:\n message.value = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL_HTTPHeader,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string Name = 1 [json_name = \"Name\"]; */\n if (message.name !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2 [json_name = \"Value\"]; */\n if (message.value !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.value);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\n */\nexport const DownloadAPI_GetDownloadURL_HTTPHeader =\n new DownloadAPI_GetDownloadURL_HTTPHeader$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass DownloadAPI_GetDownloadURL_Response$Type extends MessageType<DownloadAPI_GetDownloadURL_Response> {\n constructor() {\n super(\n 'MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response',\n [\n {\n no: 1,\n name: 'download_url',\n kind: 'scalar',\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 2,\n name: 'headers',\n kind: 'message',\n repeat: 1 /*RepeatType.PACKED*/,\n T: () => DownloadAPI_GetDownloadURL_HTTPHeader\n }\n ]\n );\n }\n create(\n value?: PartialMessage<DownloadAPI_GetDownloadURL_Response>\n ): DownloadAPI_GetDownloadURL_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.downloadUrl = '';\n message.headers = [];\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_Response>(\n this,\n message,\n value\n );\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: DownloadAPI_GetDownloadURL_Response\n ): DownloadAPI_GetDownloadURL_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string download_url */ 1:\n message.downloadUrl = reader.string();\n break;\n case /* repeated MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader headers */ 2:\n message.headers.push(\n DownloadAPI_GetDownloadURL_HTTPHeader.internalBinaryRead(\n reader,\n reader.uint32(),\n options\n )\n );\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: DownloadAPI_GetDownloadURL_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string download_url = 1; */\n if (message.downloadUrl !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.downloadUrl);\n /* repeated MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader headers = 2; */\n for (let i = 0; i < message.headers.length; i++)\n DownloadAPI_GetDownloadURL_HTTPHeader.internalBinaryWrite(\n message.headers[i],\n writer.tag(2, WireType.LengthDelimited).fork(),\n options\n ).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\n */\nexport const DownloadAPI_GetDownloadURL_Response =\n new DownloadAPI_GetDownloadURL_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport const Download = new ServiceType(\n 'MiLaboratories.Controller.Shared.Download',\n [\n {\n name: 'GetDownloadURL',\n options: {\n 'google.api.http': { get: '/resources/{resource_id}/get-download-url' }\n },\n I: DownloadAPI_GetDownloadURL_Request,\n O: DownloadAPI_GetDownloadURL_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Download } from './protocol';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { DownloadAPI_GetDownloadURL_Response } from './protocol';\nimport type { DownloadAPI_GetDownloadURL_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Download provides access to any data, that can be downloaded via network.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport interface IDownloadClient {\n /**\n * @generated from protobuf rpc: GetDownloadURL(MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request) returns (MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response);\n */\n getDownloadURL(\n input: DownloadAPI_GetDownloadURL_Request,\n options?: RpcOptions\n ): UnaryCall<\n DownloadAPI_GetDownloadURL_Request,\n DownloadAPI_GetDownloadURL_Response\n >;\n}\n/**\n *\n * Download provides access to any data, that can be downloaded via network.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport class DownloadClient implements IDownloadClient, ServiceInfo {\n typeName = Download.typeName;\n methods = Download.methods;\n options = Download.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * @generated from protobuf rpc: GetDownloadURL(MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request) returns (MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response);\n */\n getDownloadURL(\n input: DownloadAPI_GetDownloadURL_Request,\n options?: RpcOptions\n ): UnaryCall<\n DownloadAPI_GetDownloadURL_Request,\n DownloadAPI_GetDownloadURL_Response\n > {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<\n DownloadAPI_GetDownloadURL_Request,\n DownloadAPI_GetDownloadURL_Response\n >('unary', this._transport, method, opt, input);\n }\n}\n","import { Dispatcher, request } from 'undici';\nimport { Readable } from 'node:stream';\nimport { ReadableStream } from 'node:stream/web';\nimport { text } from 'node:stream/consumers';\n\nexport interface DownloadResponse {\n content: ReadableStream;\n size: number;\n}\n\n/** Throws when a status code of the downloading URL was in range [400, 500). */\nexport class NetworkError400 extends Error {}\n\nexport class DownloadHelper {\n constructor(public readonly httpClient: Dispatcher) {}\n\n async downloadRemoteFile(\n url: string,\n reqHeaders: Record<string, string>,\n signal?: AbortSignal\n ): Promise<DownloadResponse> {\n const { statusCode, body, headers } = await request(url, {\n dispatcher: this.httpClient,\n headers: reqHeaders,\n signal\n });\n\n const webBody = Readable.toWeb(body);\n\n if (statusCode != 200) {\n const textBody = await text(webBody);\n const beginning = textBody.substring(0, Math.min(textBody.length, 1000));\n\n if (400 <= statusCode && statusCode < 500) {\n throw new NetworkError400(\n `Http error: statusCode: ${statusCode} url: ${url.toString()}, beginning of body: ${beginning}`\n );\n }\n\n throw new Error(`Http error: statusCode: ${statusCode} url: ${url.toString()}`);\n }\n\n return {\n content: webBody,\n size: Number(headers['content-length'])\n };\n }\n}\n","import path from 'node:path';\n\nexport function validateAbsolute(p: string): string {\n if (!path.isAbsolute(p)) throw new Error(`Path ${p} is not absolute.`);\n return p;\n}\n","import { Readable } from 'node:stream';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { DownloadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { MiLogger } from '@milaboratories/ts-helpers';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { Dispatcher } from 'undici';\nimport {\n DownloadAPI_GetDownloadURL_HTTPHeader,\n DownloadAPI_GetDownloadURL_Response\n} from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\nimport { DownloadHelper, DownloadResponse } from '../helpers/download';\nimport { LocalStorageProjection } from '../drivers/types';\nimport { validateAbsolute } from '../helpers/validate';\n\nconst storageProtocol = 'storage://';\n\nexport class UnknownStorageError extends Error {}\n\nexport class WrongLocalFileUrl extends Error {}\n\n/** Gets URLs for downloading from pl-core, parses them and reads or downloads\n * files locally and from the web. */\nexport class ClientDownload {\n public readonly grpcClient: DownloadClient;\n private readonly downloadHelper: DownloadHelper;\n private readonly localStorageIdsToRoot: Map<string, string>;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger,\n /** Pl storages available locally */\n localProjections: LocalStorageProjection[]\n ) {\n for (const lp of localProjections) if (lp.localPath !== '') validateAbsolute(lp.localPath);\n this.grpcClient = new DownloadClient(this.grpcTransport);\n this.downloadHelper = new DownloadHelper(httpClient);\n this.localStorageIdsToRoot = new Map(\n localProjections.map((lp) => [lp.storageId, lp.localPath])\n );\n }\n\n close() {}\n\n async getUrl(\n { id, type }: ResourceInfo,\n options?: RpcOptions,\n signal?: AbortSignal\n ): Promise<DownloadAPI_GetDownloadURL_Response> {\n const withAbort = options ?? {};\n withAbort.abort = signal;\n\n return await this.grpcClient.getDownloadURL(\n { resourceId: id },\n addRTypeToMetadata(type, withAbort)\n ).response;\n }\n\n async downloadBlob(\n info: ResourceInfo,\n options?: RpcOptions,\n signal?: AbortSignal\n ): Promise<DownloadResponse> {\n const { downloadUrl, headers } = await this.getUrl(info, options, signal);\n\n this.logger.info(`download from url ${downloadUrl}`);\n\n return this.isLocal(downloadUrl)\n ? await this.readLocalFile(downloadUrl)\n : await this.downloadHelper.downloadRemoteFile(\n downloadUrl,\n headersFromProto(headers),\n signal\n );\n }\n\n private isLocal = (url: string) => url.startsWith(storageProtocol);\n\n async readLocalFile(url: string): Promise<DownloadResponse> {\n const fullPath = parseLocalFileUrl(url, this.localStorageIdsToRoot);\n const stat = await fsp.stat(fullPath);\n const size = stat.size;\n\n return {\n content: Readable.toWeb(fs.createReadStream(fullPath)),\n size\n };\n }\n}\n\nexport function parseLocalFileUrl(url: string, localStorageIdsToRoot: Map<string, string>): string {\n const parsed = new URL(url);\n if (parsed.pathname == '')\n throw new WrongLocalFileUrl(`url for local filepath ${url} does not match url scheme`);\n\n const storageId = parsed.host;\n const storageRoot = localStorageIdsToRoot.get(storageId);\n if (storageRoot === undefined)\n throw new UnknownStorageError(`Unknown storage location: ${storageId}`);\n\n const localPath = decodeURIComponent(parsed.pathname.slice(1));\n const fullPath = storageRoot === '' ? localPath : path.join(storageRoot, localPath);\n\n return fullPath;\n}\n\nexport function headersFromProto(\n headers: DownloadAPI_GetDownloadURL_HTTPHeader[]\n): Record<string, string> {\n return Object.fromEntries(headers.map(({ name, value }) => [name, value]));\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"google/protobuf/timestamp.proto\" (package \"google.protobuf\", syntax proto3)\n// tslint:disable\n//\n// Protocol Buffers - Google's data interchange format\n// Copyright 2008 Google Inc. All rights reserved.\n// https://developers.google.com/protocol-buffers/\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n//\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { typeofJsonValue } from '@protobuf-ts/runtime';\nimport type { JsonValue } from '@protobuf-ts/runtime';\nimport type { JsonReadOptions } from '@protobuf-ts/runtime';\nimport type { JsonWriteOptions } from '@protobuf-ts/runtime';\nimport { PbLong } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * A Timestamp represents a point in time independent of any time zone or local\n * calendar, encoded as a count of seconds and fractions of seconds at\n * nanosecond resolution. The count is relative to an epoch at UTC midnight on\n * January 1, 1970, in the proleptic Gregorian calendar which extends the\n * Gregorian calendar backwards to year one.\n *\n * All minutes are 60 seconds long. Leap seconds are \"smeared\" so that no leap\n * second table is needed for interpretation, using a [24-hour linear\n * smear](https://developers.google.com/time/smear).\n *\n * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By\n * restricting to that range, we ensure that we can convert to and from [RFC\n * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.\n *\n * # Examples\n *\n * Example 1: Compute Timestamp from POSIX `time()`.\n *\n * Timestamp timestamp;\n * timestamp.set_seconds(time(NULL));\n * timestamp.set_nanos(0);\n *\n * Example 2: Compute Timestamp from POSIX `gettimeofday()`.\n *\n * struct timeval tv;\n * gettimeofday(&tv, NULL);\n *\n * Timestamp timestamp;\n * timestamp.set_seconds(tv.tv_sec);\n * timestamp.set_nanos(tv.tv_usec * 1000);\n *\n * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.\n *\n * FILETIME ft;\n * GetSystemTimeAsFileTime(&ft);\n * UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;\n *\n * // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z\n * // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.\n * Timestamp timestamp;\n * timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));\n * timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));\n *\n * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.\n *\n * long millis = System.currentTimeMillis();\n *\n * Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)\n * .setNanos((int) ((millis % 1000) * 1000000)).build();\n *\n *\n * Example 5: Compute Timestamp from Java `Instant.now()`.\n *\n * Instant now = Instant.now();\n *\n * Timestamp timestamp =\n * Timestamp.newBuilder().setSeconds(now.getEpochSecond())\n * .setNanos(now.getNano()).build();\n *\n *\n * Example 6: Compute Timestamp from current time in Python.\n *\n * timestamp = Timestamp()\n * timestamp.GetCurrentTime()\n *\n * # JSON Mapping\n *\n * In JSON format, the Timestamp type is encoded as a string in the\n * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the\n * format is \"{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z\"\n * where {year} is always expressed using four digits while {month}, {day},\n * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional\n * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),\n * are optional. The \"Z\" suffix indicates the timezone (\"UTC\"); the timezone\n * is required. A proto3 JSON serializer should always use UTC (as indicated by\n * \"Z\") when printing the Timestamp type and a proto3 JSON parser should be\n * able to accept both UTC and other timezones (as indicated by an offset).\n *\n * For example, \"2017-01-15T01:30:15.01Z\" encodes 15.01 seconds past\n * 01:30 UTC on January 15, 2017.\n *\n * In JavaScript, one can convert a Date object to this format using the\n * standard\n * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)\n * method. In Python, a standard `datetime.datetime` object can be converted\n * to this format using\n * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with\n * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use\n * the Joda Time's [`ISODateTimeFormat.dateTime()`](\n * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D\n * ) to obtain a formatter capable of generating timestamps in this format.\n *\n *\n *\n * @generated from protobuf message google.protobuf.Timestamp\n */\nexport interface Timestamp {\n /**\n * Represents seconds of UTC time since Unix epoch\n * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to\n * 9999-12-31T23:59:59Z inclusive.\n *\n * @generated from protobuf field: int64 seconds = 1;\n */\n seconds: bigint;\n /**\n * Non-negative fractions of a second at nanosecond resolution. Negative\n * second values with fractions must still have non-negative nanos values\n * that count forward in time. Must be from 0 to 999,999,999\n * inclusive.\n *\n * @generated from protobuf field: int32 nanos = 2;\n */\n nanos: number;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass Timestamp$Type extends MessageType<Timestamp> {\n constructor() {\n super('google.protobuf.Timestamp', [\n {\n no: 1,\n name: 'seconds',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'nanos', kind: 'scalar', T: 5 /*ScalarType.INT32*/ }\n ]);\n }\n /**\n * Creates a new `Timestamp` for the current time.\n */\n now(): Timestamp {\n const msg = this.create();\n const ms = Date.now();\n msg.seconds = PbLong.from(Math.floor(ms / 1000)).toBigInt();\n msg.nanos = (ms % 1000) * 1000000;\n return msg;\n }\n /**\n * Converts a `Timestamp` to a JavaScript Date.\n */\n toDate(message: Timestamp): Date {\n return new Date(\n PbLong.from(message.seconds).toNumber() * 1000 +\n Math.ceil(message.nanos / 1000000)\n );\n }\n /**\n * Converts a JavaScript Date to a `Timestamp`.\n */\n fromDate(date: Date): Timestamp {\n const msg = this.create();\n const ms = date.getTime();\n msg.seconds = PbLong.from(Math.floor(ms / 1000)).toBigInt();\n msg.nanos = (ms % 1000) * 1000000;\n return msg;\n }\n /**\n * In JSON format, the `Timestamp` type is encoded as a string\n * in the RFC 3339 format.\n */\n internalJsonWrite(message: Timestamp, options: JsonWriteOptions): JsonValue {\n let ms = PbLong.from(message.seconds).toNumber() * 1000;\n if (\n ms < Date.parse('0001-01-01T00:00:00Z') ||\n ms > Date.parse('9999-12-31T23:59:59Z')\n )\n throw new Error(\n 'Unable to encode Timestamp to JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.'\n );\n if (message.nanos < 0)\n throw new Error(\n 'Unable to encode invalid Timestamp to JSON. Nanos must not be negative.'\n );\n let z = 'Z';\n if (message.nanos > 0) {\n let nanosStr = (message.nanos + 1000000000).toString().substring(1);\n if (nanosStr.substring(3) === '000000')\n z = '.' + nanosStr.substring(0, 3) + 'Z';\n else if (nanosStr.substring(6) === '000')\n z = '.' + nanosStr.substring(0, 6) + 'Z';\n else z = '.' + nanosStr + 'Z';\n }\n return new Date(ms).toISOString().replace('.000Z', z);\n }\n /**\n * In JSON format, the `Timestamp` type is encoded as a string\n * in the RFC 3339 format.\n */\n internalJsonRead(\n json: JsonValue,\n options: JsonReadOptions,\n target?: Timestamp\n ): Timestamp {\n if (typeof json !== 'string')\n throw new Error(\n 'Unable to parse Timestamp from JSON ' + typeofJsonValue(json) + '.'\n );\n let matches = json.match(\n /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/\n );\n if (!matches)\n throw new Error('Unable to parse Timestamp from JSON. Invalid format.');\n let ms = Date.parse(\n matches[1] +\n '-' +\n matches[2] +\n '-' +\n matches[3] +\n 'T' +\n matches[4] +\n ':' +\n matches[5] +\n ':' +\n matches[6] +\n (matches[8] ? matches[8] : 'Z')\n );\n if (Number.isNaN(ms))\n throw new Error('Unable to parse Timestamp from JSON. Invalid value.');\n if (\n ms < Date.parse('0001-01-01T00:00:00Z') ||\n ms > Date.parse('9999-12-31T23:59:59Z')\n )\n throw new globalThis.Error(\n 'Unable to parse Timestamp from JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.'\n );\n if (!target) target = this.create();\n target.seconds = PbLong.from(ms / 1000).toBigInt();\n target.nanos = 0;\n if (matches[7])\n target.nanos =\n parseInt('1' + matches[7] + '0'.repeat(9 - matches[7].length)) -\n 1000000000;\n return target;\n }\n create(value?: PartialMessage<Timestamp>): Timestamp {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.seconds = 0n;\n message.nanos = 0;\n if (value !== undefined)\n reflectionMergePartial<Timestamp>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: Timestamp\n ): Timestamp {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* int64 seconds */ 1:\n message.seconds = reader.int64().toBigInt();\n break;\n case /* int32 nanos */ 2:\n message.nanos = reader.int32();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: Timestamp,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* int64 seconds = 1; */\n if (message.seconds !== 0n)\n writer.tag(1, WireType.Varint).int64(message.seconds);\n /* int32 nanos = 2; */\n if (message.nanos !== 0)\n writer.tag(2, WireType.Varint).int32(message.nanos);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message google.protobuf.Timestamp\n */\nexport const Timestamp = new Timestamp$Type();\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\nimport { Timestamp } from '../../../../../../../google/protobuf/timestamp';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI\n */\nexport interface LsAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.ListItem\n */\nexport interface LsAPI_ListItem {\n /**\n * name of the item in storage, without any prefixes\n *\n * @generated from protobuf field: string name = 1;\n */\n name: string;\n /**\n * size of item in bytes\n * is always zero for directories (is_dir = true)\n *\n * @generated from protobuf field: uint64 size = 2;\n */\n size: bigint;\n /**\n * is_dir is true for item, that can have subitems.\n *\n * @generated from protobuf field: bool is_dir = 3;\n */\n isDir: boolean;\n /**\n * full_name is the name of item absolute to storage root.\n * it is <directory> + <name>\n * The <delimiter>, used in names, is storage-specific and is NOT guaranteed to be '/'.\n *\n * @generated from protobuf field: string full_name = 10;\n */\n fullName: string;\n /**\n * directory, the item is located in. The value here is always a prefix of name:\n * name.HasPrefix(directory) is always true.\n *\n * @generated from protobuf field: string directory = 11;\n */\n directory: string;\n /**\n * last_modified keeps the item last modification timestamp\n *\n * @generated from protobuf field: google.protobuf.Timestamp last_modified = 12;\n */\n lastModified?: Timestamp;\n /**\n * version of item in storage.\n * When storage supports versioning or provides checksums for the data stored,\n * the <version> field keeps that data.\n * If not - it keeps the any simple combination of item attributes, that helps to\n * detect if the contents of item has changed, e.g. <size>+<mtime>.\n * Anyway, client should not try to interpret this field, but should provide it to the Platform\n * in operations with given item (like BlobImportInternal) to help Platform with deduplication.\n *\n * @generated from protobuf field: string version = 13;\n */\n version: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.List\n */\nexport interface LsAPI_List {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Request\n */\nexport interface LsAPI_List_Request {\n /**\n * resource_id of 'LS/<Storage>' resource\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * location to list, absolute to storage root. Only items, that have <full_name> starting\n * from <location> are included into list response.\n *\n * @generated from protobuf field: string location = 2;\n */\n location: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Response\n */\nexport interface LsAPI_List_Response {\n /**\n * List of the full (absolute to storage root) names of items from storage.\n * E.g., for 'fs' storage each name will consist of names of all directories, where the\n * item is located, and the item name itself.\n * The delimiter, used in names, is storage-specific and is NOT guaranteed to be '/'.\n *\n * @generated from protobuf field: repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items = 1;\n */\n items: LsAPI_ListItem[];\n /**\n * delimiter is path separator, used in this storage. Client can use it to parse item names into parts,\n * to extract directory names.\n *\n * @generated from protobuf field: string delimiter = 2;\n */\n delimiter: string;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI$Type extends MessageType<LsAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI', []);\n }\n create(value?: PartialMessage<LsAPI>): LsAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<LsAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI\n ): LsAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: LsAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI\n */\nexport const LsAPI = new LsAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_ListItem$Type extends MessageType<LsAPI_ListItem> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.ListItem', [\n { no: 1, name: 'name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n {\n no: 2,\n name: 'size',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 3, name: 'is_dir', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },\n { no: 10, name: 'full_name', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n { no: 11, name: 'directory', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },\n { no: 12, name: 'last_modified', kind: 'message', T: () => Timestamp },\n { no: 13, name: 'version', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<LsAPI_ListItem>): LsAPI_ListItem {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.name = '';\n message.size = 0n;\n message.isDir = false;\n message.fullName = '';\n message.directory = '';\n message.version = '';\n if (value !== undefined)\n reflectionMergePartial<LsAPI_ListItem>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_ListItem\n ): LsAPI_ListItem {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* string name */ 1:\n message.name = reader.string();\n break;\n case /* uint64 size */ 2:\n message.size = reader.uint64().toBigInt();\n break;\n case /* bool is_dir */ 3:\n message.isDir = reader.bool();\n break;\n case /* string full_name */ 10:\n message.fullName = reader.string();\n break;\n case /* string directory */ 11:\n message.directory = reader.string();\n break;\n case /* google.protobuf.Timestamp last_modified */ 12:\n message.lastModified = Timestamp.internalBinaryRead(\n reader,\n reader.uint32(),\n options,\n message.lastModified\n );\n break;\n case /* string version */ 13:\n message.version = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: LsAPI_ListItem,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* string name = 1; */\n if (message.name !== '')\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* uint64 size = 2; */\n if (message.size !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.size);\n /* bool is_dir = 3; */\n if (message.isDir !== false)\n writer.tag(3, WireType.Varint).bool(message.isDir);\n /* string full_name = 10; */\n if (message.fullName !== '')\n writer.tag(10, WireType.LengthDelimited).string(message.fullName);\n /* string directory = 11; */\n if (message.directory !== '')\n writer.tag(11, WireType.LengthDelimited).string(message.directory);\n /* google.protobuf.Timestamp last_modified = 12; */\n if (message.lastModified)\n Timestamp.internalBinaryWrite(\n message.lastModified,\n writer.tag(12, WireType.LengthDelimited).fork(),\n options\n ).join();\n /* string version = 13; */\n if (message.version !== '')\n writer.tag(13, WireType.LengthDelimited).string(message.version);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.ListItem\n */\nexport const LsAPI_ListItem = new LsAPI_ListItem$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_List$Type extends MessageType<LsAPI_List> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.List', []);\n }\n create(value?: PartialMessage<LsAPI_List>): LsAPI_List {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<LsAPI_List>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_List\n ): LsAPI_List {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: LsAPI_List,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.List\n */\nexport const LsAPI_List = new LsAPI_List$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_List_Request$Type extends MessageType<LsAPI_List_Request> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.List.Request', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n { no: 2, name: 'location', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<LsAPI_List_Request>): LsAPI_List_Request {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.location = '';\n if (value !== undefined)\n reflectionMergePartial<LsAPI_List_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_List_Request\n ): LsAPI_List_Request {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* string location */ 2:\n message.location = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: LsAPI_List_Request,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* string location = 2; */\n if (message.location !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.location);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Request\n */\nexport const LsAPI_List_Request = new LsAPI_List_Request$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass LsAPI_List_Response$Type extends MessageType<LsAPI_List_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.LsAPI.List.Response', [\n {\n no: 1,\n name: 'items',\n kind: 'message',\n repeat: 1 /*RepeatType.PACKED*/,\n T: () => LsAPI_ListItem\n },\n { no: 2, name: 'delimiter', kind: 'scalar', T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<LsAPI_List_Response>): LsAPI_List_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.items = [];\n message.delimiter = '';\n if (value !== undefined)\n reflectionMergePartial<LsAPI_List_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: LsAPI_List_Response\n ): LsAPI_List_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items */ 1:\n message.items.push(\n LsAPI_ListItem.internalBinaryRead(reader, reader.uint32(), options)\n );\n break;\n case /* string delimiter */ 2:\n message.delimiter = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: LsAPI_List_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items = 1; */\n for (let i = 0; i < message.items.length; i++)\n LsAPI_ListItem.internalBinaryWrite(\n message.items[i],\n writer.tag(1, WireType.LengthDelimited).fork(),\n options\n ).join();\n /* string delimiter = 2; */\n if (message.delimiter !== '')\n writer.tag(2, WireType.LengthDelimited).string(message.delimiter);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.LsAPI.List.Response\n */\nexport const LsAPI_List_Response = new LsAPI_List_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.LS\n */\nexport const LS = new ServiceType('MiLaboratories.Controller.Shared.LS', [\n { name: 'List', options: {}, I: LsAPI_List_Request, O: LsAPI_List_Response }\n]);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { LS } from './protocol';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { LsAPI_List_Response } from './protocol';\nimport type { LsAPI_List_Request } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * LS provides access to lists of blobs (files, S3 objects and so on) is some storage.\n * This API allows clients to know, whan items are available in storages, that\n * the contorllers can access, providing clients with the ability to start indexation\n * on, say, existing sequence files from the corporate storage.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.LS\n */\nexport interface ILSClient {\n /**\n * @generated from protobuf rpc: List(MiLaboratories.Controller.Shared.LsAPI.List.Request) returns (MiLaboratories.Controller.Shared.LsAPI.List.Response);\n */\n list(\n input: LsAPI_List_Request,\n options?: RpcOptions\n ): UnaryCall<LsAPI_List_Request, LsAPI_List_Response>;\n}\n/**\n *\n * LS provides access to lists of blobs (files, S3 objects and so on) is some storage.\n * This API allows clients to know, whan items are available in storages, that\n * the contorllers can access, providing clients with the ability to start indexation\n * on, say, existing sequence files from the corporate storage.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.LS\n */\nexport class LSClient implements ILSClient, ServiceInfo {\n typeName = LS.typeName;\n methods = LS.methods;\n options = LS.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * @generated from protobuf rpc: List(MiLaboratories.Controller.Shared.LsAPI.List.Request) returns (MiLaboratories.Controller.Shared.LsAPI.List.Response);\n */\n list(\n input: LsAPI_List_Request,\n options?: RpcOptions\n ): UnaryCall<LsAPI_List_Request, LsAPI_List_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<LsAPI_List_Request, LsAPI_List_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n}\n","import { MiLogger } from '@milaboratories/ts-helpers';\nimport type { LsAPI_List_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol';\nimport { LSClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLs {\n private readonly grpcClient: LSClient;\n\n constructor(\n grpcTransport: GrpcTransport,\n private readonly logger: MiLogger\n ) {\n this.grpcClient = new LSClient(grpcTransport);\n }\n\n close() {}\n\n public async list(\n rInfo: ResourceInfo,\n path: string,\n options?: RpcOptions\n ): Promise<LsAPI_List_Response> {\n return await this.grpcClient.list(\n {\n resourceId: rInfo.id,\n location: path\n },\n addRTypeToMetadata(rInfo.type, options)\n ).response;\n }\n}\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport { ServiceType } from '@protobuf-ts/runtime-rpc';\nimport { WireType } from '@protobuf-ts/runtime';\nimport type { BinaryWriteOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryWriter } from '@protobuf-ts/runtime';\nimport { UnknownFieldHandler } from '@protobuf-ts/runtime';\nimport type { BinaryReadOptions } from '@protobuf-ts/runtime';\nimport type { IBinaryReader } from '@protobuf-ts/runtime';\nimport type { PartialMessage } from '@protobuf-ts/runtime';\nimport { reflectionMergePartial } from '@protobuf-ts/runtime';\nimport { MessageType } from '@protobuf-ts/runtime';\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI\n */\nexport interface StreamingAPI {}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary\n */\nexport interface StreamingAPI_StreamBinary {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the data.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <chunk_size> limits the maximum size of <data> for each response message in stream.\n *\n * Default value: 32 768 (32 KiB)\n * Max value: 3900 * 1024 (3.9 MiB)\n *\n * @generated from protobuf field: optional uint32 chunk_size = 11;\n */\n chunkSize?: number;\n /**\n * <read_limit> allows client to limit total data sent from server.\n * This limit is aggregation of all data, sent in all chunks.\n * E.g. to read 2000 bytes of data in chunks of at most\n * 130 bytes, use <chunk_size> = 130; <read_limit> = 2000.\n * For storage item of appropriate size this settings will result in\n * 16 messages from server: 15 of 130 bytes and one of 50 bytes.\n *\n * @generated from protobuf field: optional int64 read_limit = 20;\n */\n readLimit?: bigint;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary\n */\nexport interface StreamingAPI_ReadBinary {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the data.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <chunk_size> limits the maximum size of <data> for response message in stream.\n *\n * Default value: 32 768 (32 KiB)\n * Max value: 3900 * 1024 (3.9 MiB)\n *\n * @generated from protobuf field: optional uint32 chunk_size = 11;\n */\n chunkSize?: number;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamText\n */\nexport interface StreamingAPI_StreamText {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the contents.\n * This offset is taken in BYTES, as it eases streaming recovery after client reconnection or controller restart.\n * Client can just use the <new_offset> value of the last response from server to continue streaming after reconnection.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <read_limit> allows client to limit total data sent from server.\n * This limit is aggregation of all data, sent in all chunks, measured\n * in lines of text.\n * E.g. to read top 1000 lines from stream source, use <read_limit> = 1000.\n * When both <read_limit> and <search>/<search_re> are set, the <read_limit> is applied first.\n * this is equivalent to 'head -n <read_limit> | grep <search>'.\n *\n * @generated from protobuf field: optional int64 read_limit = 20;\n */\n readLimit?: bigint;\n /**\n * <search> is substring for line search pattern.\n * This option makes controller to send to the client only lines, that\n * have given substring.\n *\n * @generated from protobuf field: optional string search = 21;\n */\n search?: string;\n /**\n * <search_re> is regular expression for line search pattern.\n * This option makes controller to send to the client only lines, that\n * match given regular expression.\n *\n * @generated from protobuf field: optional string search_re = 22;\n */\n searchRe?: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadText\n */\nexport interface StreamingAPI_ReadText {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the contents.\n * This offset is taken in BYTES, as it eases streaming recovery after client reconnection or controller restart.\n * Client can just use the <new_offset> value of the last response from server to continue streaming after reconnection.\n *\n * @generated from protobuf field: int64 offset = 2;\n */\n offset: bigint;\n /**\n * <read_limit> allows client to limit total data sent from server.\n * Measured in lines of text.\n * E.g. to read top 1000 lines from stream source, use <read_limit> = 1000.\n * When both <read_limit> and <search>/<search_re> are set, the <read_limit> is applied first.\n * this is equivalent to 'head -n <read_limit> | grep <search>'.\n * At most 3.9 MiB (3900 * 1024 KiB) of data is returned in single read regardless of <read_limit> option\n * Only full lines of text are returned except for the last line from the completed source\n * (the one that is not expected to have new data, like blob in storage)\n *\n * @generated from protobuf field: optional int64 read_limit = 20;\n */\n readLimit?: bigint;\n /**\n * <search> is substring for line search pattern.\n * This option makes controller to send to the client only lines, that\n * have given substring.\n *\n * @generated from protobuf field: optional string search = 21;\n */\n search?: string;\n /**\n * <search_re> is regular expression for line search pattern.\n * This option makes controller to send to the client only lines, that\n * match given regular expression.\n *\n * @generated from protobuf field: optional string search_re = 22;\n */\n searchRe?: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.LastLines\n */\nexport interface StreamingAPI_LastLines {\n /**\n * <resource_id> of Stream resource, that keeps info on item to be streamed.\n *\n * @generated from protobuf field: uint64 resource_id = 1;\n */\n resourceId: bigint;\n /**\n * <offset> makes streamer to perform seek operation to given offset before sending the contents.\n * This offset is taken in BYTES, as it eases streaming recovery after client reconnection or controller restart.\n * By default, LastLines starts to treat the data source from the very last byte available in data stream\n * at the moment of call, but client can set the server to start from earlier position.\n *\n * @generated from protobuf field: optional int64 offset = 2;\n */\n offset?: bigint;\n /**\n * <line_count> makes streamer to return up to <line_count> lines to the client.\n * Default value: 1\n *\n * @generated from protobuf field: optional int32 line_count = 3;\n */\n lineCount?: number;\n /**\n * <search> is substring for line search pattern.\n * This option makes controller to send to the client only lines, that\n * have given substring.\n *\n * @generated from protobuf field: optional string search = 21;\n */\n search?: string;\n /**\n * <search_re> is regular expression for line search pattern.\n * This option makes controller to send to the client only lines, that\n * match given regular expression.\n *\n * @generated from protobuf field: optional string search_re = 22;\n */\n searchRe?: string;\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI.Response\n */\nexport interface StreamingAPI_Response {\n /**\n * data chunk from item, starting from the <new_offset> of the previous message in the same stream.\n *\n * @generated from protobuf field: bytes data = 1;\n */\n data: Uint8Array;\n /**\n * <size> is the actual size of the streamed item at the moment of this message.\n * This might be not a final amount of streamed data, as stream source can be updated\n * by other independent process (e.g., data is written to log file).\n * This field in combination with <new_offset> shows, how far the client is from the end\n * of the data right now.\n *\n * @generated from protobuf field: uint64 size = 2;\n */\n size: bigint;\n /**\n * <new_offset> is the new offset in bytes from the start of the streamed item,\n * including size of <data> in current response.\n * Call to Stream rpc with <offset> = <new_offset> will continue\n * streaming from the place of last received message\n * (e.g. <offset> = <new_offset> - 1 will repeat the last byte of\n * previously received <data>)\n *\n * @generated from protobuf field: uint64 new_offset = 3;\n */\n newOffset: bigint;\n}\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI$Type extends MessageType<StreamingAPI> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI', []);\n }\n create(value?: PartialMessage<StreamingAPI>): StreamingAPI {\n const message = globalThis.Object.create(this.messagePrototype!);\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI\n ): StreamingAPI {\n return target ?? this.create();\n }\n internalBinaryWrite(\n message: StreamingAPI,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI\n */\nexport const StreamingAPI = new StreamingAPI$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_StreamBinary$Type extends MessageType<StreamingAPI_StreamBinary> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 11,\n name: 'chunk_size',\n kind: 'scalar',\n opt: true,\n T: 13 /*ScalarType.UINT32*/\n },\n {\n no: 20,\n name: 'read_limit',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_StreamBinary>\n ): StreamingAPI_StreamBinary {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_StreamBinary>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_StreamBinary\n ): StreamingAPI_StreamBinary {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional uint32 chunk_size */ 11:\n message.chunkSize = reader.uint32();\n break;\n case /* optional int64 read_limit */ 20:\n message.readLimit = reader.int64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_StreamBinary,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional uint32 chunk_size = 11; */\n if (message.chunkSize !== undefined)\n writer.tag(11, WireType.Varint).uint32(message.chunkSize);\n /* optional int64 read_limit = 20; */\n if (message.readLimit !== undefined)\n writer.tag(20, WireType.Varint).int64(message.readLimit);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary\n */\nexport const StreamingAPI_StreamBinary = new StreamingAPI_StreamBinary$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_ReadBinary$Type extends MessageType<StreamingAPI_ReadBinary> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 11,\n name: 'chunk_size',\n kind: 'scalar',\n opt: true,\n T: 13 /*ScalarType.UINT32*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_ReadBinary>\n ): StreamingAPI_ReadBinary {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_ReadBinary>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_ReadBinary\n ): StreamingAPI_ReadBinary {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional uint32 chunk_size */ 11:\n message.chunkSize = reader.uint32();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_ReadBinary,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional uint32 chunk_size = 11; */\n if (message.chunkSize !== undefined)\n writer.tag(11, WireType.Varint).uint32(message.chunkSize);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary\n */\nexport const StreamingAPI_ReadBinary = new StreamingAPI_ReadBinary$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_StreamText$Type extends MessageType<StreamingAPI_StreamText> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.StreamText', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 20,\n name: 'read_limit',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 21,\n name: 'search',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 22,\n name: 'search_re',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_StreamText>\n ): StreamingAPI_StreamText {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_StreamText>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_StreamText\n ): StreamingAPI_StreamText {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional int64 read_limit */ 20:\n message.readLimit = reader.int64().toBigInt();\n break;\n case /* optional string search */ 21:\n message.search = reader.string();\n break;\n case /* optional string search_re */ 22:\n message.searchRe = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_StreamText,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional int64 read_limit = 20; */\n if (message.readLimit !== undefined)\n writer.tag(20, WireType.Varint).int64(message.readLimit);\n /* optional string search = 21; */\n if (message.search !== undefined)\n writer.tag(21, WireType.LengthDelimited).string(message.search);\n /* optional string search_re = 22; */\n if (message.searchRe !== undefined)\n writer.tag(22, WireType.LengthDelimited).string(message.searchRe);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.StreamText\n */\nexport const StreamingAPI_StreamText = new StreamingAPI_StreamText$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_ReadText$Type extends MessageType<StreamingAPI_ReadText> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.ReadText', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 20,\n name: 'read_limit',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 21,\n name: 'search',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 22,\n name: 'search_re',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_ReadText>): StreamingAPI_ReadText {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n message.offset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_ReadText>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_ReadText\n ): StreamingAPI_ReadText {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional int64 read_limit */ 20:\n message.readLimit = reader.int64().toBigInt();\n break;\n case /* optional string search */ 21:\n message.search = reader.string();\n break;\n case /* optional string search_re */ 22:\n message.searchRe = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_ReadText,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* int64 offset = 2; */\n if (message.offset !== 0n)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional int64 read_limit = 20; */\n if (message.readLimit !== undefined)\n writer.tag(20, WireType.Varint).int64(message.readLimit);\n /* optional string search = 21; */\n if (message.search !== undefined)\n writer.tag(21, WireType.LengthDelimited).string(message.search);\n /* optional string search_re = 22; */\n if (message.searchRe !== undefined)\n writer.tag(22, WireType.LengthDelimited).string(message.searchRe);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.ReadText\n */\nexport const StreamingAPI_ReadText = new StreamingAPI_ReadText$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_LastLines$Type extends MessageType<StreamingAPI_LastLines> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.LastLines', [\n {\n no: 1,\n name: 'resource_id',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 2,\n name: 'offset',\n kind: 'scalar',\n opt: true,\n T: 3 /*ScalarType.INT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'line_count',\n kind: 'scalar',\n opt: true,\n T: 5 /*ScalarType.INT32*/\n },\n {\n no: 21,\n name: 'search',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n },\n {\n no: 22,\n name: 'search_re',\n kind: 'scalar',\n opt: true,\n T: 9 /*ScalarType.STRING*/\n }\n ]);\n }\n create(\n value?: PartialMessage<StreamingAPI_LastLines>\n ): StreamingAPI_LastLines {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_LastLines>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_LastLines\n ): StreamingAPI_LastLines {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* uint64 resource_id */ 1:\n message.resourceId = reader.uint64().toBigInt();\n break;\n case /* optional int64 offset */ 2:\n message.offset = reader.int64().toBigInt();\n break;\n case /* optional int32 line_count */ 3:\n message.lineCount = reader.int32();\n break;\n case /* optional string search */ 21:\n message.search = reader.string();\n break;\n case /* optional string search_re */ 22:\n message.searchRe = reader.string();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_LastLines,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* optional int64 offset = 2; */\n if (message.offset !== undefined)\n writer.tag(2, WireType.Varint).int64(message.offset);\n /* optional int32 line_count = 3; */\n if (message.lineCount !== undefined)\n writer.tag(3, WireType.Varint).int32(message.lineCount);\n /* optional string search = 21; */\n if (message.search !== undefined)\n writer.tag(21, WireType.LengthDelimited).string(message.search);\n /* optional string search_re = 22; */\n if (message.searchRe !== undefined)\n writer.tag(22, WireType.LengthDelimited).string(message.searchRe);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.LastLines\n */\nexport const StreamingAPI_LastLines = new StreamingAPI_LastLines$Type();\n// @generated message type with reflection information, may provide speed optimized methods\nclass StreamingAPI_Response$Type extends MessageType<StreamingAPI_Response> {\n constructor() {\n super('MiLaboratories.Controller.Shared.StreamingAPI.Response', [\n { no: 1, name: 'data', kind: 'scalar', T: 12 /*ScalarType.BYTES*/ },\n {\n no: 2,\n name: 'size',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n },\n {\n no: 3,\n name: 'new_offset',\n kind: 'scalar',\n T: 4 /*ScalarType.UINT64*/,\n L: 0 /*LongType.BIGINT*/\n }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_Response>): StreamingAPI_Response {\n const message = globalThis.Object.create(this.messagePrototype!);\n message.data = new Uint8Array(0);\n message.size = 0n;\n message.newOffset = 0n;\n if (value !== undefined)\n reflectionMergePartial<StreamingAPI_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(\n reader: IBinaryReader,\n length: number,\n options: BinaryReadOptions,\n target?: StreamingAPI_Response\n ): StreamingAPI_Response {\n let message = target ?? this.create(),\n end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n case /* bytes data */ 1:\n message.data = reader.bytes();\n break;\n case /* uint64 size */ 2:\n message.size = reader.uint64().toBigInt();\n break;\n case /* uint64 new_offset */ 3:\n message.newOffset = reader.uint64().toBigInt();\n break;\n default:\n let u = options.readUnknownField;\n if (u === 'throw')\n throw new globalThis.Error(\n `Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`\n );\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(\n this.typeName,\n message,\n fieldNo,\n wireType,\n d\n );\n }\n }\n return message;\n }\n internalBinaryWrite(\n message: StreamingAPI_Response,\n writer: IBinaryWriter,\n options: BinaryWriteOptions\n ): IBinaryWriter {\n /* bytes data = 1; */\n if (message.data.length)\n writer.tag(1, WireType.LengthDelimited).bytes(message.data);\n /* uint64 size = 2; */\n if (message.size !== 0n)\n writer.tag(2, WireType.Varint).uint64(message.size);\n /* uint64 new_offset = 3; */\n if (message.newOffset !== 0n)\n writer.tag(3, WireType.Varint).uint64(message.newOffset);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(\n this.typeName,\n message,\n writer\n );\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.StreamingAPI.Response\n */\nexport const StreamingAPI_Response = new StreamingAPI_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Streaming\n */\nexport const Streaming = new ServiceType(\n 'MiLaboratories.Controller.Shared.Streaming',\n [\n {\n name: 'StreamBinary',\n serverStreaming: true,\n options: {},\n I: StreamingAPI_StreamBinary,\n O: StreamingAPI_Response\n },\n {\n name: 'ReadBinary',\n options: {},\n I: StreamingAPI_ReadBinary,\n O: StreamingAPI_Response\n },\n {\n name: 'StreamText',\n serverStreaming: true,\n options: {},\n I: StreamingAPI_StreamText,\n O: StreamingAPI_Response\n },\n {\n name: 'ReadText',\n options: {},\n I: StreamingAPI_ReadText,\n O: StreamingAPI_Response\n },\n {\n name: 'LastLines',\n options: {},\n I: StreamingAPI_LastLines,\n O: StreamingAPI_Response\n }\n ]\n);\n","// @generated by protobuf-ts 2.9.4 with parameter client_generic,optimize_speed,generate_dependencies,force_server_none\n// @generated from protobuf file \"github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.proto\" (package \"MiLaboratories.Controller.Shared\", syntax proto3)\n// tslint:disable\nimport type { RpcTransport } from '@protobuf-ts/runtime-rpc';\nimport type { ServiceInfo } from '@protobuf-ts/runtime-rpc';\nimport { Streaming } from './protocol';\nimport type { StreamingAPI_LastLines } from './protocol';\nimport type { StreamingAPI_ReadText } from './protocol';\nimport type { StreamingAPI_StreamText } from './protocol';\nimport type { StreamingAPI_ReadBinary } from './protocol';\nimport type { UnaryCall } from '@protobuf-ts/runtime-rpc';\nimport { stackIntercept } from '@protobuf-ts/runtime-rpc';\nimport type { StreamingAPI_Response } from './protocol';\nimport type { StreamingAPI_StreamBinary } from './protocol';\nimport type { ServerStreamingCall } from '@protobuf-ts/runtime-rpc';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\n/**\n *\n * Streaming provides access to online data stream from item in storage. Whenever item is appended with data,\n * the caller receives this fresh data in stream from server.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Streaming\n */\nexport interface IStreamingClient {\n /**\n * StreamBinary provides stream of binary file. Each response message keeps\n * one single chunk of binary data from data source. See StreamingAPI.Binary message\n * for more info on available options.\n *\n * @generated from protobuf rpc: StreamBinary(MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamBinary(\n input: StreamingAPI_StreamBinary,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamBinary, StreamingAPI_Response>;\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadBinary(MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readBinary(\n input: StreamingAPI_ReadBinary,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadBinary, StreamingAPI_Response>;\n /**\n * StreamText provides stream of textual file, splitting the data by newline symbol.\n * Each response message keeps one single line of text from data source.\n *\n * @generated from protobuf rpc: StreamText(MiLaboratories.Controller.Shared.StreamingAPI.StreamText) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamText(\n input: StreamingAPI_StreamText,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamText, StreamingAPI_Response>;\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadText(MiLaboratories.Controller.Shared.StreamingAPI.ReadText) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readText(\n input: StreamingAPI_ReadText,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadText, StreamingAPI_Response>;\n /**\n * LastLines provides single message with the last lines from data source.\n * When search pattern is specified, the last lines matching the given pattern are returned.\n * The lines are returned in reversed order, as server reads data source from the end.\n * Consider it as equivalent to 'tac <file> | grep <search> | head -n <line_count>'\n * The <new_offset> returned in the response points to the _beginning_ of the last\n * line found, so client can continue reading the file backwards in subsequent calls.\n * This means, that use of this <new_offset> in ReadText() will return you the same line\n * returned last in LastLines() data.\n *\n * @generated from protobuf rpc: LastLines(MiLaboratories.Controller.Shared.StreamingAPI.LastLines) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n lastLines(\n input: StreamingAPI_LastLines,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_LastLines, StreamingAPI_Response>;\n}\n/**\n *\n * Streaming provides access to online data stream from item in storage. Whenever item is appended with data,\n * the caller receives this fresh data in stream from server.\n *\n *\n * @generated from protobuf service MiLaboratories.Controller.Shared.Streaming\n */\nexport class StreamingClient implements IStreamingClient, ServiceInfo {\n typeName = Streaming.typeName;\n methods = Streaming.methods;\n options = Streaming.options;\n constructor(private readonly _transport: RpcTransport) {}\n /**\n * StreamBinary provides stream of binary file. Each response message keeps\n * one single chunk of binary data from data source. See StreamingAPI.Binary message\n * for more info on available options.\n *\n * @generated from protobuf rpc: StreamBinary(MiLaboratories.Controller.Shared.StreamingAPI.StreamBinary) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamBinary(\n input: StreamingAPI_StreamBinary,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamBinary, StreamingAPI_Response> {\n const method = this.methods[0],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamBinary, StreamingAPI_Response>(\n 'serverStreaming',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadBinary(MiLaboratories.Controller.Shared.StreamingAPI.ReadBinary) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readBinary(\n input: StreamingAPI_ReadBinary,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadBinary, StreamingAPI_Response> {\n const method = this.methods[1],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadBinary, StreamingAPI_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * StreamText provides stream of textual file, splitting the data by newline symbol.\n * Each response message keeps one single line of text from data source.\n *\n * @generated from protobuf rpc: StreamText(MiLaboratories.Controller.Shared.StreamingAPI.StreamText) returns (stream MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n streamText(\n input: StreamingAPI_StreamText,\n options?: RpcOptions\n ): ServerStreamingCall<StreamingAPI_StreamText, StreamingAPI_Response> {\n const method = this.methods[2],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamText, StreamingAPI_Response>(\n 'serverStreaming',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * ReadBinary allows to read remote item in chunks using stream-like API.\n * The difference to StreamBinary is that the client receives single response for each\n * call and has to send new calls to the server to get fresh data from remote item.\n * Each response (each chunk from server) keeps not more than 3.9MiB of data.\n *\n * @generated from protobuf rpc: ReadText(MiLaboratories.Controller.Shared.StreamingAPI.ReadText) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n readText(\n input: StreamingAPI_ReadText,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_ReadText, StreamingAPI_Response> {\n const method = this.methods[3],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadText, StreamingAPI_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n /**\n * LastLines provides single message with the last lines from data source.\n * When search pattern is specified, the last lines matching the given pattern are returned.\n * The lines are returned in reversed order, as server reads data source from the end.\n * Consider it as equivalent to 'tac <file> | grep <search> | head -n <line_count>'\n * The <new_offset> returned in the response points to the _beginning_ of the last\n * line found, so client can continue reading the file backwards in subsequent calls.\n * This means, that use of this <new_offset> in ReadText() will return you the same line\n * returned last in LastLines() data.\n *\n * @generated from protobuf rpc: LastLines(MiLaboratories.Controller.Shared.StreamingAPI.LastLines) returns (MiLaboratories.Controller.Shared.StreamingAPI.Response);\n */\n lastLines(\n input: StreamingAPI_LastLines,\n options?: RpcOptions\n ): UnaryCall<StreamingAPI_LastLines, StreamingAPI_Response> {\n const method = this.methods[4],\n opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_LastLines, StreamingAPI_Response>(\n 'unary',\n this._transport,\n method,\n opt,\n input\n );\n }\n}\n","import { StreamingClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { MiLogger, notEmpty } from '@milaboratories/ts-helpers';\nimport { Dispatcher } from 'undici';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLogs {\n public readonly grpcClient: StreamingClient;\n\n constructor(\n public readonly grpcTransport: GrpcTransport,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger\n ) {\n this.grpcClient = new StreamingClient(this.grpcTransport);\n }\n\n close() {}\n\n /** Reads text back and returns the text,\n * the new offset\n * and the total size of the (currently existing) file. */\n public async lastLines(\n { id: rId, type: rType }: ResourceInfo,\n lineCount: number,\n offsetBytes: bigint = 0n, // if 0n, then start from the end.\n searchStr?: string,\n options?: RpcOptions\n ): Promise<StreamingAPI_Response> {\n return (\n await this.grpcClient.lastLines(\n {\n resourceId: rId,\n lineCount: lineCount,\n offset: offsetBytes,\n search: searchStr\n },\n addRTypeToMetadata(rType, options)\n )\n ).response;\n }\n\n /** Reads the file forward and returns the text,\n * the new offset\n * and the total size of the (currently existing) file. */\n public async readText(\n { id: rId, type: rType }: ResourceInfo,\n lineCount: number,\n offsetBytes: bigint = 0n, // if 0n, then start from the beginning.\n searchStr?: string,\n options?: RpcOptions\n ): Promise<StreamingAPI_Response> {\n return (\n await this.grpcClient.readText(\n {\n resourceId: notEmpty(rId),\n readLimit: BigInt(lineCount),\n offset: offsetBytes,\n search: searchStr\n },\n addRTypeToMetadata(rType, options)\n )\n ).response;\n }\n}\n","import { PlClient } from '@milaboratories/pl-client';\nimport { MiLogger } from '@milaboratories/ts-helpers';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport { Dispatcher } from 'undici';\nimport { ClientDownload } from './download';\nimport { ClientLogs } from './logs';\nimport { ClientProgress } from './progress';\nimport { ClientUpload } from './upload';\nimport { ClientLs } from './ls_api';\nimport { LocalStorageProjection } from '../drivers/types';\n\nexport function createDownloadClient(\n logger: MiLogger,\n client: PlClient,\n localProjections: LocalStorageProjection[]\n) {\n return client.getDriver({\n name: 'DownloadBlob',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientDownload(grpcTransport, httpDispatcher, logger, localProjections)\n });\n}\n\nexport function createLogsClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'StreamLogs',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientLogs(grpcTransport, httpDispatcher, logger)\n });\n}\n\nexport function createUploadProgressClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadProgress',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientProgress(grpcTransport, httpDispatcher, client, logger)\n });\n}\n\nexport function createUploadBlobClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadBlob',\n init: (_: PlClient, grpcTransport: GrpcTransport, httpDispatcher: Dispatcher) =>\n new ClientUpload(grpcTransport, httpDispatcher, client, logger)\n });\n}\n\nexport function createLsFilesClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'LsFiles',\n init: (_client: PlClient, grpcTransport: GrpcTransport, _httpDispatcher: Dispatcher) =>\n new ClientLs(grpcTransport, logger)\n });\n}\n","import type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { ClientLogs } from '../../clients/logs';\nimport {\n PlClient,\n ResourceId,\n BasicResourceData,\n isNullResourceId,\n valErr,\n getField\n} from '@milaboratories/pl-client';\nimport { scheduler } from 'node:timers/promises';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\n// TODO: remove this when we switch to refreshState.\n\n/** It's an Updater but for tasks that happens in a while loop with sleeping between. */\nexport class LongUpdater {\n private updater: Updater;\n\n constructor(\n private readonly onUpdate: () => Promise<boolean>,\n private readonly sleepMs: number\n ) {\n this.updater = new Updater(async () => {\n while (true) {\n const done = await this.onUpdate();\n if (done) return;\n await scheduler.wait(this.sleepMs);\n }\n });\n }\n\n schedule = () => this.updater.schedule();\n}\n\n/** Updater incorporates a pattern when someone wants to run a callback\n * that updates something only when it's not already running. */\nexport class Updater {\n private updating: Promise<void> | undefined;\n\n constructor(private readonly onUpdate: () => Promise<void>) {}\n\n schedule() {\n if (this.updating == undefined) {\n this.updating = (async () => {\n try {\n await this.onUpdate();\n } catch (e) {\n console.log(`error while updating in Updater: ${e}`);\n } finally {\n this.updating = undefined;\n }\n })();\n }\n }\n}\n\n// TODO: remove all the code below to the computable that calculates Mixcr logs.\n\nexport async function getStream(\n client: PlClient,\n streamManagerId: ResourceId\n): Promise<BasicResourceData | undefined> {\n return client.withReadTx('LogsDriverGetStream', async (tx) => {\n const sm = await tx.getResourceData(streamManagerId, true);\n const stream = await valErr(tx, getField(sm, 'stream'));\n if (stream.error != '') {\n throw new Error(`while getting stream: ${stream.error}`);\n }\n if (isNullResourceId(stream.valueId)) return undefined;\n\n return await tx.getResourceData(stream.valueId, false);\n });\n}\n\nexport type MixcrProgressResponse = { found: false } | ({ found: true } & MixcrProgressLine);\n\nexport type MixcrProgressLine = {\n stage: string; // Building pre-clones from tag groups\n progress: string; // 35.3%\n eta: string; // ETA: 00:00:07\n};\n\n/** Is set by a template code.\n * Mixcr adds this prefix to every log line that contains a progress. */\nconst mixcrProgressPrefix = '8C7#F1328%9E089B3D22';\nconst mixcrProgressRegex = /(?<stage>.*):\\s*(?<progress>[\\d.]+%)\\s.*(?<eta>ETA:.*)/g;\n\nexport function lineToProgress(line: string): MixcrProgressLine | undefined {\n const noPrefix = line.replace(mixcrProgressPrefix, '');\n const parsed = noPrefix.match(mixcrProgressRegex);\n\n if (parsed == null || parsed.length != 4) {\n return undefined;\n }\n\n const [_, stage, progress, eta] = parsed;\n\n return {\n stage, // For example, 'Building pre-clones from tag groups'\n progress, // 35.3%\n eta // ETA: 00:00:07\n };\n}\n\nexport async function mixcrProgressFromLogs(\n rInfo: ResourceInfo,\n client: ClientLogs,\n options?: RpcOptions\n): Promise<MixcrProgressResponse> {\n const lastLines = await client.lastLines(rInfo, 1, 0n, mixcrProgressPrefix, options);\n if (lastLines.data == null || lastLines.data.length == 0) {\n return { found: false };\n }\n\n const line = lastLines.data.toString().split(/\\r?\\n/)[0];\n if (line == undefined) {\n return { found: false };\n }\n\n const progress = lineToProgress(line);\n if (progress === undefined) {\n return { found: false };\n }\n\n return { found: true, ...progress };\n}\n","import { CallersCounter, mapEntries, mapGet } from '@milaboratories/ts-helpers';\n\ntype PathLike = string;\n\nexport interface CachedFile {\n sizeBytes: number;\n path: PathLike;\n counter: CallersCounter;\n}\n\n/** Holds counters of how many callers need the file.\n * If some counters become zero and a cache size exceeds a soft limit,\n * remove not needed blobs one by one.\n * If all the files are needed, do nothing. */\nexport class FilesCache<T extends CachedFile> {\n private cache: Map<PathLike, T> = new Map();\n private totalSizeBytes: number = 0;\n\n constructor(private readonly softSizeBytes: number) {}\n\n existsFile(path: PathLike): boolean {\n return this.cache.get(path) != undefined;\n }\n\n getFile(path: PathLike, callerId: string): T | undefined {\n const file = this.cache.get(path);\n if (file != undefined) {\n file.counter.inc(callerId);\n }\n\n return file;\n }\n\n /** Decrements a counter in a cache and if we exceeds\n * a soft limit, removes files with zero counters. */\n removeFile(path: PathLike, callerId: string): T[] {\n mapGet(this.cache, path).counter.dec(callerId);\n return this.toDelete();\n }\n\n /** Returns what results should be deleted to comply with the soft limit. */\n toDelete(): T[] {\n if (this.totalSizeBytes <= this.softSizeBytes) return [];\n\n const result: T[] = [];\n let freedBytes = 0;\n\n mapEntries(this.cache)\n .filter(([_, file]: [string, T]) => file.counter.isZero())\n .forEach(([path, _]) => {\n if (this.totalSizeBytes - freedBytes <= this.softSizeBytes) return;\n const file = mapGet(this.cache, path);\n freedBytes += file.sizeBytes;\n result.push(file);\n });\n\n return result;\n }\n\n addCache(file: T, callerId: string) {\n const created = this.cache.get(file.path) == undefined;\n this.cache.set(file.path, file);\n file.counter.inc(callerId);\n\n if (file.sizeBytes < 0) throw new Error(`empty sizeBytes: ${file}`);\n\n if (created) this.totalSizeBytes += file.sizeBytes;\n }\n\n removeCache(file: T) {\n this.cache.delete(file.path);\n this.totalSizeBytes -= file.sizeBytes;\n }\n}\n","import { Computable, ComputableCtx } from '@milaboratories/computable';\nimport { PlTreeEntry, ResourceInfo } from '@milaboratories/pl-tree';\nimport { bigintToResourceId, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport { LogsStreamDriver } from './logs_stream';\nimport { DownloadDriver } from './download_and_logs_blob';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { ConsoleLoggerAdapter, MiLogger } from '@milaboratories/ts-helpers';\n\nexport class LogsDriver implements sdk.LogsDriver {\n constructor(\n private readonly logger: MiLogger,\n private readonly logsStreamDriver: LogsStreamDriver,\n private readonly downloadDriver: DownloadDriver\n ) {}\n\n /** Returns all logs and schedules a job that reads remain logs.\n * Notifies when a new portion of the log appeared. */\n getLastLogs(res: PlTreeEntry, lines: number): Computable<string | undefined>;\n getLastLogs(res: PlTreeEntry, lines: number, ctx: ComputableCtx): Computable<string | undefined>;\n getLastLogs(\n res: PlTreeEntry,\n lines: number,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getLastLogs(res, lines, ctx));\n\n const stream = streamManagerGetStream(ctx, res);\n if (stream === undefined) {\n ctx.markUnstable('no stream in stream manager');\n return undefined;\n }\n\n if (isBlob(stream)) return this.downloadDriver.getLastLogs(stream, lines, ctx);\n\n try {\n return this.logsStreamDriver.getLastLogs(stream, lines, ctx);\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n ctx.markUnstable(`NOT_FOUND in logs stream driver while getting last logs: ${e}`);\n return undefined;\n }\n throw e;\n }\n }\n\n /** Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLog(res: PlTreeEntry, patternToSearch: string): Computable<string | undefined>;\n getProgressLog(res: PlTreeEntry, patternToSearch: string, ctx: ComputableCtx): string | undefined;\n getProgressLog(\n res: PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx === undefined)\n return Computable.make((ctx) => this.getProgressLog(res, patternToSearch, ctx));\n\n const stream = streamManagerGetStream(ctx, res);\n if (stream === undefined) {\n ctx.markUnstable('no stream in stream manager');\n return undefined;\n }\n\n if (isBlob(stream)) return this.downloadDriver.getProgressLog(stream, patternToSearch, ctx);\n\n try {\n return this.logsStreamDriver.getProgressLog(stream, patternToSearch, ctx);\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n ctx.markUnstable(`NOT_FOUND in logs stream driver while getting a progress log: ${e}`);\n return undefined;\n }\n throw e;\n }\n }\n\n /** Returns an Id of a smart object, that can read logs directly from\n * the platform. */\n getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<sdk.AnyLogHandle | undefined>;\n getLogHandle(res: PlTreeEntry, ctx: ComputableCtx): sdk.AnyLogHandle | undefined;\n getLogHandle(\n res: PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<sdk.AnyLogHandle | undefined> | sdk.AnyLogHandle | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getLogHandle(res, ctx));\n\n const stream = streamManagerGetStream(ctx, res);\n if (stream === undefined) {\n ctx.markUnstable('no stream in stream manager');\n return undefined;\n }\n\n if (isBlob(stream)) return this.downloadDriver.getLogHandle(stream, ctx);\n\n return this.logsStreamDriver.getLogHandle(stream, ctx);\n }\n\n async lastLines(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string\n ): Promise<sdk.StreamingApiResponse> {\n if (isLiveLogHandle(handle))\n return await this.logsStreamDriver.lastLines(handle, lineCount, offsetBytes, searchStr);\n return await this.downloadDriver.lastLines(handle, lineCount, offsetBytes, searchStr);\n }\n\n async readText(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string\n ): Promise<sdk.StreamingApiResponse> {\n if (isLiveLogHandle(handle))\n return await this.logsStreamDriver.readText(handle, lineCount, offsetBytes, searchStr);\n return await this.downloadDriver.readText(handle, lineCount, offsetBytes, searchStr);\n }\n}\n\nfunction isBlob(rInfo: ResourceInfo) {\n return !rInfo.type.name.startsWith('StreamWorkdir');\n}\n\nfunction streamManagerGetStream(ctx: ComputableCtx, manager: PlTreeEntry) {\n return ctx.accessor(manager).node().traverse('stream')?.resourceInfo;\n}\n\nexport function handleToData(handle: sdk.AnyLogHandle): ResourceInfo {\n let parsed: RegExpMatchArray | null;\n\n if (isLiveLogHandle(handle)) {\n parsed = handle.match(liveHandleRegex);\n } else if (isReadyLogHandle(handle)) {\n parsed = handle.match(readyHandleRegex);\n } else throw new Error(`Log handle is malformed: ${handle}`);\n if (parsed == null) throw new Error(`Log handle wasn't parsed: ${handle}`);\n\n const { resourceType, resourceVersion, resourceId } = parsed.groups!;\n\n return {\n id: bigintToResourceId(BigInt(resourceId)),\n type: { name: resourceType, version: resourceVersion }\n };\n}\n\nexport function dataToHandle(live: boolean, rInfo: ResourceInfo): sdk.AnyLogHandle {\n if (live) {\n return `log+live://log/${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}` as sdk.LiveLogHandle;\n }\n\n return `log+ready://log/${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}` as sdk.ReadyLogHandle;\n}\n\nconst liveHandleRegex =\n /^log\\+live:\\/\\/log\\/(?<resourceType>.*)\\/(?<resourceVersion>.*)\\/(?<resourceId>.*)$/;\n\nexport function isLiveLogHandle(handle: string): handle is sdk.LiveLogHandle {\n return liveHandleRegex.test(handle);\n}\n\nconst readyHandleRegex =\n /^log\\+ready:\\/\\/log\\/(?<resourceType>.*)\\/(?<resourceVersion>.*)\\/(?<resourceId>.*)$/;\n\nexport function isReadyLogHandle(handle: string): handle is sdk.ReadyLogHandle {\n return readyHandleRegex.test(handle);\n}\n","import {\n ChangeSource,\n Computable,\n ComputableCtx,\n ComputableStableDefined,\n Watcher\n} from '@milaboratories/computable';\nimport { bigintToResourceId, ResourceId } from '@milaboratories/pl-client';\nimport {\n CallersCounter,\n MiLogger,\n TaskProcessor,\n Signer,\n ValueOrError\n} from '@milaboratories/ts-helpers';\nimport * as fsp from 'node:fs/promises';\nimport * as fs from 'fs';\nimport * as path from 'node:path';\nimport { Writable } from 'node:stream';\nimport { ClientDownload, UnknownStorageError, WrongLocalFileUrl } from '../clients/download';\nimport { ClientLogs } from '../clients/logs';\nimport * as helper from './helpers/helpers';\nimport * as readline from 'node:readline/promises';\nimport Denque from 'denque';\nimport * as os from 'node:os';\nimport { FilesCache } from './helpers/files_cache';\nimport { randomUUID } from 'node:crypto';\nimport { buffer } from 'node:stream/consumers';\nimport { Readable } from 'node:stream';\nimport {\n InferSnapshot,\n ResourceInfo,\n PlTreeEntry,\n ResourceWithMetadata,\n rsSchema,\n makeResourceSnapshot,\n treeEntryToResourceWithMetadata,\n ResourceSnapshot,\n treeEntryToResourceInfo,\n isPlTreeEntry\n} from '@milaboratories/pl-tree';\nimport {\n AnyLogHandle,\n BlobDriver,\n LocalBlobHandle,\n LocalBlobHandleAndSize,\n ReadyLogHandle,\n RemoteBlobHandle,\n RemoteBlobHandleAndSize,\n StreamingApiResponse\n} from '@milaboratories/pl-model-common';\nimport { dataToHandle, handleToData, isReadyLogHandle } from './logs';\nimport { z } from 'zod';\nimport { NetworkError400 } from '../helpers/download';\n\n/** ResourceSnapshot that can be passed to OnDemandBlob */\nexport const OnDemandBlobResourceSnapshot = rsSchema({\n kv: {\n 'ctl/file/blobInfo': z.object({\n sizeBytes: z.coerce.number()\n })\n }\n});\n\nexport type OnDemandBlobResourceSnapshot = InferSnapshot<typeof OnDemandBlobResourceSnapshot>;\n\nexport type DownloadDriverOps = {\n /**\n * A soft limit of the amount of blob storage, in bytes.\n * Once exceeded, the download driver will start deleting blobs one by one\n * when they become unneeded.\n * */\n cacheSoftSizeBytes: number;\n /**\n * Max number of concurrent downloads while calculating computable states\n * derived from this driver\n * */\n nConcurrentDownloads: number;\n};\n\n/** DownloadDriver holds a queue of downloading tasks,\n * and notifies every watcher when a file were downloaded. */\nexport class DownloadDriver implements BlobDriver {\n /** Represents a Resource Id to the path of a blob as a map. */\n private idToDownload: Map<ResourceId, Download> = new Map();\n\n /** Writes and removes files to a hard drive and holds a counter for every\n * file that should be kept. */\n private cache: FilesCache<Download>;\n\n /** Downloads files and writes them to the local dir. */\n private downloadQueue: TaskProcessor;\n\n private idToOnDemand: Map<ResourceId, OnDemandBlobHolder> = new Map();\n\n private idToLastLines: Map<ResourceId, LastLinesGetter> = new Map();\n private idToProgressLog: Map<ResourceId, LastLinesGetter> = new Map();\n\n private readonly saveDir: string;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientDownload: ClientDownload,\n private readonly clientLogs: ClientLogs,\n saveDir: string,\n private readonly signer: Signer,\n ops: DownloadDriverOps\n ) {\n this.cache = new FilesCache(ops.cacheSoftSizeBytes);\n this.downloadQueue = new TaskProcessor(this.logger, ops.nConcurrentDownloads);\n\n this.saveDir = path.resolve(saveDir);\n }\n\n /** Gets a blob by its resource id or downloads a blob and sets it in a cache.*/\n getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx: ComputableCtx\n ): LocalBlobHandleAndSize | undefined;\n getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry\n ): ComputableStableDefined<LocalBlobHandleAndSize>;\n getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<LocalBlobHandleAndSize | undefined> | LocalBlobHandleAndSize | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getDownloadedBlob(res, ctx));\n\n const rInfo = treeEntryToResourceInfo(res, ctx);\n\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(rInfo.id, callerId));\n\n const result = this.getDownloadedBlobNoCtx(ctx.watcher, rInfo as ResourceSnapshot, callerId);\n if (result == undefined) ctx.markUnstable('download blob is still undefined');\n\n return result;\n }\n\n getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry\n ): Computable<RemoteBlobHandleAndSize>;\n getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx: ComputableCtx\n ): RemoteBlobHandleAndSize;\n getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx?: ComputableCtx\n ): ComputableStableDefined<RemoteBlobHandleAndSize> | RemoteBlobHandleAndSize | undefined {\n if (ctx === undefined) return Computable.make((ctx) => this.getOnDemandBlob(res, ctx));\n\n const rInfo: OnDemandBlobResourceSnapshot = isPlTreeEntry(res)\n ? makeResourceSnapshot(res, OnDemandBlobResourceSnapshot, ctx)\n : res;\n\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseOnDemandBlob(rInfo.id, callerId));\n\n const result = this.getOnDemandBlobNoCtx(ctx.watcher, rInfo, callerId);\n\n return result;\n }\n\n public getLocalPath(handle: LocalBlobHandle): string {\n return localHandleToPath(handle, this.signer);\n }\n\n public async getContent(handle: LocalBlobHandle | RemoteBlobHandle): Promise<Uint8Array> {\n if (isLocalBlobHandle(handle)) return await read(this.getLocalPath(handle));\n\n if (!isRemoteBlobHandle(handle)) throw new Error('Malformed remote handle');\n\n const result = remoteHandleToData(handle, this.signer);\n const { content } = await this.clientDownload.downloadBlob(result);\n\n return await buffer(content);\n }\n\n private getDownloadedBlobNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n callerId: string\n ): LocalBlobHandleAndSize | undefined {\n let task = this.idToDownload.get(rInfo.id);\n\n if (task === undefined) {\n // schedule the blob downloading\n const newTask = this.setNewDownloadTask(w, rInfo, callerId);\n this.downloadQueue.push({\n fn: () => this.downloadBlob(newTask, callerId),\n recoverableErrorPredicate: (_) => true\n });\n task = newTask;\n }\n\n task.attach(w, callerId);\n const result = task.getBlob();\n if (result === undefined) return undefined;\n if (result.ok) return result.value;\n throw result.error;\n }\n\n private setNewDownloadTask(w: Watcher, rInfo: ResourceSnapshot, callerId: string) {\n const fPath = this.getFilePath(rInfo.id);\n const result = new Download(\n this.clientDownload,\n rInfo,\n fPath,\n dataToLocalHandle(fPath, this.signer)\n );\n this.idToDownload.set(rInfo.id, result);\n\n return result;\n }\n\n private async downloadBlob(task: Download, callerId: string) {\n await task.download();\n if (task.getBlob()?.ok) this.cache.addCache(task, callerId);\n }\n\n private getOnDemandBlobNoCtx(\n w: Watcher,\n info: OnDemandBlobResourceSnapshot,\n callerId: string\n ): RemoteBlobHandleAndSize {\n let blob = this.idToOnDemand.get(info.id);\n\n if (blob === undefined) {\n blob = new OnDemandBlobHolder(\n info.kv['ctl/file/blobInfo'].sizeBytes,\n dataToRemoteHandle(info, this.signer)\n );\n this.idToOnDemand.set(info.id, blob);\n }\n\n blob.attach(w, callerId);\n\n return blob.getHandle();\n }\n\n /** Returns all logs and schedules a job that reads remain logs.\n * Notifies when a new portion of the log appeared. */\n getLastLogs(res: ResourceInfo | PlTreeEntry, lines: number): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx: ComputableCtx\n ): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined) return Computable.make((ctx) => this.getLastLogs(res, lines, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(r.id, callerId));\n\n const result = this.getLastLogsNoCtx(ctx.watcher, r as ResourceSnapshot, lines, callerId);\n if (result == undefined)\n ctx.markUnstable('either a file was not downloaded or logs was not read');\n\n return result;\n }\n\n private getLastLogsNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n lines: number,\n callerId: string\n ): string | undefined {\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n\n const path = localHandleToPath(blob.handle, this.signer);\n\n let logGetter = this.idToLastLines.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, lines);\n this.idToLastLines.set(rInfo.id, newLogGetter);\n logGetter = newLogGetter;\n }\n\n const result = logGetter.getOrSchedule(w);\n if (result.error) throw result.error;\n\n return result.log;\n }\n\n /** Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string\n ): Computable<string | undefined>;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx: ComputableCtx\n ): string | undefined;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined)\n return Computable.make((ctx) => this.getProgressLog(res, patternToSearch, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(r.id, callerId));\n\n const result = this.getProgressLogNoCtx(\n ctx.watcher,\n r as ResourceSnapshot,\n patternToSearch,\n callerId\n );\n if (result === undefined)\n ctx.markUnstable('either a file was not downloaded or a progress log was not read');\n\n return result;\n }\n\n private getProgressLogNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n patternToSearch: string,\n callerId: string\n ): string | undefined {\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n const path = localHandleToPath(blob.handle, this.signer);\n\n let logGetter = this.idToProgressLog.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, 1, patternToSearch);\n this.idToProgressLog.set(rInfo.id, newLogGetter);\n\n logGetter = newLogGetter;\n }\n\n const result = logGetter.getOrSchedule(w);\n if (result.error) throw result.error;\n\n return result.log;\n }\n\n /** Returns an Id of a smart object, that can read logs directly from\n * the platform. */\n getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<AnyLogHandle>;\n getLogHandle(res: ResourceInfo | PlTreeEntry, ctx: ComputableCtx): AnyLogHandle;\n getLogHandle(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<AnyLogHandle> | AnyLogHandle {\n if (ctx == undefined) return Computable.make((ctx) => this.getLogHandle(res, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n\n return this.getLogHandleNoCtx(r as ResourceSnapshot);\n }\n\n private getLogHandleNoCtx(rInfo: ResourceSnapshot): AnyLogHandle {\n return dataToHandle(false, rInfo);\n }\n\n async lastLines(\n handle: ReadyLogHandle,\n lineCount: number,\n offsetBytes?: number, // if 0n, then start from the end.\n searchStr?: string\n ): Promise<StreamingApiResponse> {\n const resp = await this.clientLogs.lastLines(\n handleToData(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr\n );\n\n return {\n live: false,\n shouldUpdateHandle: false,\n data: resp.data,\n size: Number(resp.size),\n newOffset: Number(resp.newOffset)\n };\n }\n\n async readText(\n handle: ReadyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string\n ): Promise<StreamingApiResponse> {\n const resp = await this.clientLogs.readText(\n handleToData(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr\n );\n\n return {\n live: false,\n shouldUpdateHandle: false,\n data: resp.data,\n size: Number(resp.size),\n newOffset: Number(resp.newOffset)\n };\n }\n\n private async releaseBlob(blobId: ResourceId, callerId: string) {\n const task = this.idToDownload.get(blobId);\n if (task == undefined) return;\n\n if (this.cache.existsFile(task.path)) {\n const toDelete = this.cache.removeFile(task.path, callerId);\n await Promise.all(\n toDelete.map(async (task) => {\n await fsp.rm(task.path);\n\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${task.path} was removed` +\n `from cache along with ${toDelete.map((d) => d.path)}`\n );\n })\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted) this.removeTask(task, `the task ${task.path} was removed from cache`);\n }\n }\n\n private removeTask(task: Download, reason: string) {\n task.abort(reason);\n task.change.markChanged();\n this.idToDownload.delete(task.rInfo.id);\n this.idToLastLines.delete(task.rInfo.id);\n this.idToProgressLog.delete(task.rInfo.id);\n }\n\n private async releaseOnDemandBlob(blobId: ResourceId, callerId: string) {\n const deleted = this.idToOnDemand.get(blobId)?.release(callerId) ?? false;\n if (deleted) this.idToOnDemand.delete(blobId);\n }\n\n /** Removes all files from a hard drive. */\n async releaseAll() {\n this.downloadQueue.stop();\n\n this.idToDownload.forEach((task, blobId) => {\n this.idToDownload.delete(blobId);\n task.change.markChanged();\n });\n }\n\n private getFilePath(rId: ResourceId): string {\n return path.resolve(path.join(this.saveDir, String(BigInt(rId))));\n }\n}\n\nclass OnDemandBlobHolder {\n private readonly change = new ChangeSource();\n private readonly counter = new CallersCounter();\n\n constructor(\n private readonly size: number,\n private readonly handle: RemoteBlobHandle\n ) {}\n\n getHandle(): RemoteBlobHandleAndSize {\n return { handle: this.handle, size: this.size };\n }\n\n attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n this.change.attachWatcher(w);\n }\n\n release(callerId: string): boolean {\n return this.counter.dec(callerId);\n }\n}\n\nclass LastLinesGetter {\n private updater: helper.Updater;\n private log: string | undefined;\n private readonly change: ChangeSource = new ChangeSource();\n private error: any | undefined = undefined;\n\n constructor(\n private readonly path: string,\n private readonly lines: number,\n private readonly patternToSearch?: string\n ) {\n this.updater = new helper.Updater(async () => this.update());\n }\n\n getOrSchedule(w: Watcher): {\n log: string | undefined;\n error?: any | undefined;\n } {\n this.change.attachWatcher(w);\n\n this.updater.schedule();\n\n return {\n log: this.log,\n error: this.error\n };\n }\n\n async update(): Promise<void> {\n try {\n const newLogs = await getLastLines(this.path, this.lines, this.patternToSearch);\n\n if (this.log != newLogs) this.change.markChanged();\n this.log = newLogs;\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n // No resource\n this.log = '';\n this.error = e;\n this.change.markChanged();\n return;\n }\n\n throw e;\n }\n }\n}\n\nasync function fileOrDirExists(path: string): Promise<boolean> {\n try {\n await fsp.access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function read(path: string): Promise<Uint8Array> {\n return await buffer(Readable.toWeb(fs.createReadStream(path)));\n}\n\n/** Gets last lines from a file by reading the file from the top and keeping\n * last N lines in a window queue. */\nfunction getLastLines(fPath: PathLike, nLines: number, patternToSearch?: string): Promise<string> {\n const inStream = fs.createReadStream(fPath);\n const outStream = new Writable();\n\n return new Promise((resolve, reject) => {\n const rl = readline.createInterface(inStream, outStream);\n\n const lines = new Denque();\n rl.on('line', function (line) {\n if (patternToSearch != undefined && !line.includes(patternToSearch)) return;\n\n lines.push(line);\n if (lines.length > nLines) {\n lines.shift();\n }\n });\n\n rl.on('error', reject);\n\n rl.on('close', function () {\n // last EOL is for keeping backward compat with platforma implementation.\n resolve(lines.toArray().join(os.EOL) + os.EOL);\n });\n });\n}\n\nexport class Download {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n readonly signalCtl = new AbortController();\n error: any | undefined;\n done = false;\n sizeBytes = 0;\n\n constructor(\n readonly clientDownload: ClientDownload,\n readonly rInfo: ResourceSnapshot,\n readonly path: string,\n readonly handle: LocalBlobHandle\n ) {}\n\n attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n if (!this.done) this.change.attachWatcher(w);\n }\n\n async download() {\n try {\n // TODO: move size bytes inside fileExists check like in download_url.\n const { content, size } = await this.clientDownload.downloadBlob(this.rInfo);\n\n if (!(await fileOrDirExists(path.dirname(this.path))))\n await fsp.mkdir(path.dirname(this.path), { recursive: true });\n\n // check in case we already have a file by this resource id\n // in the directory. It can happen when we forgot to call removeAll\n // in the previous launch.\n if (await fileOrDirExists(this.path)) {\n await content.cancel(`the file already existed`); // we don't need the blob\n } else {\n const fileToWrite = Writable.toWeb(fs.createWriteStream(this.path));\n await content.pipeTo(fileToWrite);\n }\n\n this.setDone(size);\n } catch (e: any) {\n if (\n e instanceof DownloadAborted ||\n e instanceof NetworkError400 ||\n e instanceof UnknownStorageError ||\n e instanceof WrongLocalFileUrl ||\n e.code == 'ENOENT' // file that we downloads from was moved or deleted.\n ) {\n this.setError(e);\n // Just in case we were half-way extracting an archive.\n await fsp.rm(this.path);\n return;\n }\n\n throw e;\n }\n }\n\n getBlob(): ValueOrError<LocalBlobHandleAndSize> | undefined {\n if (this.done)\n return {\n ok: true,\n value: {\n handle: this.handle,\n size: this.sizeBytes\n }\n };\n\n if (this.error)\n return {\n ok: false,\n error: this.error\n };\n\n return undefined;\n }\n\n private setDone(sizeBytes: number) {\n this.done = true;\n this.sizeBytes = sizeBytes;\n this.change.markChanged();\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new DownloadAborted(reason));\n }\n\n private setError(e: any) {\n this.error = e;\n this.change.markChanged();\n }\n}\n\ntype PathLike = string;\n\nclass DownloadAborted extends Error {}\n\n// https://regex101.com/r/kfnBVX/1\nconst localHandleRegex = /^blob\\+local:\\/\\/download\\/(?<path>.*)#(?<signature>.*)$/;\n\nfunction isLocalBlobHandle(handle: string): handle is LocalBlobHandle {\n return Boolean(handle.match(localHandleRegex));\n}\n\nfunction localHandleToPath(handle: LocalBlobHandle, signer: Signer): string {\n const parsed = handle.match(localHandleRegex);\n\n if (parsed === null) throw new Error(`Local handle is malformed: ${handle}, matches: ${parsed}`);\n\n const { path, signature } = parsed.groups!;\n\n signer.verify(path, signature, `Signature verification failed for: ${handle}`);\n\n return path;\n}\n\nfunction dataToLocalHandle(path: string, signer: Signer): LocalBlobHandle {\n return `blob+local://download/${path}#${signer.sign(path)}` as LocalBlobHandle;\n}\n\n// https://regex101.com/r/rvbPZt/1\nconst remoteHandleRegex =\n /^blob\\+remote:\\/\\/download\\/(?<content>(?<resourceType>.*)\\/(?<resourceVersion>.*)\\/(?<resourceId>.*))#(?<signature>.*)$/;\n\nfunction isRemoteBlobHandle(handle: string): handle is RemoteBlobHandle {\n return Boolean(handle.match(remoteHandleRegex));\n}\n\nfunction remoteHandleToData(handle: RemoteBlobHandle, signer: Signer): ResourceInfo {\n const parsed = handle.match(remoteHandleRegex);\n if (parsed === null) throw new Error(`Remote handle is malformed: ${handle}, matches: ${parsed}`);\n\n const { content, resourceType, resourceVersion, resourceId, signature } = parsed.groups!;\n\n signer.verify(content, signature, `Signature verification failed for ${handle}`);\n\n return {\n id: bigintToResourceId(BigInt(resourceId)),\n type: { name: resourceType, version: resourceVersion }\n };\n}\n\nfunction dataToRemoteHandle(rInfo: OnDemandBlobResourceSnapshot, signer: Signer): RemoteBlobHandle {\n const content = `${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}`;\n return `blob+remote://download/${content}#${signer.sign(content)}` as RemoteBlobHandle;\n}\n","import { z } from 'zod';\n\nexport const ImportFileHandleUploadData = z.object({\n /** Local file path, to take data for upload */\n localPath: z.string(),\n /** Path signature, to check this data was generated by us */\n pathSignature: z.string(),\n /** File size in bytes */\n sizeBytes: z.string(),\n /** Modification time unix timestamp in seconds */\n modificationTime: z.string()\n});\nexport type ImportFileHandleUploadData = z.infer<typeof ImportFileHandleUploadData>;\n\nexport const ImportFileHandleIndexData = z.object({\n /** Pl storage id */\n storageId: z.string(),\n /** Path inside storage */\n path: z.string()\n});\nexport type ImportFileHandleIndexData = z.infer<typeof ImportFileHandleIndexData>;\n\nexport const ImportFileHandleData = z.union([\n ImportFileHandleUploadData,\n ImportFileHandleIndexData\n]);\nexport type ImportFileHandleData = z.infer<typeof ImportFileHandleData>;\n\n/** Defines which storages from pl are available via local paths */\nexport type LocalStorageProjection = {\n /** Pl storage id */\n readonly storageId: string;\n\n /**\n * Local path, the storage is mounted at.\n *\n * Empty string means that this storage accepts absolute paths, and operates inside the same OS.\n * This matches the behaviour how pl interprets FS storage config.\n * */\n readonly localPath: string;\n};\n\n/** Allows to add parts of local FS as virtual storages, presenting homogeneous API to UI */\nexport type VirtualLocalStorageSpec = {\n /** Virtual storage ID, must not intersect with other storage ids */\n readonly name: string;\n\n /** Local path to \"chroot\" the API in */\n readonly root: string;\n\n /** Used as hint to UI controls to, set as initial path during browsing */\n readonly initialPath: string;\n};\n","import { randomUUID } from 'node:crypto';\nimport { ResourceId, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport {\n Watcher,\n ChangeSource,\n ComputableCtx,\n Computable,\n PollingComputableHooks\n} from '@milaboratories/computable';\nimport {\n MiLogger,\n asyncPool,\n TaskProcessor,\n CallersCounter,\n Signer\n} from '@milaboratories/ts-helpers';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { ProgressStatus, ClientProgress } from '../clients/progress';\nimport { ClientUpload, MTimeError, NoFileForUploading, UnexpectedEOF } from '../clients/upload';\nimport {\n InferSnapshot,\n isPlTreeEntry,\n isPlTreeEntryAccessor,\n makeResourceSnapshot,\n PlTreeEntry,\n PlTreeEntryAccessor,\n PlTreeNodeAccessor,\n rsSchema\n} from '@milaboratories/pl-tree';\nimport { scheduler } from 'node:timers/promises';\nimport { PollingOps } from './helpers/polling_ops';\nimport { ImportFileHandleUploadData } from './types';\n\n/** Options from BlobUpload resource that have to be passed to getProgress. */\n\n/** ResourceSnapshot that can be passed to GetProgressID */\nexport const UploadResourceSnapshot = rsSchema({\n data: ImportFileHandleUploadData,\n fields: {\n blob: false\n }\n});\n\nexport const IndexResourceSnapshot = rsSchema({\n fields: {\n incarnation: false\n }\n});\n\nexport type UploadResourceSnapshot = InferSnapshot<typeof UploadResourceSnapshot>;\nexport type IndexResourceSnapshot = InferSnapshot<typeof IndexResourceSnapshot>;\n\nexport type ImportResourceSnapshot = UploadResourceSnapshot | IndexResourceSnapshot;\n\nexport function makeBlobImportSnapshot(\n entryOrAccessor: PlTreeEntry | PlTreeNodeAccessor | PlTreeEntryAccessor,\n ctx: ComputableCtx\n): ImportResourceSnapshot {\n const node = isPlTreeEntry(entryOrAccessor)\n ? ctx.accessor(entryOrAccessor).node()\n : isPlTreeEntryAccessor(entryOrAccessor)\n ? entryOrAccessor.node()\n : entryOrAccessor;\n if (node.resourceType.name.startsWith('BlobUpload'))\n return makeResourceSnapshot(node, UploadResourceSnapshot);\n else return makeResourceSnapshot(node, IndexResourceSnapshot);\n}\n\nexport type UploadDriverOps = PollingOps & {\n /** How much parts of a file can be multipart-uploaded to S3 at once. */\n nConcurrentPartUploads: number;\n /** How much upload/indexing statuses of blobs can the driver ask\n * from the platform gRPC at once. */\n nConcurrentGetProgresses: number;\n};\n\n// TODO: add abort signal to Upload Tasks.\n\n/** Uploads blobs in a queue and holds counters, so it can stop not-needed\n * uploads.\n * Handles both Index and Upload blobs,\n * the client needs to pass concrete blobs from `handle` field. */\nexport class UploadDriver {\n private readonly idToProgress: Map<ResourceId, ProgressUpdater> = new Map();\n\n /** Holds a queue that upload blobs. */\n private readonly uploadQueue: TaskProcessor;\n private readonly hooks: PollingComputableHooks;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly signer: Signer,\n private readonly clientBlob: ClientUpload,\n private readonly clientProgress: ClientProgress,\n private readonly opts: UploadDriverOps = {\n nConcurrentPartUploads: 10,\n nConcurrentGetProgresses: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000\n }\n ) {\n this.uploadQueue = new TaskProcessor(this.logger, 1, {\n type: 'exponentialWithMaxDelayBackoff',\n initialDelay: 20,\n maxDelay: 15000, // 15 seconds\n backoffMultiplier: 1.5,\n jitter: 0.5\n });\n\n this.hooks = new PollingComputableHooks(\n () => this.startUpdating(),\n () => this.stopUpdating(),\n { stopDebounce: opts.stopPollingDelay },\n (resolve, reject) => this.scheduleOnNextState(resolve, reject)\n );\n }\n\n /** Returns a progress id and schedules an upload task if it's necessary. */\n getProgressId(\n handleResource: ImportResourceSnapshot | PlTreeEntry\n ): Computable<sdk.ImportProgress>;\n getProgressId(\n handleResource: ImportResourceSnapshot | PlTreeEntry,\n ctx: ComputableCtx\n ): sdk.ImportProgress;\n getProgressId(\n handleResource: ImportResourceSnapshot | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<sdk.ImportProgress> | sdk.ImportProgress {\n if (ctx == undefined) return Computable.make((ctx) => this.getProgressId(handleResource, ctx));\n\n const rInfo: ImportResourceSnapshot = isPlTreeEntry(handleResource)\n ? makeBlobImportSnapshot(handleResource, ctx)\n : handleResource;\n\n const callerId = randomUUID();\n ctx.attacheHooks(this.hooks);\n ctx.addOnDestroy(() => this.release(rInfo.id, callerId));\n\n const result = this.getProgressIdNoCtx(ctx.watcher, rInfo, callerId);\n if (!isProgressStable(result)) {\n ctx.markUnstable(\n `upload/index progress was got, but it's not stable: ${JSON.stringify(result)}`\n );\n }\n\n return result;\n }\n\n private getProgressIdNoCtx(\n w: Watcher,\n res: ImportResourceSnapshot,\n callerId: string\n ): sdk.ImportProgress {\n const blobExists =\n 'blob' in res.fields ? res.fields.blob !== undefined : res.fields.incarnation !== undefined;\n\n const value = this.idToProgress.get(res.id);\n\n if (value != undefined) {\n value.attach(w, callerId);\n return value.mustGetProgress(blobExists);\n }\n\n const newValue = new ProgressUpdater(\n this.logger,\n this.clientBlob,\n this.clientProgress,\n this.opts.nConcurrentPartUploads,\n this.signer,\n res\n );\n\n this.idToProgress.set(res.id, newValue);\n newValue.attach(w, callerId);\n\n if (newValue.progress.isUpload && newValue.progress.isUploadSignMatch)\n this.uploadQueue.push({\n fn: () => newValue.uploadBlobTask(),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e)\n });\n\n return newValue.mustGetProgress(blobExists);\n }\n\n /** Decrement counters for the file and remove an uploading if counter == 0. */\n private async release(id: ResourceId, callerId: string) {\n const value = this.idToProgress.get(id);\n if (value === undefined) return;\n\n const deleted = value.decCounter(callerId);\n if (deleted) this.idToProgress.delete(id);\n }\n\n /** Must be called when the driver is closing. */\n public async releaseAll() {\n this.uploadQueue.stop();\n }\n\n private scheduledOnNextState: ScheduledRefresh[] = [];\n\n private scheduleOnNextState(resolve: () => void, reject: (err: any) => void): void {\n this.scheduledOnNextState.push({ resolve, reject });\n }\n\n /** Called from observer */\n private startUpdating(): void {\n this.keepRunning = true;\n if (this.currentLoop === undefined) this.currentLoop = this.mainLoop();\n }\n\n /** Called from observer */\n private stopUpdating(): void {\n this.keepRunning = false;\n }\n\n /** If true, main loop will continue polling pl state. */\n private keepRunning = false;\n /** Actual state of main loop. */\n private currentLoop: Promise<void> | undefined = undefined;\n\n private async mainLoop() {\n while (this.keepRunning) {\n const toNotify = this.scheduledOnNextState;\n this.scheduledOnNextState = [];\n\n try {\n await asyncPool(\n this.opts.nConcurrentGetProgresses,\n this.getAllNotDoneProgresses().map((p) => async () => await p.updateStatus())\n );\n\n toNotify.forEach((n) => n.resolve());\n } catch (e: any) {\n console.error(e);\n toNotify.forEach((n) => n.reject(e));\n }\n\n if (!this.keepRunning) break;\n await scheduler.wait(this.opts.pollingInterval);\n }\n\n this.currentLoop = undefined;\n }\n\n private getAllNotDoneProgresses(): Array<ProgressUpdater> {\n return Array.from(this.idToProgress.entries())\n .filter(([_, p]) => !isProgressStable(p.progress))\n .map(([_, p]) => p);\n }\n}\n\n/** Holds all info needed to upload a file and a status of uploadong\n * and indexing. Also, has a method to update a status of the progress.\n * And holds a change source. */\nclass ProgressUpdater {\n private readonly change: ChangeSource = new ChangeSource();\n private readonly counter: CallersCounter = new CallersCounter();\n\n public progress: sdk.ImportProgress;\n /** If this is upload progress this field will be defined */\n private uploadData?: ImportFileHandleUploadData;\n public uploadingTerminallyFailed?: boolean;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientBlob: ClientUpload,\n private readonly clientProgress: ClientProgress,\n private readonly nConcurrentPartsUpload: number,\n signer: Signer,\n public readonly res: ImportResourceSnapshot\n ) {\n const isUpload = res.type.name.startsWith('BlobUpload');\n let isUploadSignMatch: boolean | undefined;\n if (isUpload) {\n this.uploadData = ImportFileHandleUploadData.parse(res.data);\n isUploadSignMatch = isSignMatch(\n signer,\n this.uploadData.localPath,\n this.uploadData.pathSignature\n );\n }\n\n this.progress = {\n done: false,\n status: undefined,\n isUpload: isUpload,\n isUploadSignMatch: isUploadSignMatch,\n lastError: undefined\n };\n }\n\n public mustGetProgress(blobExists: boolean) {\n // We provide a deep copy of progress,\n // since we do not want to pass a mutable object\n // to API, it led to bugs before.\n\n // We do not use '...' cloning syntax\n // for the compiler to fail here if we change API.\n const progress: sdk.ImportProgress = {\n done: this.progress.done,\n isUpload: this.progress.isUpload,\n isUploadSignMatch: this.progress.isUploadSignMatch,\n lastError: this.progress.lastError\n };\n if (this.progress.status)\n progress.status = {\n progress: this.progress.status.progress,\n bytesProcessed: this.progress.status.bytesProcessed,\n bytesTotal: this.progress.status.bytesTotal\n };\n\n if (blobExists) {\n this.setDone(blobExists);\n return progress;\n }\n\n if (this.uploadingTerminallyFailed) {\n this.logger.error(`Uploading terminally failed: ${this.progress.lastError}`);\n throw new Error(this.progress.lastError);\n }\n\n return progress;\n }\n\n public attach(w: Watcher, callerId: string) {\n this.change.attachWatcher(w);\n this.counter.inc(callerId);\n }\n\n public decCounter(callerId: string) {\n return this.counter.dec(callerId);\n }\n\n /** Uploads a blob if it's not BlobIndex. */\n async uploadBlobTask() {\n try {\n await this.uploadBlob();\n } catch (e: any) {\n this.setLastError(e);\n\n if (isResourceWasDeletedError(e)) {\n this.logger.warn(`resource was deleted while uploading a blob: ${e}`);\n this.change.markChanged();\n this.setDone(true);\n\n return;\n }\n\n this.logger.error(`error while uploading a blob: ${e}`);\n this.change.markChanged();\n\n if (nonRecoverableError(e)) this.terminateWithError(e);\n\n throw e;\n }\n }\n\n /** Uploads a blob using client. */\n private async uploadBlob() {\n if (this.counter.isZero()) return;\n const parts = await this.clientBlob.initUpload(this.res);\n\n this.logger.info(`start to upload blob ${this.res.id}, parts count: ${parts.length}`);\n\n const partUploadFn = (part: bigint) => async () => {\n if (this.counter.isZero()) return;\n await this.clientBlob.partUpload(\n this.res,\n this.uploadData!.localPath,\n part,\n parts.length,\n BigInt(this.uploadData!.modificationTime)\n );\n };\n\n await asyncPool(this.nConcurrentPartsUpload, parts.map(partUploadFn));\n\n if (this.counter.isZero()) return;\n await this.clientBlob.finalizeUpload(this.res);\n\n this.logger.info(`uploading of resource ${this.res.id} finished.`);\n this.change.markChanged();\n }\n\n private terminateWithError(e: unknown) {\n this.progress.lastError = String(e);\n this.progress.done = false;\n this.uploadingTerminallyFailed = true;\n }\n\n private setLastError(e: unknown) {\n this.progress.lastError = String(e);\n }\n\n private setDone(done: boolean) {\n this.progress.done = done;\n if (done) this.progress.lastError = undefined;\n }\n\n async updateStatus() {\n try {\n const status = await this.clientProgress.getStatus(this.res);\n\n const oldStatus = this.progress.status;\n this.progress.status = protoToStatus(status);\n this.setDone(status.done);\n\n if (status.done || status.progress != oldStatus?.progress) this.change.markChanged();\n } catch (e: any) {\n this.setLastError(e);\n\n if (e.name == 'RpcError' && e.code == 'DEADLINE_EXCEEDED') {\n this.logger.warn(`deadline exceeded while getting a status of BlobImport`);\n return;\n }\n\n if (isResourceWasDeletedError(e)) {\n this.logger.warn(\n `resource was not found while updating a status of BlobImport: ${e}, ${stringifyWithResourceId(this.res)}`\n );\n this.change.markChanged();\n this.setDone(true);\n return;\n }\n\n this.logger.error(`error while updating a status of BlobImport: ${e}`);\n this.change.markChanged();\n this.terminateWithError(e);\n }\n }\n}\n\nfunction isProgressStable(p: sdk.ImportProgress) {\n return p.done && p.status !== undefined && p.status !== null && p.status.progress >= 1.0;\n}\n\nfunction protoToStatus(proto: ProgressStatus): sdk.ImportStatus {\n return {\n progress: proto.progress ?? 0,\n bytesProcessed: Number(proto.bytesProcessed),\n bytesTotal: Number(proto.bytesTotal)\n };\n}\n\nfunction isSignMatch(signer: Signer, path: string, signature: string): boolean {\n try {\n signer.verify(path, signature);\n return true;\n } catch (e) {\n return false;\n }\n}\n\nfunction nonRecoverableError(e: any) {\n return e instanceof MTimeError || e instanceof UnexpectedEOF || e instanceof NoFileForUploading;\n}\n\nfunction isResourceWasDeletedError(e: any) {\n return (\n e.name == 'RpcError' &&\n (e.code == 'NOT_FOUND' || e.code == 'ABORTED' || e.code == 'ALREADY_EXISTS')\n );\n}\n\ntype ScheduledRefresh = {\n resolve: () => void;\n reject: (err: any) => void;\n};\n","import {\n ChangeSource,\n Computable,\n ComputableCtx,\n PollingComputableHooks,\n Watcher\n} from '@milaboratories/computable';\nimport { ResourceId, resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport { asyncPool, CallersCounter, MiLogger } from '@milaboratories/ts-helpers';\nimport { ClientLogs } from '../clients/logs';\nimport { randomUUID } from 'node:crypto';\nimport { PlTreeEntry, ResourceInfo, treeEntryToResourceInfo } from '@milaboratories/pl-tree';\nimport { dataToHandle, handleToData, isLiveLogHandle } from './logs';\nimport { scheduler } from 'node:timers/promises';\nimport { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { PollingOps } from './helpers/polling_ops';\nimport { RpcError } from '@protobuf-ts/runtime-rpc';\n\nexport type LogsStreamDriverOps = PollingOps & {\n /** Max number of concurrent requests to log streaming backend while calculating computable states */\n nConcurrentGetLogs: number;\n};\n\nexport class LogsStreamDriver implements sdk.LogsDriver {\n /** Holds a map of StreamManager Resource Id to all logs of this stream. */\n private readonly idToLastLines: Map<ResourceId, LogGetter> = new Map();\n\n /** Holds a map of StreamManager Resource Id to the last log line of this stream. */\n private readonly idToProgressLog: Map<ResourceId, LogGetter> = new Map();\n\n /** Holds a map of StreamManager Resource Id to log id smart object. */\n private readonly hooks: PollingComputableHooks;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientLogs: ClientLogs,\n private readonly opts: LogsStreamDriverOps = {\n nConcurrentGetLogs: 10,\n pollingInterval: 1000,\n stopPollingDelay: 1000\n }\n ) {\n this.hooks = new PollingComputableHooks(\n () => this.startUpdating(),\n () => this.stopUpdating(),\n { stopDebounce: opts.stopPollingDelay },\n (resolve, reject) => this.scheduleOnNextState(resolve, reject)\n );\n }\n\n getLastLogs(res: ResourceInfo | PlTreeEntry, lines: number): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx: ComputableCtx\n ): Computable<string | undefined>;\n getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined) return Computable.make((ctx) => this.getLastLogs(res, lines, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.attacheHooks(this.hooks);\n ctx.addOnDestroy(() => this.releaseLastLogs(r.id, callerId));\n\n const result = this.getLastLogsNoCtx(ctx.watcher, r, lines, callerId);\n ctx.markUnstable(\n 'The logs are from stream, so we consider them unstable. Final values will be got from blobs.'\n );\n\n return result;\n }\n\n private getLastLogsNoCtx(\n w: Watcher,\n rInfo: ResourceInfo,\n lines: number,\n callerId: string\n ): string | undefined {\n let logGetter = this.idToLastLines.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LogGetter(this.logger, this.clientLogs, rInfo, lines);\n this.idToLastLines.set(rInfo.id, newLogGetter);\n\n logGetter = newLogGetter;\n }\n\n logGetter.attach(w, callerId);\n const result = logGetter.getLog();\n if (result.error != undefined) throw result.error;\n\n return result.log;\n }\n\n /** Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string\n ): Computable<string | undefined>;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx: ComputableCtx\n ): string | undefined;\n getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx\n ): Computable<string | undefined> | string | undefined {\n if (ctx == undefined)\n return Computable.make((ctx) => this.getProgressLog(res, patternToSearch, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n const callerId = randomUUID();\n ctx.attacheHooks(this.hooks);\n ctx.addOnDestroy(() => this.releaseProgressLog(r.id, callerId));\n\n const result = this.getProgressLogNoCtx(ctx.watcher, r, patternToSearch, callerId);\n ctx.markUnstable(\n 'The progress log is from the stream, so we consider it unstable. Final value will be got from blobs.'\n );\n\n return result;\n }\n\n private getProgressLogNoCtx(\n w: Watcher,\n rInfo: ResourceInfo,\n patternToSearch: string,\n callerId: string\n ): string | undefined {\n let logGetter = this.idToProgressLog.get(rInfo.id);\n\n if (logGetter == undefined) {\n const newLogGetter = new LogGetter(this.logger, this.clientLogs, rInfo, 1, patternToSearch);\n this.idToProgressLog.set(rInfo.id, newLogGetter);\n\n logGetter = newLogGetter;\n }\n\n logGetter.attach(w, callerId);\n const result = logGetter.getLog();\n if (result.error) throw result.error;\n\n return result.log;\n }\n\n getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<sdk.AnyLogHandle>;\n getLogHandle(res: ResourceInfo | PlTreeEntry, ctx: ComputableCtx): sdk.AnyLogHandle;\n getLogHandle(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx\n ): Computable<sdk.AnyLogHandle> | sdk.AnyLogHandle {\n if (ctx == undefined) return Computable.make((ctx) => this.getLogHandle(res, ctx));\n\n const r = treeEntryToResourceInfo(res, ctx);\n\n const result = this.getLogHandleNoCtx(r);\n \n // All logs from streams should be considered unstable,\n // final value will be got from blobs.\n ctx.markUnstable(`live_log:${resourceIdToString(r.id)}`);\n\n return result;\n }\n\n private getLogHandleNoCtx(rInfo: ResourceInfo): sdk.AnyLogHandle {\n return dataToHandle(true, rInfo);\n }\n\n async lastLines(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string | undefined\n ) {\n return await this.tryWithNotFound(handle, () =>\n this.clientLogs.lastLines(\n handleToData(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr\n )\n );\n }\n\n async readText(\n handle: sdk.AnyLogHandle,\n lineCount: number,\n offsetBytes?: number,\n searchStr?: string | undefined\n ) {\n return await this.tryWithNotFound(handle, () =>\n this.clientLogs.readText(handleToData(handle), lineCount, BigInt(offsetBytes ?? 0), searchStr)\n );\n }\n\n private async tryWithNotFound(\n handle: sdk.AnyLogHandle,\n method: () => Promise<StreamingAPI_Response>\n ): Promise<sdk.StreamingApiResponse> {\n if (!isLiveLogHandle(handle))\n throw new Error(`Not live log handle was passed to live log driver, handle: ${handle}`);\n\n try {\n const resp = await method();\n return {\n live: true,\n shouldUpdateHandle: false,\n data: resp.data,\n size: Number(resp.size),\n newOffset: Number(resp.newOffset)\n };\n } catch (e: any) {\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n return { shouldUpdateHandle: true };\n }\n\n throw e;\n }\n }\n\n private async releaseLastLogs(rId: ResourceId, callerId: string) {\n const deleted = this.idToLastLines.get(rId)?.release(callerId);\n if (deleted) this.idToLastLines.delete(rId);\n }\n\n private async releaseProgressLog(rId: ResourceId, callerId: string) {\n const deleted = this.idToProgressLog.get(rId)?.release(callerId);\n if (deleted) this.idToProgressLog.delete(rId);\n }\n\n async releaseAll() {}\n\n private scheduledOnNextState: ScheduledRefresh[] = [];\n\n private scheduleOnNextState(resolve: () => void, reject: (err: any) => void): void {\n this.scheduledOnNextState.push({ resolve, reject });\n }\n\n /** Called from observer */\n private startUpdating(): void {\n this.keepRunning = true;\n if (this.currentLoop === undefined) this.currentLoop = this.mainLoop();\n }\n\n /** Called from observer */\n private stopUpdating(): void {\n this.keepRunning = false;\n }\n\n /** If true, main loop will continue polling pl state. */\n private keepRunning = false;\n /** Actual state of main loop. */\n private currentLoop: Promise<void> | undefined = undefined;\n\n private async mainLoop() {\n while (this.keepRunning) {\n const toNotify = this.scheduledOnNextState;\n this.scheduledOnNextState = [];\n\n try {\n const logs = this.getAllLogs();\n await asyncPool(\n this.opts.nConcurrentGetLogs,\n logs.map((getter) => async () => await getter.update())\n );\n\n toNotify.forEach((n) => n.resolve());\n } catch (e: any) {\n console.error(e);\n toNotify.forEach((n) => n.reject(e));\n }\n\n if (!this.keepRunning) break;\n await scheduler.wait(this.opts.pollingInterval);\n }\n\n this.currentLoop = undefined;\n }\n\n private getAllLogs(): Array<LogGetter> {\n return Array.from(this.idToLastLines.entries())\n .concat(Array.from(this.idToProgressLog.entries()))\n .map(([_, getter]) => getter);\n }\n}\n\n/** A job that gets last lines from a StreamWorkdir resource. */\nclass LogGetter {\n private logs: string | undefined;\n private error: any | undefined = undefined;\n\n private readonly change: ChangeSource = new ChangeSource();\n private readonly counter: CallersCounter = new CallersCounter();\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientLogs: ClientLogs,\n private readonly rInfo: ResourceInfo,\n private readonly lines: number,\n private readonly patternToSearch?: string\n ) {}\n\n getLog(): {\n log: string | undefined;\n error?: any | undefined;\n } {\n return {\n log: this.logs,\n error: this.error\n };\n }\n\n attach(w: Watcher, callerId: string) {\n this.change.attachWatcher(w);\n this.counter.inc(callerId);\n }\n\n release(callerId: string): boolean {\n return this.counter.dec(callerId);\n }\n\n async update() {\n try {\n const resp = await this.clientLogs.lastLines(\n this.rInfo,\n this.lines,\n 0n,\n this.patternToSearch\n );\n\n const newLogs = resp.data.toString();\n\n if (this.logs != newLogs) this.change.markChanged();\n this.logs = newLogs;\n this.error = undefined;\n\n return;\n } catch (e: any) {\n e as RpcError;\n if (e.name == 'RpcError' && e.code == 'NOT_FOUND') {\n // No resource\n this.logs = '';\n this.error = e;\n this.change.markChanged();\n return;\n }\n\n this.logger.error(\n `Stream log lines for ${stringifyWithResourceId(this.rInfo.id)} failed, reason: ${e}`\n );\n throw e;\n }\n }\n}\n\ntype ScheduledRefresh = {\n resolve: () => void;\n reject: (err: any) => void;\n};\n","import {\n CallersCounter,\n MiLogger,\n TaskProcessor,\n notEmpty,\n fileExists\n} from '@milaboratories/ts-helpers';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Writable, Transform } from 'node:stream';\nimport { ChangeSource, Computable, ComputableCtx, Watcher } from '@milaboratories/computable';\nimport { randomUUID, createHash } from 'node:crypto';\nimport * as zlib from 'node:zlib';\nimport * as tar from 'tar-fs';\nimport { FilesCache } from './helpers/files_cache';\nimport { Dispatcher } from 'undici';\nimport { DownloadHelper, NetworkError400 } from '../helpers/download';\n\nexport interface DownloadUrlSyncReader {\n /** Returns a Computable that (when the time will come)\n * downloads an archive from an URL,\n * extracts it to the local dir and returns a path to that dir. */\n getPath(url: URL): Computable<PathResult | undefined>;\n}\n\nexport interface PathResult {\n /** Path to the downloadable blob, might be undefined when the error happened. */\n path?: string;\n /** Error that happened when the archive were downloaded. */\n error?: string;\n}\n\nexport type DownloadUrlDriverOps = {\n cacheSoftSizeBytes: number;\n withGunzip: boolean;\n nConcurrentDownloads: number;\n};\n\n/** Downloads .tar or .tar.gz archives by given URLs\n * and extracts them into saveDir. */\nexport class DownloadUrlDriver implements DownloadUrlSyncReader {\n private readonly downloadHelper: DownloadHelper;\n\n private urlToDownload: Map<string, Download> = new Map();\n private downloadQueue: TaskProcessor;\n\n /** Writes and removes files to a hard drive and holds a counter for every\n * file that should be kept. */\n private cache: FilesCache<Download>;\n\n constructor(\n private readonly logger: MiLogger,\n httpClient: Dispatcher,\n private readonly saveDir: string,\n private readonly opts: DownloadUrlDriverOps = {\n cacheSoftSizeBytes: 50 * 1024 * 1024,\n withGunzip: true,\n nConcurrentDownloads: 50\n }\n ) {\n this.downloadQueue = new TaskProcessor(this.logger, this.opts.nConcurrentDownloads);\n this.cache = new FilesCache(this.opts.cacheSoftSizeBytes);\n this.downloadHelper = new DownloadHelper(httpClient);\n }\n\n /** Use to get a path result inside a computable context */\n getPath(url: URL, ctx: ComputableCtx): PathResult | undefined;\n\n /** Returns a Computable that do the work */\n getPath(url: URL): Computable<PathResult | undefined>;\n\n getPath(\n url: URL,\n ctx?: ComputableCtx\n ): Computable<PathResult | undefined> | PathResult | undefined {\n // wrap result as computable, if we were not given an existing computable context\n if (ctx === undefined) return Computable.make((c) => this.getPath(url, c));\n\n const callerId = randomUUID();\n\n // read as ~ golang's defer\n ctx.addOnDestroy(() => this.releasePath(url, callerId));\n\n const result = this.getPathNoCtx(url, ctx.watcher, callerId);\n if (result?.path === undefined)\n ctx.markUnstable(\n `a path to the downloaded and untared archive might be undefined. The current result: ${result}`\n );\n\n return result;\n }\n\n getPathNoCtx(url: URL, w: Watcher, callerId: string) {\n const key = url.toString();\n const task = this.urlToDownload.get(key);\n\n if (task != undefined) {\n task.attach(w, callerId);\n return task.getPath();\n }\n\n const newTask = this.setNewTask(w, url, callerId);\n this.downloadQueue.push({\n fn: async () => this.downloadUrl(newTask, callerId),\n recoverableErrorPredicate: (e) => true\n });\n\n return newTask.getPath();\n }\n\n /** Downloads and extracts a tar archive if it wasn't downloaded yet. */\n async downloadUrl(task: Download, callerId: string) {\n await task.download(this.downloadHelper, this.opts.withGunzip);\n // Might be undefined if a error happened\n if (task.getPath()?.path != undefined) this.cache.addCache(task, callerId);\n }\n\n /** Removes a directory and aborts a downloading task when all callers\n * are not interested in it. */\n async releasePath(url: URL, callerId: string): Promise<void> {\n const key = url.toString();\n const task = this.urlToDownload.get(key);\n if (task == undefined) return;\n\n if (this.cache.existsFile(task.path)) {\n const toDelete = this.cache.removeFile(task.path, callerId);\n\n await Promise.all(\n toDelete.map(async (task) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${JSON.stringify(task)} was removed` +\n `from cache along with ${JSON.stringify(toDelete)}`\n );\n })\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted) this.removeTask(task, `the task ${JSON.stringify(task)} was removed from cache`);\n }\n }\n\n /** Removes all files from a hard drive. */\n async releaseAll() {\n this.downloadQueue.stop();\n\n await Promise.all(\n Array.from(this.urlToDownload.entries()).map(async ([id, task]) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(task, `the task ${task} was released when the driver was closed`);\n })\n );\n }\n\n private setNewTask(w: Watcher, url: URL, callerId: string) {\n const result = new Download(this.getFilePath(url), url);\n result.attach(w, callerId);\n this.urlToDownload.set(url.toString(), result);\n\n return result;\n }\n\n private removeTask(task: Download, reason: string) {\n task.abort(reason);\n task.change.markChanged();\n this.urlToDownload.delete(task.url.toString());\n }\n\n private getFilePath(url: URL): string {\n const sha256 = createHash('sha256').update(url.toString()).digest('hex');\n return path.join(this.saveDir, sha256);\n }\n}\n\nclass Download {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n readonly signalCtl = new AbortController();\n error: string | undefined;\n done = false;\n sizeBytes = 0;\n\n constructor(\n readonly path: string,\n readonly url: URL\n ) {}\n\n attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n if (!this.done) this.change.attachWatcher(w);\n }\n\n async download(clientDownload: DownloadHelper, withGunzip: boolean) {\n try {\n const sizeBytes = await this.downloadAndUntar(\n clientDownload,\n withGunzip,\n this.signalCtl.signal\n );\n this.setDone(sizeBytes);\n } catch (e: any) {\n if (e instanceof URLAborted || e instanceof NetworkError400) {\n this.setError(e);\n // Just in case we were half-way extracting an archive.\n await rmRFDir(this.path);\n return;\n }\n\n throw e;\n }\n }\n\n private async downloadAndUntar(\n clientDownload: DownloadHelper,\n withGunzip: boolean,\n signal: AbortSignal\n ): Promise<number> {\n if (await fileExists(this.path)) {\n return await dirSize(this.path);\n }\n\n const resp = await clientDownload.downloadRemoteFile(this.url.toString(), {}, signal);\n let content = resp.content;\n\n if (withGunzip) {\n const gunzip = Transform.toWeb(zlib.createGunzip());\n content = content.pipeThrough(gunzip, { signal });\n }\n const untar = Writable.toWeb(tar.extract(this.path));\n await content.pipeTo(untar, { signal });\n\n return resp.size;\n }\n\n getPath(): PathResult | undefined {\n if (this.done) return { path: notEmpty(this.path) };\n\n if (this.error) return { error: this.error };\n\n return undefined;\n }\n\n private setDone(sizeBytes: number) {\n this.done = true;\n this.sizeBytes = sizeBytes;\n this.change.markChanged();\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new URLAborted(reason));\n }\n\n private setError(e: any) {\n this.error = String(e);\n this.change.markChanged();\n }\n}\n\nclass URLAborted extends Error {}\n\n/** Gets a directory size by calculating sizes recursively. */\nasync function dirSize(dir: string): Promise<number> {\n const files = await fsp.readdir(dir, { withFileTypes: true });\n const sizes = await Promise.all(\n files.map(async (file) => {\n const fPath = path.join(dir, file.name);\n\n if (file.isDirectory()) return await dirSize(fPath);\n\n const stat = await fsp.stat(fPath);\n return stat.size;\n })\n );\n\n return sizes.reduce((sum, size) => sum + size, 0);\n}\n\n/** Do rm -rf on dir. */\nasync function rmRFDir(path: string) {\n await fsp.rm(path, { recursive: true, force: true });\n}\n","import { MiLogger, notEmpty, Signer } from '@milaboratories/ts-helpers';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport { Timestamp } from '../../proto/google/protobuf/timestamp';\nimport { Dirent, Stats } from 'node:fs';\nimport { z } from 'zod';\nimport { ImportFileHandleIndexData, ImportFileHandleUploadData } from '../types';\n\n/** A duck-typing interface for grpc results. */\nexport interface ListResponse {\n items: ListItem[];\n delimiter: string;\n}\n/** @deprecated */\nexport interface ListItem {\n isDir: boolean;\n name: string;\n fullName: string;\n lastModified?: Timestamp;\n size: bigint;\n directory: string;\n}\n\n/** @deprecated */\nexport function toLsEntries(info: {\n storageName: string;\n list: ListResponse;\n signer: Signer;\n remote: boolean;\n}): sdk.ListFilesResult {\n const parent = info.list.items.length > 0 ? info.list.items[0]?.directory : undefined;\n\n return {\n parent: parent,\n entries: info.list.items.map((item) => toLsEntry(item, info))\n };\n}\n\n/** @deprecated */\nfunction toLsEntry(\n item: ListItem,\n info: {\n storageName: string;\n list: ListResponse;\n signer: Signer;\n remote: boolean;\n }\n): sdk.LsEntry {\n if (item.isDir)\n return {\n type: 'dir',\n name: item.name,\n fullPath: item.fullName\n };\n\n return {\n type: 'file',\n name: item.name,\n fullPath: item.fullName,\n handle: toFileHandle({ item: item, ...info })\n };\n}\n\n/** @deprecated */\nexport function toFileHandle(info: {\n storageName: string;\n item: ListItem;\n signer: Signer;\n remote: boolean;\n}): sdk.ImportFileHandle {\n if (info.remote) {\n return createIndexImportHandle(info.storageName, info.item.fullName);\n }\n\n return createUploadImportHandle(\n info.item.fullName,\n info.signer,\n info.item.size,\n notEmpty(info.item.lastModified).seconds\n );\n}\n\nexport function createIndexImportHandle(\n storageName: string,\n path: string\n): sdk.ImportFileHandleIndex {\n const data: ImportFileHandleIndexData = {\n storageId: storageName,\n path: path\n };\n\n return `index://index/${encodeURIComponent(JSON.stringify(data))}`;\n}\n\nexport function createUploadImportHandle(\n localPath: string,\n signer: Signer,\n sizeBytes: bigint,\n modificationTimeSeconds: bigint\n): sdk.ImportFileHandleUpload {\n const data: ImportFileHandleUploadData = {\n localPath,\n pathSignature: signer.sign(localPath),\n sizeBytes: String(sizeBytes),\n modificationTime: String(modificationTimeSeconds)\n };\n\n return `upload://upload/${encodeURIComponent(JSON.stringify(data))}`;\n}\n\nexport function parseUploadHandle(handle: sdk.ImportFileHandleUpload): ImportFileHandleUploadData {\n const url = new URL(handle);\n return ImportFileHandleUploadData.parse(\n JSON.parse(decodeURIComponent(url.pathname.substring(1)))\n );\n}\n\nexport function parseIndexHandle(handle: sdk.ImportFileHandleIndex): ImportFileHandleIndexData {\n const url = new URL(handle);\n return ImportFileHandleIndexData.parse(JSON.parse(decodeURIComponent(url.pathname.substring(1))));\n}\n\nexport function toListItem(\n logger: MiLogger,\n info: {\n directory: string;\n fullName: string;\n dirent: Dirent;\n stat: Stats;\n }\n): ListItem | undefined {\n if (!(info.dirent.isFile() || info.dirent.isDirectory())) {\n logger.warn(`tried to get non-dir and non-file ${info.dirent.name}, skip it`);\n return;\n }\n\n return {\n directory: info.directory,\n isDir: info.dirent.isDirectory(),\n name: info.dirent.name,\n fullName: info.fullName,\n lastModified: {\n seconds: BigInt(Math.floor(info.stat.mtimeMs / 1000)),\n nanos: 0\n },\n size: BigInt(info.stat.size)\n };\n}\n","import * as sdk from '@milaboratories/pl-model-common';\nimport { bigintToResourceId, ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { assertNever } from '@milaboratories/ts-helpers';\n\nexport type StorageHandleData = RemoteStorageHandleData | LocalStorageHandleData;\n\n/**\n * Gets a storage handle and gives an underlying data from it.\n */\nexport function parseStorageHandle(handle: sdk.StorageHandle): StorageHandleData {\n if (isRemoteStorageHandle(handle)) {\n return parseRemoteStorageHandle(handle);\n } else if (isLocalStorageHandle(handle)) {\n return parseLocalStorageHandle(handle);\n }\n\n assertNever(handle);\n}\n\n//\n// Local storage:\n//\n\nexport type LocalStorageHandleData = {\n isRemote: false;\n name: string;\n rootPath: string;\n};\n\nconst localHandleRegex = /^local:\\/\\/(?<name>.*)\\/(?<path>.*)$/;\n\nexport function isLocalStorageHandle(handle: sdk.StorageHandle): handle is sdk.StorageHandleLocal {\n return localHandleRegex.test(handle);\n}\n\nexport function createLocalStorageHandle(name: string, path: string): sdk.StorageHandleLocal {\n return `local://${name}/${encodeURIComponent(path)}`;\n}\n\nfunction parseLocalStorageHandle(handle: string): LocalStorageHandleData {\n const parsed = handle.match(localHandleRegex);\n if (parsed == null) throw new Error(`Local list handle wasn't parsed: ${handle}`);\n\n const { name, path } = parsed.groups!;\n\n return {\n rootPath: decodeURIComponent(path),\n name,\n isRemote: false\n };\n}\n\n//\n// Remote storage:\n//\n\nexport type RemoteStorageHandleData = {\n isRemote: true;\n name: string;\n id: ResourceId;\n type: ResourceType;\n};\n\nconst remoteHandleRegex = /^remote:\\/\\/(?<name>.*)\\/(?<resourceId>.*)$/;\n\nexport function isRemoteStorageHandle(\n handle: sdk.StorageHandle\n): handle is sdk.StorageHandleRemote {\n return remoteHandleRegex.test(handle);\n}\n\nexport function createRemoteStorageHandle(name: string, rId: ResourceId): sdk.StorageHandleRemote {\n return `remote://${name}/${BigInt(rId)}`;\n}\n\nfunction parseRemoteStorageHandle(handle: string): RemoteStorageHandleData {\n const parsed = handle.match(remoteHandleRegex);\n if (parsed == null) throw new Error(`Remote list handle wasn't parsed: ${handle}`);\n const { name, resourceId } = parsed.groups!;\n\n return {\n id: bigintToResourceId(BigInt(resourceId)),\n type: storageType(name),\n name,\n isRemote: true\n };\n}\n\nfunction storageType(name: string): ResourceType {\n return { name: `LS/${name}`, version: '1' };\n}\n","import path from 'path';\nimport os from 'os';\nimport util from 'util';\nimport { exec } from 'child_process';\nimport { VirtualLocalStorageSpec } from './types';\n\nexport async function DefaultVirtualLocalStorages(): Promise<VirtualLocalStorageSpec[]> {\n const home = os.homedir();\n if (path.sep == '/')\n return [\n {\n name: 'local',\n root: '/',\n initialPath: home\n }\n ];\n else {\n // determine the drive on which user's home folder is stored\n const homeRoot = path.parse(home).root; // e.g. C:\\\n const homeDrive = homeRoot.replaceAll(':\\\\', ''); // e.g. C drive.\n\n // code below inspired by\n // https://stackoverflow.com/a/52411712/769192\n\n try {\n const wmic = await util.promisify(exec)('wmic logicaldisk get name');\n // parsing wmic output\n const drives = wmic.stdout\n .split('\\r\\n')\n .filter((line) => line.includes(':'))\n .map((line) => line.trim().replaceAll(':', ''));\n\n return drives.map((drive) => {\n const isHomeDrive = drive == homeDrive;\n return {\n name: `local_disk_${drive}`,\n root: `${drive}:\\\\`,\n initialPath: isHomeDrive ? home : `${drive}:\\\\`\n };\n });\n } catch (e: any) {\n return [\n {\n name: `local_disk_${homeDrive}`,\n root: `${homeDrive}:\\\\`,\n initialPath: home\n }\n ];\n }\n }\n}\n","import { isNotNullResourceId, PlClient, ResourceData, ResourceId } from '@milaboratories/pl-client';\nimport { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport * as sdk from '@milaboratories/pl-model-common';\nimport {\n isImportFileHandleIndex,\n LocalImportFileHandle,\n LsEntry,\n OpenDialogOps,\n OpenMultipleFilesResponse,\n OpenSingleFileResponse,\n TableRange\n} from '@milaboratories/pl-model-common';\nimport { ClientLs } from '../clients/ls_api';\nimport * as path from 'node:path';\nimport * as fsp from 'node:fs/promises';\nimport {\n createIndexImportHandle,\n createUploadImportHandle,\n parseIndexHandle,\n parseUploadHandle\n} from './helpers/ls_list_entry';\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle\n} from './helpers/ls_storage_entry';\nimport { LocalStorageProjection, VirtualLocalStorageSpec } from './types';\nimport { createLsFilesClient } from '../clients/helpers';\nimport { validateAbsolute } from '../helpers/validate';\nimport { DefaultVirtualLocalStorages } from './virtual_storages';\n\n/**\n * Extends public and safe SDK's driver API with methods used internally in the middle\n * layer and in tests.\n */\nexport interface InternalLsDriver extends sdk.LsDriver {\n /**\n * Given local path, generates well-structured and signed upload handle.\n * To be used in tests and in implementation of the native file selection UI API.\n * */\n getLocalFileHandle(localPath: string): Promise<sdk.LocalImportFileHandle>;\n}\n\nexport type OpenFileDialogCallback = (\n multipleFiles: boolean,\n ops?: OpenDialogOps\n) => Promise<undefined | string[]>;\n\nexport class LsDriver implements InternalLsDriver {\n private constructor(\n private readonly logger: MiLogger,\n private readonly lsClient: ClientLs,\n /** Pl storage id, to resource id. The resource id can be used to make LS GRPC calls to. */\n private readonly storageIdToResourceId: Record<string, ResourceId>,\n private readonly signer: Signer,\n /** Virtual storages by name */\n private readonly virtualStoragesMap: Map<string, VirtualLocalStorageSpec>,\n /** Local projections by storageId */\n private readonly localProjectionsMap: Map<string, LocalStorageProjection>,\n private readonly openFileDialogCallback: OpenFileDialogCallback\n ) {}\n\n public async getLocalFileContent(\n file: LocalImportFileHandle,\n range?: TableRange\n ): Promise<Uint8Array> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n if (range) throw new Error('Range request not yet supported.');\n return await fsp.readFile(localPath);\n }\n\n public async getLocalFileSize(file: LocalImportFileHandle): Promise<number> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n const stat = await fsp.stat(localPath);\n return stat.size;\n }\n\n public async showOpenMultipleFilesDialog(\n ops?: OpenDialogOps\n ): Promise<OpenMultipleFilesResponse> {\n const result = await this.openFileDialogCallback(true, ops);\n if (result === undefined) return {};\n return {\n files: await Promise.all(result.map((localPath) => this.getLocalFileHandle(localPath)))\n };\n }\n\n public async showOpenSingleFileDialog(ops?: OpenDialogOps): Promise<OpenSingleFileResponse> {\n const result = await this.openFileDialogCallback(false, ops);\n if (result === undefined) return {};\n return {\n file: await this.getLocalFileHandle(result[0])\n };\n }\n\n /**\n * Resolves local handle to local file path.\n *\n * @param handle handle to be resolved\n * @private\n */\n private async tryResolveLocalFileHandle(handle: LocalImportFileHandle): Promise<string> {\n if (isImportFileHandleIndex(handle)) {\n const handleData = parseIndexHandle(handle);\n const localProjection = this.localProjectionsMap.get(handleData.storageId);\n if (!localProjection)\n throw new Error(`Storage ${handleData.storageId} is not mounted locally.`);\n return path.join(localProjection.localPath, handleData.path);\n } else {\n const handleData = parseUploadHandle(handle);\n // checking it is a valid local handle from out machine\n this.signer.verify(\n handleData.localPath,\n handleData.pathSignature,\n 'Failed to validate local file handle signature.'\n );\n\n const localPath = handleData.localPath;\n\n const stat = await fsp.stat(localPath, { bigint: true });\n if (String(stat.mtimeMs / 1000n) !== handleData.modificationTime)\n throw new Error('File has changed since the handle was created.');\n\n return localPath;\n }\n }\n\n public async getLocalFileHandle(\n localPath: string\n ): Promise<sdk.ImportFileHandle & LocalImportFileHandle> {\n validateAbsolute(localPath);\n\n // Checking if local path is directly reachable by pl, because it is in one of the\n // locally mounted storages\n for (const lp of this.localProjectionsMap.values()) {\n // note: empty lp.localPath will match any address\n if (localPath.startsWith(lp.localPath)) {\n // Just in case:\n // > path.relative(\"/a/b\", \"/a/b/c\");\n // 'c'\n const pathWithinStorage =\n lp.localPath === '' ? localPath : path.relative(lp.localPath, localPath);\n return createIndexImportHandle(\n lp.storageId,\n pathWithinStorage\n ) as sdk.ImportFileHandleIndex & LocalImportFileHandle;\n }\n }\n\n // we get here if none of the local projections matched the path\n\n const stat = await fsp.stat(localPath, { bigint: true });\n return createUploadImportHandle(\n localPath,\n this.signer,\n stat.size,\n stat.mtimeMs / 1000n // integer division\n ) as sdk.ImportFileHandleUpload & LocalImportFileHandle;\n }\n\n public async getStorageList(): Promise<sdk.StorageEntry[]> {\n const virtualStorages = [...this.virtualStoragesMap.values()].map((s) => ({\n name: s.name,\n handle: createLocalStorageHandle(s.name, s.root),\n initialFullPath: s.initialPath\n }));\n\n const otherStorages = Object.entries(this.storageIdToResourceId!).map(\n ([storageId, resourceId]) => ({\n name: storageId,\n handle: createRemoteStorageHandle(storageId, resourceId),\n initialFullPath: '', // we don't have any additional information from where to start browsing remote storages\n isInitialPathHome: false\n })\n );\n\n // root must be a storage so we can index any file,\n // but for UI it's enough\n // to have local virtual storage on *nix,\n // and local_disk_${drive} on Windows.\n const noRoot = otherStorages.filter((it) => it.name !== 'root');\n\n return [...virtualStorages, ...noRoot];\n }\n\n public async listFiles(\n storageHandle: sdk.StorageHandle,\n fullPath: string\n ): Promise<sdk.ListFilesResult> {\n const storageData = parseStorageHandle(storageHandle);\n\n if (storageData.isRemote) {\n const response = await this.lsClient.list(storageData, fullPath);\n return {\n entries: response.items.map((e) => ({\n type: e.isDir ? 'dir' : 'file',\n name: e.name,\n fullPath: e.fullName,\n handle: createIndexImportHandle(storageData.name, e.fullName)\n }))\n };\n } else {\n if (path.sep === '/' && fullPath === '') fullPath = '/';\n\n if (storageData.rootPath === '') {\n validateAbsolute(fullPath);\n }\n const lsRoot = path.isAbsolute(fullPath)\n ? fullPath\n : path.join(storageData.rootPath, fullPath);\n\n const entries: LsEntry[] = [];\n for await (const dirent of await fsp.opendir(lsRoot)) {\n if (!dirent.isFile() && !dirent.isDirectory()) continue;\n\n // We cannot use no dirent.fullPath no dirent.parentPath,\n // since the former is deprecated\n // and the later works differently on different versions.\n const absolutePath = path.join(lsRoot, dirent.name);\n\n entries.push({\n type: dirent.isFile() ? 'file' : 'dir',\n name: dirent.name,\n fullPath: absolutePath,\n handle: await this.getLocalFileHandle(absolutePath)\n });\n }\n\n return { entries };\n }\n }\n\n public async fileToImportHandle(file: sdk.FileLike): Promise<sdk.ImportFileHandle> {\n throw new Error(\n 'Not implemented. This method must be implemented and intercepted in desktop preload script.'\n );\n }\n\n public static async init(\n logger: MiLogger,\n client: PlClient,\n signer: Signer,\n /** Pl storages available locally */\n localProjections: LocalStorageProjection[],\n openFileDialogCallback: OpenFileDialogCallback,\n virtualStorages?: VirtualLocalStorageSpec[]\n ): Promise<LsDriver> {\n const lsClient = createLsFilesClient(client, logger);\n\n if (!virtualStorages) virtualStorages = await DefaultVirtualLocalStorages();\n\n // validating inputs\n for (const vp of virtualStorages) validateAbsolute(vp.root);\n for (const lp of localProjections) if (lp.localPath !== '') validateAbsolute(lp.localPath);\n\n // creating indexed maps for quick access\n const virtualStoragesMap = new Map(virtualStorages.map((s) => [s.name, s]));\n const localProjectionsMap = new Map(localProjections.map((s) => [s.storageId, s]));\n\n // validating there is no intersection\n if (\n new Set([...virtualStoragesMap.keys(), ...localProjectionsMap.keys()]).size !==\n virtualStoragesMap.size + localProjectionsMap.size\n )\n throw new Error(\n 'Intersection between local projection storage ids and virtual storages names detected.'\n );\n\n return new LsDriver(\n logger,\n lsClient,\n await doGetAvailableStorageIds(client),\n signer,\n virtualStoragesMap,\n localProjectionsMap,\n openFileDialogCallback\n );\n }\n}\n\nasync function doGetAvailableStorageIds(client: PlClient): Promise<Record<string, ResourceId>> {\n return client.withReadTx('GetAvailableStorageIds', async (tx) => {\n const lsProviderId = await tx.getResourceByName('LSProvider');\n const provider = await tx.getResourceData(lsProviderId, true);\n\n return providerToStorageIds(provider);\n });\n}\n\nfunction providerToStorageIds(provider: ResourceData) {\n return Object.fromEntries(\n provider.fields\n .filter((f) => f.type == 'Dynamic' && isNotNullResourceId(f.value))\n .map((f) => [f.name.substring('storage/'.length), f.value as ResourceId])\n );\n}\n"],"names":["uploadapi$Type","MessageType","value","message","reflectionMergePartial","reader","length","options","target","writer","u","UnknownFieldHandler","uploadapi_Init$Type","uploadapi_Init_Request$Type","end","fieldNo","wireType","d","WireType","uploadapi_Init_Request","uploadapi_Init_Response$Type","e","i","uploadapi_Init_Response","uploadapi_UpdateProgress$Type","uploadapi_UpdateProgress_Request$Type","uploadapi_UpdateProgress_Request","uploadapi_UpdateProgress_Response$Type","uploadapi_UpdateProgress_Response","uploadapi_GetPartURL$Type","uploadapi_GetPartURL_Request$Type","uploadapi_GetPartURL_Request","uploadapi_GetPartURL_HTTPHeader$Type","uploadapi_GetPartURL_HTTPHeader","uploadapi_GetPartURL_Response$Type","uploadapi_GetPartURL_Response","uploadapi_Finalize$Type","uploadapi_Finalize_Request$Type","uploadapi_Finalize_Request","uploadapi_Finalize_Response$Type","uploadapi_Finalize_Response","Upload","ServiceType","UploadClient","_transport","__publicField","input","method","opt","stackIntercept","MTimeError","UnexpectedEOF","NetworkError","NoFileForUploading","ClientUpload","grpcTransport","httpClient","_","logger","id","type","init","addRTypeToMetadata","path","partNumber","partsOverall","expectedMTimeUnix","info","chunk","mTime","resp","request","body","chunkStart","chunkEnd","f","fs","len","pos","b","bytesRead","stat","position","bytesReadTotal","toUpload","uploaded","headers","name","Duration$Type","s","PbLong","text","nanosStr","json","typeofJsonValue","match","sign","secs","nanos","longSeconds","Duration","ProgressAPI$Type","ProgressAPI_Report$Type","ProgressAPI_Report","ProgressAPI_GetStatus$Type","ProgressAPI_GetStatus_Request$Type","ProgressAPI_GetStatus_Request","ProgressAPI_GetStatus_Response$Type","ProgressAPI_GetStatus_Response","ProgressAPI_RealtimeStatus$Type","ProgressAPI_RealtimeStatus_Request$Type","ProgressAPI_RealtimeStatus_Request","ProgressAPI_RealtimeStatus_Response$Type","ProgressAPI_RealtimeStatus_Response","Progress","ProgressClient","ClientProgress","client","status","report","notEmpty","updateIntervalMs","updateInterval","responses","DownloadAPI$Type","DownloadAPI_GetDownloadURL$Type","DownloadAPI_GetDownloadURL_Request$Type","DownloadAPI_GetDownloadURL_Request","DownloadAPI_GetDownloadURL_HTTPHeader$Type","DownloadAPI_GetDownloadURL_HTTPHeader","DownloadAPI_GetDownloadURL_Response$Type","DownloadAPI_GetDownloadURL_Response","Download","DownloadClient","NetworkError400","DownloadHelper","url","reqHeaders","signal","statusCode","webBody","Readable","textBody","beginning","validateAbsolute","p","storageProtocol","UnknownStorageError","WrongLocalFileUrl","ClientDownload","localProjections","lp","withAbort","downloadUrl","headersFromProto","fullPath","parseLocalFileUrl","size","fsp","localStorageIdsToRoot","parsed","storageId","storageRoot","localPath","Timestamp$Type","msg","ms","date","z","matches","Timestamp","LsAPI$Type","LsAPI_ListItem$Type","LsAPI_ListItem","LsAPI_List$Type","LsAPI_List_Request$Type","LsAPI_List_Request","LsAPI_List_Response$Type","LsAPI_List_Response","LS","LSClient","ClientLs","rInfo","StreamingAPI$Type","StreamingAPI_StreamBinary$Type","StreamingAPI_StreamBinary","StreamingAPI_ReadBinary$Type","StreamingAPI_ReadBinary","StreamingAPI_StreamText$Type","StreamingAPI_StreamText","StreamingAPI_ReadText$Type","StreamingAPI_ReadText","StreamingAPI_LastLines$Type","StreamingAPI_LastLines","StreamingAPI_Response$Type","StreamingAPI_Response","Streaming","StreamingClient","ClientLogs","rId","rType","lineCount","offsetBytes","searchStr","createDownloadClient","httpDispatcher","createLogsClient","createUploadProgressClient","createUploadBlobClient","createLsFilesClient","_client","_httpDispatcher","LongUpdater","onUpdate","sleepMs","Updater","scheduler","getStream","streamManagerId","tx","sm","stream","valErr","getField","isNullResourceId","mixcrProgressPrefix","mixcrProgressRegex","lineToProgress","line","stage","progress","eta","mixcrProgressFromLogs","lastLines","FilesCache","softSizeBytes","callerId","file","mapGet","result","freedBytes","mapEntries","created","LogsDriver","logsStreamDriver","downloadDriver","res","lines","ctx","Computable","streamManagerGetStream","isBlob","patternToSearch","handle","isLiveLogHandle","manager","_a","handleToData","liveHandleRegex","isReadyLogHandle","readyHandleRegex","resourceType","resourceVersion","resourceId","bigintToResourceId","dataToHandle","live","OnDemandBlobResourceSnapshot","rsSchema","DownloadDriver","clientDownload","clientLogs","saveDir","signer","ops","TaskProcessor","treeEntryToResourceInfo","randomUUID","isPlTreeEntry","makeResourceSnapshot","localHandleToPath","isLocalBlobHandle","read","isRemoteBlobHandle","remoteHandleToData","content","buffer","w","task","newTask","fPath","dataToLocalHandle","blob","OnDemandBlobHolder","dataToRemoteHandle","logGetter","newLogGetter","LastLinesGetter","r","blobId","toDelete","reason","ChangeSource","CallersCounter","helper.Updater","newLogs","getLastLines","fileOrDirExists","nLines","inStream","outStream","Writable","resolve","reject","rl","readline","Denque","os","Download$1","fileToWrite","DownloadAborted","sizeBytes","localHandleRegex","signature","remoteHandleRegex","ImportFileHandleUploadData","ImportFileHandleIndexData","ImportFileHandleData","UploadResourceSnapshot","IndexResourceSnapshot","makeBlobImportSnapshot","entryOrAccessor","node","isPlTreeEntryAccessor","UploadDriver","clientBlob","clientProgress","opts","PollingComputableHooks","handleResource","isProgressStable","blobExists","newValue","ProgressUpdater","nonRecoverableError","toNotify","asyncPool","n","nConcurrentPartsUpload","isUpload","isUploadSignMatch","isSignMatch","isResourceWasDeletedError","parts","partUploadFn","part","done","oldStatus","protoToStatus","stringifyWithResourceId","proto","LogsStreamDriver","LogGetter","resourceIdToString","logs","getter","DownloadUrlDriver","c","key","rmRFDir","sha256","createHash","withGunzip","URLAborted","fileExists","dirSize","gunzip","Transform","zlib","untar","tar","dir","files","sum","createIndexImportHandle","storageName","createUploadImportHandle","modificationTimeSeconds","data","parseUploadHandle","parseIndexHandle","parseStorageHandle","isRemoteStorageHandle","parseRemoteStorageHandle","isLocalStorageHandle","parseLocalStorageHandle","assertNever","createLocalStorageHandle","createRemoteStorageHandle","storageType","DefaultVirtualLocalStorages","home","homeDrive","util","exec","drive","isHomeDrive","LsDriver","lsClient","storageIdToResourceId","virtualStoragesMap","localProjectionsMap","openFileDialogCallback","range","isImportFileHandleIndex","handleData","localProjection","pathWithinStorage","virtualStorages","noRoot","it","storageHandle","storageData","lsRoot","entries","dirent","absolutePath","vp","doGetAvailableStorageIds","lsProviderId","provider","providerToStorageIds","isNotNullResourceId"],"mappings":"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"}