@milaboratories/pl-drivers 1.8.3 → 1.9.0

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/helpers/download.ts","../src/helpers/validate.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/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/constructors.ts","../src/drivers/helpers/read_file.ts","../src/drivers/helpers/download_local_handle.ts","../src/drivers/types.ts","../src/drivers/helpers/download_remote_handle.ts","../src/drivers/helpers/helpers.ts","../src/drivers/helpers/logs_handle.ts","../src/drivers/download_blob/blob_key.ts","../src/drivers/download_blob/download_blob_task.ts","../src/drivers/helpers/files_cache.ts","../src/drivers/download_blob/sparse_cache/ranges.ts","../src/drivers/download_blob/sparse_cache/file.ts","../src/drivers/download_blob/sparse_cache/cache.ts","../src/drivers/download_blob/download_blob.ts","../src/drivers/download_blob_url/snapshot.ts","../src/drivers/urls/url.ts","../src/drivers/download_blob_url/task.ts","../src/drivers/download_blob_url/driver_id.ts","../src/drivers/download_blob_url/driver.ts","../src/drivers/upload_task.ts","../src/drivers/upload.ts","../src/drivers/logs_stream.ts","../src/drivers/logs.ts","../src/drivers/download_url/task.ts","../src/drivers/download_url/driver.ts","../src/drivers/helpers/ls_remote_import_handle.ts","../src/drivers/helpers/ls_storage_entry.ts","../src/drivers/virtual_storages.ts","../src/drivers/ls.ts"],"sourcesContent":["// @generated by protobuf-ts 2.11.0 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 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 { MessageType } from \"@protobuf-ts/runtime\";\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi\n */\nexport interface uploadapi {\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init\n */\nexport interface uploadapi_Init {\n}\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/**\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/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL\n */\nexport interface uploadapi_GetPartURL {\n}\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 * Do we need to presign URL for internal use.\n * Controllers could use this if they are trying to download something from internal network.\n * For backward compatibility, by default pl backend will presign external urls.\n *\n * @generated from protobuf field: bool is_internal_use = 4\n */\n isInternalUse: boolean;\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\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2\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/**\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}\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi): uploadapi {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Init): uploadapi_Init {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Init, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_Init_Request>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Init_Request): uploadapi_Init_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Init_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"parts_count\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"uploaded_parts\", kind: \"scalar\", repeat: 1 /*RepeatType.PACKED*/, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_Init_Response>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Init_Response): uploadapi_Init_Response {\n let message = target ?? this.create(), 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\n message.uploadedParts.push(reader.uint64().toBigInt());\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Init_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(value?: PartialMessage<uploadapi_UpdateProgress>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_UpdateProgress): uploadapi_UpdateProgress {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_UpdateProgress, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"bytes_processed\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_UpdateProgress_Request>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_UpdateProgress_Request): uploadapi_UpdateProgress_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_UpdateProgress_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request\n */\nexport const uploadapi_UpdateProgress_Request = 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(\"MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\", []);\n }\n create(value?: PartialMessage<uploadapi_UpdateProgress_Response>): uploadapi_UpdateProgress_Response {\n const message = globalThis.Object.create((this.messagePrototype!));\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_UpdateProgress_Response): uploadapi_UpdateProgress_Response {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_UpdateProgress_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\n */\nexport const uploadapi_UpdateProgress_Response = 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL): uploadapi_GetPartURL {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"part_number\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"uploaded_part_size\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 4, name: \"is_internal_use\", kind: \"scalar\", T: 8 /*ScalarType.BOOL*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL_Request>): uploadapi_GetPartURL_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n message.partNumber = 0n;\n message.uploadedPartSize = 0n;\n message.isInternalUse = false;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL_Request): uploadapi_GetPartURL_Request {\n let message = target ?? this.create(), 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 case /* bool is_internal_use */ 4:\n message.isInternalUse = reader.bool();\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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 /* bool is_internal_use = 4; */\n if (message.isInternalUse !== false)\n writer.tag(4, WireType.Varint).bool(message.isInternalUse);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request\n */\nexport const uploadapi_GetPartURL_Request = 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 { no: 1, name: \"Name\", kind: \"scalar\", jsonName: \"Name\", T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: \"Value\", kind: \"scalar\", jsonName: \"Value\", T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL_HTTPHeader>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL_HTTPHeader): uploadapi_GetPartURL_HTTPHeader {\n let message = target ?? this.create(), 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 /* string 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL_HTTPHeader, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* string Name = 1; */\n if (message.name !== \"\")\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2; */\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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader\n */\nexport const uploadapi_GetPartURL_HTTPHeader = 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 { no: 3, name: \"headers\", kind: \"message\", repeat: 2 /*RepeatType.UNPACKED*/, T: () => uploadapi_GetPartURL_HTTPHeader },\n { no: 4, name: \"chunk_start\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 5, name: \"chunk_end\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL_Response>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL_Response): uploadapi_GetPartURL_Response {\n let message = target ?? this.create(), 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(uploadapi_GetPartURL_HTTPHeader.internalBinaryRead(reader, reader.uint32(), options));\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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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.internalBinaryWrite(message.headers[i], writer.tag(3, WireType.LengthDelimited).fork(), options).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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response\n */\nexport const uploadapi_GetPartURL_Response = 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Finalize): uploadapi_Finalize {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Finalize, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_Finalize_Request>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Finalize_Request): uploadapi_Finalize_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Finalize_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(value?: PartialMessage<uploadapi_Finalize_Response>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Finalize_Response): uploadapi_Finalize_Response {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Finalize_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Response\n */\nexport const uploadapi_Finalize_Response = new uploadapi_Finalize_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport const Upload = new ServiceType(\"MiLaboratories.Controller.Shared.Upload\", [\n { name: \"Init\", options: {}, I: uploadapi_Init_Request, O: uploadapi_Init_Response },\n { name: \"GetPartURL\", options: {}, I: uploadapi_GetPartURL_Request, O: uploadapi_GetPartURL_Response },\n { name: \"UpdateProgress\", options: {}, I: uploadapi_UpdateProgress_Request, O: uploadapi_UpdateProgress_Response },\n { name: \"Finalize\", options: {}, I: uploadapi_Finalize_Request, O: uploadapi_Finalize_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n init(input: uploadapi_Init_Request, options?: RpcOptions): 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\n */\n getPartURL(input: uploadapi_GetPartURL_Request, options?: RpcOptions): 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\n */\n updateProgress(input: uploadapi_UpdateProgress_Request, options?: RpcOptions): UnaryCall<uploadapi_UpdateProgress_Request, uploadapi_UpdateProgress_Response>;\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\n */\n finalize(input: uploadapi_Finalize_Request, options?: RpcOptions): 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 *\n * Init upload, making controller to do all required preparation steps.\n *\n *\n * @generated from protobuf rpc: Init\n */\n init(input: uploadapi_Init_Request, options?: RpcOptions): UnaryCall<uploadapi_Init_Request, uploadapi_Init_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_Init_Request, uploadapi_Init_Response>(\"unary\", this._transport, method, opt, input);\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\n */\n getPartURL(input: uploadapi_GetPartURL_Request, options?: RpcOptions): UnaryCall<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response> {\n const method = this.methods[1], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response>(\"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\n */\n updateProgress(input: uploadapi_UpdateProgress_Request, options?: RpcOptions): UnaryCall<uploadapi_UpdateProgress_Request, uploadapi_UpdateProgress_Response> {\n const method = this.methods[2], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_UpdateProgress_Request, uploadapi_UpdateProgress_Response>(\"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\n */\n finalize(input: uploadapi_Finalize_Request, options?: RpcOptions): UnaryCall<uploadapi_Finalize_Request, uploadapi_Finalize_Response> {\n const method = this.methods[3], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_Finalize_Request, uploadapi_Finalize_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","import type { GrpcClientProvider, GrpcClientProviderFactory, PlClient, ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport * as fs from 'node:fs/promises';\nimport type { Dispatcher } from 'undici';\nimport { request } from 'undici';\nimport type { uploadapi_GetPartURL_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol';\nimport { UploadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client';\n\nimport type { IncomingHttpHeaders } from 'undici/types/header';\n\nexport class MTimeError extends Error {\n name = 'MTimeError';\n}\n\nexport class UnexpectedEOF extends Error {\n name = 'UnexpectedEOF';\n}\n\nexport class NetworkError extends Error {\n name = 'NetworkError';\n}\n\n/** Happens when the file doesn't exist */\nexport class NoFileForUploading extends Error {\n name = 'NoFileForUploading';\n}\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: GrpcClientProvider<UploadClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n public readonly httpClient: Dispatcher,\n _: PlClient,\n public readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new UploadClient(transport));\n }\n\n close() {}\n\n public async initUpload(\n { id, type }: ResourceInfo,\n options?: RpcOptions,\n ): Promise<{\n overall: bigint;\n toUpload: bigint[];\n }> {\n const init = await this.grpcInit(id, type, options);\n return {\n overall: init.partsCount,\n toUpload: this.partsToUpload(init.partsCount, init.uploadedParts),\n };\n }\n\n public async partUpload(\n { id, type }: ResourceInfo,\n path: string,\n expectedMTimeUnix: bigint,\n partNumber: bigint,\n options?: RpcOptions,\n ) {\n const info = await this.grpcGetPartUrl(\n { id, type },\n partNumber,\n 0n, // we update progress as a separate call later.\n options,\n );\n\n const chunk = await readFileChunk(path, info.chunkStart, info.chunkEnd);\n await checkExpectedMTime(path, expectedMTimeUnix);\n\n try {\n const {\n body: rawBody,\n statusCode,\n headers,\n } = await request(info.uploadUrl, {\n dispatcher: this.httpClient,\n body: chunk,\n // We got headers only after we send\n // the whole body (in case of S3 PUT requests it's 5 MB).\n // It might be slow with a slow connection (or with SSH),\n // that's why we got big timeout here.\n headersTimeout: 60000,\n bodyTimeout: 60000,\n headers: Object.fromEntries(info.headers.map(({ name, value }) => [name, value])),\n method: info.method.toUpperCase() as Dispatcher.HttpMethod,\n });\n\n // always read the body for resources to be garbage collected.\n const body = await rawBody.text();\n checkStatusCodeOk(statusCode, body, headers, info);\n } catch (e: unknown) {\n if (e instanceof NetworkError)\n throw e;\n\n throw new Error(`partUpload: error ${JSON.stringify(e)} happened while trying to do part upload to the url ${info.uploadUrl}, headers: ${JSON.stringify(info.headers)}`);\n }\n\n await this.grpcUpdateProgress({ id, type }, BigInt(info.chunkEnd - info.chunkStart), options);\n }\n\n public async finalize(info: ResourceInfo, options?: RpcOptions) {\n return await this.grpcFinalize(info, options);\n }\n\n /** Calculates parts that need to be uploaded from the parts that were\n * already uploaded. */\n private partsToUpload(partsCount: bigint, uploadedParts: bigint[]): bigint[] {\n const toUpload: bigint[] = [];\n const uploaded = new Set(uploadedParts);\n\n for (let i = 1n; i <= partsCount; i++) {\n if (!uploaded.has(i)) toUpload.push(i);\n }\n\n return toUpload;\n }\n\n private async grpcInit(id: ResourceId, type: ResourceType, options?: RpcOptions) {\n return await this.grpcClient.get().init({ resourceId: id }, addRTypeToMetadata(type, options))\n .response;\n }\n\n private async grpcGetPartUrl(\n { id, type }: ResourceInfo,\n partNumber: bigint,\n uploadedPartSize: bigint,\n options?: RpcOptions,\n ) {\n return await this.grpcClient.get().getPartURL(\n { resourceId: id, partNumber, uploadedPartSize, isInternalUse: false },\n addRTypeToMetadata(type, options),\n ).response;\n }\n\n private async grpcUpdateProgress(\n { id, type }: ResourceInfo,\n bytesProcessed: bigint,\n options?: RpcOptions,\n ) {\n await this.grpcClient.get().updateProgress(\n {\n resourceId: id,\n bytesProcessed,\n },\n addRTypeToMetadata(type, options),\n ).response;\n }\n\n private async grpcFinalize({ id, type }: ResourceInfo, options?: RpcOptions) {\n return await this.grpcClient.get().finalize({ resourceId: id }, addRTypeToMetadata(type, options))\n .response;\n }\n}\n\nasync function readFileChunk(path: string, chunkStart: bigint, chunkEnd: bigint): Promise<Buffer> {\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 readBytesFromPosition(f, b, len, pos);\n\n return b.subarray(0, bytesRead);\n } catch (e: unknown) {\n if (e && typeof e === 'object' && ('code' in e) && e.code == 'ENOENT') throw new NoFileForUploading(`there is no file ${path} for uploading`);\n throw e;\n } finally {\n await f?.close();\n }\n}\n\n/** Read len bytes from a given position.\n * Without this, `FileHandle.read` can read less bytes than needed. */\nasync function 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\nasync function checkExpectedMTime(path: string, expectedMTimeUnix: bigint) {\n const mTime = BigInt(Math.floor((await fs.stat(path)).mtimeMs / 1000));\n if (mTime > expectedMTimeUnix) {\n throw new MTimeError(`file was modified, expected mtime: ${expectedMTimeUnix}, got: ${mTime}.`);\n }\n}\n\nfunction checkStatusCodeOk(\n statusCode: number,\n body: string,\n headers: IncomingHttpHeaders,\n info: uploadapi_GetPartURL_Response,\n) {\n if (statusCode != 200) {\n throw new NetworkError(\n `response is not ok, status code: ${statusCode},`\n + ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`,\n );\n }\n}\n","// @generated by protobuf-ts 2.11.0 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 * @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 { no: 1, name: \"seconds\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\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)\n 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(json: JsonValue, options: JsonReadOptions, target?: Duration): Duration {\n if (typeof json !== \"string\")\n throw new Error(\"Unable to parse Duration from JSON \" + typeofJsonValue(json) + \". Expected string.\");\n let match = json.match(/^(-?)([0-9]+)(?:\\.([0-9]+))?s/);\n if (match === null)\n throw new Error(\"Unable to parse Duration from JSON string. Invalid format.\");\n if (!target)\n target = this.create();\n let [, sign, secs, nanos] = match;\n let longSeconds = PbLong.from(sign + secs);\n if (longSeconds.toNumber() > 315576000000 || longSeconds.toNumber() < -315576000000)\n throw new Error(\"Unable to parse Duration from JSON string. Value out of range.\");\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Duration): Duration {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: Duration, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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.11.0 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 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 { 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/**\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/**\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/**\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI): ProgressAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 2, name: \"bytes_processed\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"bytes_total\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_Report): ProgressAPI_Report {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_Report, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_GetStatus): ProgressAPI_GetStatus {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_GetStatus, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_GetStatus_Request>): ProgressAPI_GetStatus_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_GetStatus_Request): ProgressAPI_GetStatus_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_GetStatus_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request\n */\nexport const ProgressAPI_GetStatus_Request = 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(value?: PartialMessage<ProgressAPI_GetStatus_Response>): ProgressAPI_GetStatus_Response {\n const message = globalThis.Object.create((this.messagePrototype!));\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_GetStatus_Response): ProgressAPI_GetStatus_Response {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.report);\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_GetStatus_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(message.report, writer.tag(1, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response\n */\nexport const ProgressAPI_GetStatus_Response = 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(value?: PartialMessage<ProgressAPI_RealtimeStatus>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_RealtimeStatus): ProgressAPI_RealtimeStatus {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_RealtimeStatus, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(\"MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\", [\n { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"update_interval\", kind: \"message\", T: () => Duration }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_RealtimeStatus_Request>): ProgressAPI_RealtimeStatus_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_RealtimeStatus_Request): ProgressAPI_RealtimeStatus_Request {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.updateInterval);\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_RealtimeStatus_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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(message.updateInterval, writer.tag(2, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\n */\nexport const ProgressAPI_RealtimeStatus_Request = 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(\"MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\", [\n { no: 1, name: \"report\", kind: \"message\", T: () => ProgressAPI_Report }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_RealtimeStatus_Response>): ProgressAPI_RealtimeStatus_Response {\n const message = globalThis.Object.create((this.messagePrototype!));\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_RealtimeStatus_Response): ProgressAPI_RealtimeStatus_Response {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.report);\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_RealtimeStatus_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(message.report, writer.tag(1, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\n */\nexport const ProgressAPI_RealtimeStatus_Response = new ProgressAPI_RealtimeStatus_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport const Progress = new ServiceType(\"MiLaboratories.Controller.Shared.Progress\", [\n { name: \"GetStatus\", options: { \"google.api.http\": { get: \"/resources/{resource_id}/get-progress\" } }, I: ProgressAPI_GetStatus_Request, O: ProgressAPI_GetStatus_Response },\n { name: \"RealtimeStatus\", serverStreaming: true, options: {}, I: ProgressAPI_RealtimeStatus_Request, O: ProgressAPI_RealtimeStatus_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n getStatus(input: ProgressAPI_GetStatus_Request, options?: RpcOptions): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response>;\n /**\n * @generated from protobuf rpc: RealtimeStatus\n */\n realtimeStatus(input: ProgressAPI_RealtimeStatus_Request, options?: RpcOptions): ServerStreamingCall<ProgressAPI_RealtimeStatus_Request, ProgressAPI_RealtimeStatus_Response>;\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 /**\n * @generated from protobuf rpc: GetStatus\n */\n getStatus(input: ProgressAPI_GetStatus_Request, options?: RpcOptions): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response>(\"unary\", this._transport, method, opt, input);\n }\n /**\n * @generated from protobuf rpc: RealtimeStatus\n */\n realtimeStatus(input: ProgressAPI_RealtimeStatus_Request, options?: RpcOptions): ServerStreamingCall<ProgressAPI_RealtimeStatus_Request, ProgressAPI_RealtimeStatus_Response> {\n const method = this.methods[1], opt = this._transport.mergeOptions(options);\n return stackIntercept<ProgressAPI_RealtimeStatus_Request, ProgressAPI_RealtimeStatus_Response>(\"serverStreaming\", this._transport, method, opt, input);\n }\n}\n","import { ProgressClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { Duration } from '../proto/google/protobuf/duration';\nimport type { GrpcClientProvider, GrpcClientProviderFactory, PlClient } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport type { Dispatcher } from 'undici';\nimport type { 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: GrpcClientProvider<ProgressClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n _: Dispatcher,\n public readonly client: PlClient,\n public readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new ProgressClient(transport));\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.get().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.get().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' + String(e));\n throw e;\n }\n }\n}\n","// @TODO Gleb Zakharov\n/* eslint-disable n/no-unsupported-features/node-builtins */\nimport type { Dispatcher } from 'undici';\nimport { request } from 'undici';\nimport { Readable } from 'node:stream';\nimport type { ReadableStream } from 'node:stream/web';\nimport { text } from 'node:stream/consumers';\nimport type { RangeBytes } from '@milaboratories/pl-model-common';\n\nexport interface DownloadOps {\n signal?: AbortSignal;\n range?: RangeBytes;\n}\n\nexport type ContentHandler<T> = (content: ReadableStream, size: number) => Promise<T>;\n\n/** Throws when a status code of the downloading URL was in range [400, 500). */\nexport class NetworkError400 extends Error {\n name = 'NetworkError400';\n}\n\nexport class RemoteFileDownloader {\n constructor(public readonly httpClient: Dispatcher) {}\n\n async withContent<T>(\n url: string,\n reqHeaders: Record<string, string>,\n ops: DownloadOps,\n handler: ContentHandler<T>,\n ): Promise<T> {\n const headers = { ...reqHeaders };\n\n // Add range header if specified\n if (ops.range) {\n headers['Range'] = `bytes=${ops.range.from}-${ops.range.to - 1}`;\n }\n\n const { statusCode, body, headers: responseHeaders } = await request(url, {\n dispatcher: this.httpClient,\n headers,\n signal: ops.signal,\n });\n\n const webBody = Readable.toWeb(body);\n let handlerSuccess = false;\n\n try {\n await checkStatusCodeOk(statusCode, webBody, url);\n const size = Number(responseHeaders['content-length']);\n const result = await handler(webBody, size);\n handlerSuccess = true;\n return result;\n } catch (error) {\n // Cleanup on error (including handler errors)\n if (!handlerSuccess && !webBody.locked) {\n try {\n await webBody.cancel();\n } catch {\n // Ignore cleanup errors\n }\n }\n throw error;\n }\n }\n}\n\nasync function checkStatusCodeOk(statusCode: number, webBody: ReadableStream, url: string) {\n if (statusCode != 200 && statusCode != 206 /* partial content from range request */) {\n const beginning = (await text(webBody)).substring(0, 1000);\n\n if (400 <= statusCode && statusCode < 500) {\n throw new NetworkError400(\n `Http error: statusCode: ${statusCode} `\n + `url: ${url.toString()}, beginning of body: ${beginning}`);\n }\n\n throw new Error(`Http error: statusCode: ${statusCode} url: ${url.toString()}`);\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","// @generated by protobuf-ts 2.11.0 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 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 { MessageType } from \"@protobuf-ts/runtime\";\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI\n */\nexport interface DownloadAPI {\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL\n */\nexport interface DownloadAPI_GetDownloadURL {\n}\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 * Pass `true` here if the blob will be downloaded from internal network,\n * e.g. controllers could use this if they are trying to download something from internal network.\n * For backward compatibility, by default pl treats all requests as from external network.\n *\n * @generated from protobuf field: bool is_internal_use = 2\n */\n isInternalUse: boolean;\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\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI): DownloadAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(value?: PartialMessage<DownloadAPI_GetDownloadURL>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL): DownloadAPI_GetDownloadURL {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(\"MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\", [\n { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"is_internal_use\", kind: \"scalar\", T: 8 /*ScalarType.BOOL*/ }\n ]);\n }\n create(value?: PartialMessage<DownloadAPI_GetDownloadURL_Request>): DownloadAPI_GetDownloadURL_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n message.isInternalUse = false;\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL_Request): DownloadAPI_GetDownloadURL_Request {\n let message = target ?? this.create(), 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 /* bool is_internal_use */ 2:\n message.isInternalUse = reader.bool();\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL_Request, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* bool is_internal_use = 2; */\n if (message.isInternalUse !== false)\n writer.tag(2, WireType.Varint).bool(message.isInternalUse);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\n */\nexport const DownloadAPI_GetDownloadURL_Request = 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(\"MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\", [\n { no: 1, name: \"Name\", kind: \"scalar\", jsonName: \"Name\", T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: \"Value\", kind: \"scalar\", jsonName: \"Value\", T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<DownloadAPI_GetDownloadURL_HTTPHeader>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL_HTTPHeader): DownloadAPI_GetDownloadURL_HTTPHeader {\n let message = target ?? this.create(), 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 /* string 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL_HTTPHeader, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* string Name = 1; */\n if (message.name !== \"\")\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2; */\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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\n */\nexport const DownloadAPI_GetDownloadURL_HTTPHeader = 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(\"MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\", [\n { no: 1, name: \"download_url\", kind: \"scalar\", T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: \"headers\", kind: \"message\", repeat: 2 /*RepeatType.UNPACKED*/, T: () => DownloadAPI_GetDownloadURL_HTTPHeader }\n ]);\n }\n create(value?: PartialMessage<DownloadAPI_GetDownloadURL_Response>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL_Response): DownloadAPI_GetDownloadURL_Response {\n let message = target ?? this.create(), 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(DownloadAPI_GetDownloadURL_HTTPHeader.internalBinaryRead(reader, reader.uint32(), options));\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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(message.headers[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\n */\nexport const DownloadAPI_GetDownloadURL_Response = new DownloadAPI_GetDownloadURL_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport const Download = new ServiceType(\"MiLaboratories.Controller.Shared.Download\", [\n { name: \"GetDownloadURL\", options: { \"google.api.http\": { get: \"/resources/{resource_id}/get-download-url\" } }, I: DownloadAPI_GetDownloadURL_Request, O: DownloadAPI_GetDownloadURL_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n getDownloadURL(input: DownloadAPI_GetDownloadURL_Request, options?: RpcOptions): UnaryCall<DownloadAPI_GetDownloadURL_Request, DownloadAPI_GetDownloadURL_Response>;\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 /**\n * @generated from protobuf rpc: GetDownloadURL\n */\n getDownloadURL(input: DownloadAPI_GetDownloadURL_Request, options?: RpcOptions): UnaryCall<DownloadAPI_GetDownloadURL_Request, DownloadAPI_GetDownloadURL_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<DownloadAPI_GetDownloadURL_Request, DownloadAPI_GetDownloadURL_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","/* eslint-disable n/no-unsupported-features/node-builtins */\nimport type { GrpcClientProvider, GrpcClientProviderFactory } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { ConcurrencyLimitingExecutor } from '@milaboratories/ts-helpers';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Readable } from 'node:stream';\nimport type { Dispatcher } from 'undici';\nimport type { LocalStorageProjection } from '../drivers/types';\nimport type { DownloadOps, ContentHandler } from '../helpers/download';\nimport { RemoteFileDownloader } from '../helpers/download';\nimport { validateAbsolute } from '../helpers/validate';\nimport type { DownloadAPI_GetDownloadURL_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol';\nimport { DownloadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client';\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: GrpcClientProvider<DownloadClient>;\n private readonly remoteFileDownloader: RemoteFileDownloader;\n\n /** Helps to find a storage root directory by a storage id from URL scheme. */\n private readonly localStorageIdsToRoot: Map<string, string>;\n\n /** Concurrency limiter for local file reads - limit to 32 parallel reads */\n private readonly localFileReadLimiter = new ConcurrencyLimitingExecutor(32);\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger,\n /** Pl storages available locally */\n localProjections: LocalStorageProjection[],\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new DownloadClient(transport));\n this.remoteFileDownloader = new RemoteFileDownloader(httpClient);\n this.localStorageIdsToRoot = newLocalStorageIdsToRoot(localProjections);\n }\n\n close() {}\n\n /**\n * Gets a presign URL and downloads the file.\n * An optional range with 2 numbers from what byte and to what byte to download can be provided.\n * @param fromBytes - from byte including this byte\n * @param toBytes - to byte excluding this byte\n */\n async withBlobContent<T>(\n info: ResourceInfo,\n options: RpcOptions | undefined,\n ops: DownloadOps,\n handler: ContentHandler<T>,\n ): Promise<T> {\n const { downloadUrl, headers } = await this.grpcGetDownloadUrl(info, options, ops.signal);\n\n const remoteHeaders = Object.fromEntries(headers.map(({ name, value }) => [name, value]));\n this.logger.info(`download blob ${stringifyWithResourceId(info)} from url ${downloadUrl}, ops: ${JSON.stringify(ops)}`);\n\n return isLocal(downloadUrl)\n ? await this.withLocalFileContent(downloadUrl, ops, handler)\n : await this.remoteFileDownloader.withContent(downloadUrl, remoteHeaders, ops, handler);\n }\n\n async withLocalFileContent<T>(\n url: string,\n ops: DownloadOps,\n handler: ContentHandler<T>,\n ): Promise<T> {\n const { storageId, relativePath } = parseLocalUrl(url);\n const fullPath = getFullPath(storageId, this.localStorageIdsToRoot, relativePath);\n\n return await this.localFileReadLimiter.run(async () => {\n const readOps = {\n start: ops.range?.from,\n end: ops.range?.to !== undefined ? ops.range.to - 1 : undefined,\n };\n let stream: fs.ReadStream | undefined;\n let handlerSuccess = false;\n\n try {\n const stat = await fsp.stat(fullPath);\n stream = fs.createReadStream(fullPath, readOps);\n const webStream = Readable.toWeb(stream);\n\n const result = await handler(webStream, stat.size);\n handlerSuccess = true;\n return result;\n } catch (error) {\n // Cleanup on error (including handler errors)\n if (!handlerSuccess && stream && !stream.destroyed) {\n stream.destroy();\n }\n throw error;\n }\n });\n }\n\n private async grpcGetDownloadUrl(\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.get().getDownloadURL(\n { resourceId: id, isInternalUse: false },\n addRTypeToMetadata(type, withAbort),\n ).response;\n }\n}\n\nexport function parseLocalUrl(url: 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 return {\n storageId: parsed.host,\n relativePath: decodeURIComponent(parsed.pathname.slice(1)),\n };\n}\n\nexport function getFullPath(\n storageId: string,\n localStorageIdsToRoot: Map<string, string>,\n relativePath: string,\n) {\n const root = localStorageIdsToRoot.get(storageId);\n if (root === undefined) throw new UnknownStorageError(`Unknown storage location: ${storageId}`);\n\n if (root === '') return relativePath;\n\n return path.join(root, relativePath);\n}\n\nconst storageProtocol = 'storage://';\nfunction isLocal(url: string) {\n return url.startsWith(storageProtocol);\n}\n\n/** Throws when a local URL have invalid scheme. */\nexport class WrongLocalFileUrl extends Error {\n name = 'WrongLocalFileUrl';\n}\n\n/** Happens when a storage for a local file can't be found. */\nexport class UnknownStorageError extends Error {\n name = 'UnknownStorageError';\n}\n\nexport function newLocalStorageIdsToRoot(projections: LocalStorageProjection[]) {\n const idToRoot: Map<string, string> = new Map();\n for (const lp of projections) {\n // Empty string means no prefix, i.e. any file on this machine can be got from the storage.\n if (lp.localPath !== '') {\n validateAbsolute(lp.localPath);\n }\n idToRoot.set(lp.storageId, lp.localPath);\n }\n\n return idToRoot;\n}\n","// @generated by protobuf-ts 2.11.0 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 * 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 * 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://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()\n * ) to obtain a formatter capable of generating timestamps in this format.\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 { no: 1, name: \"seconds\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\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(PbLong.from(message.seconds).toNumber() * 1000 + Math.ceil(message.nanos / 1000000));\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) + (ms < 0 && ms % 1000 !== 0 ? 1000 : 0)) * 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 (ms < Date.parse(\"0001-01-01T00:00:00Z\") || ms > Date.parse(\"9999-12-31T23:59:59Z\"))\n throw new Error(\"Unable to encode Timestamp to JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.\");\n if (message.nanos < 0)\n throw new Error(\"Unable to encode invalid Timestamp to JSON. Nanos must not be negative.\");\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\n 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(json: JsonValue, options: JsonReadOptions, target?: Timestamp): Timestamp {\n if (typeof json !== \"string\")\n throw new Error(\"Unable to parse Timestamp from JSON \" + typeofJsonValue(json) + \".\");\n let matches = json.match(/^([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 if (!matches)\n throw new Error(\"Unable to parse Timestamp from JSON. Invalid format.\");\n let ms = Date.parse(matches[1] + \"-\" + matches[2] + \"-\" + matches[3] + \"T\" + matches[4] + \":\" + matches[5] + \":\" + matches[6] + (matches[8] ? matches[8] : \"Z\"));\n if (Number.isNaN(ms))\n throw new Error(\"Unable to parse Timestamp from JSON. Invalid value.\");\n if (ms < Date.parse(\"0001-01-01T00:00:00Z\") || ms > Date.parse(\"9999-12-31T23:59:59Z\"))\n throw new globalThis.Error(\"Unable to parse Timestamp from JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.\");\n if (!target)\n target = this.create();\n target.seconds = PbLong.from(ms / 1000).toBigInt();\n target.nanos = 0;\n if (matches[7])\n target.nanos = (parseInt(\"1\" + matches[7] + \"0\".repeat(9 - matches[7].length)) - 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Timestamp): Timestamp {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: Timestamp, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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.11.0 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 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 { 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/**\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/**\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI): LsAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 2, name: \"size\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_ListItem): LsAPI_ListItem {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.lastModified);\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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_ListItem, writer: IBinaryWriter, options: BinaryWriteOptions): 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(message.lastModified, writer.tag(12, WireType.LengthDelimited).fork(), options).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)(this.typeName, message, writer);\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_List): LsAPI_List {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_List, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_List_Request): LsAPI_List_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_List_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"items\", kind: \"message\", repeat: 2 /*RepeatType.UNPACKED*/, T: () => LsAPI_ListItem },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_List_Response): LsAPI_List_Response {\n let message = target ?? this.create(), 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(LsAPI_ListItem.internalBinaryRead(reader, reader.uint32(), options));\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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_List_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items = 1; */\n for (let i = 0; i < message.items.length; i++)\n LsAPI_ListItem.internalBinaryWrite(message.items[i], writer.tag(1, WireType.LengthDelimited).fork(), options).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)(this.typeName, message, writer);\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.11.0 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\n */\n list(input: LsAPI_List_Request, options?: RpcOptions): 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 /**\n * @generated from protobuf rpc: List\n */\n list(input: LsAPI_List_Request, options?: RpcOptions): UnaryCall<LsAPI_List_Request, LsAPI_List_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<LsAPI_List_Request, LsAPI_List_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","import type { 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 type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport type { GrpcClientProvider, GrpcClientProviderFactory } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLs {\n private readonly grpcClient: GrpcClientProvider<LSClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n private readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new LSClient(transport));\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.get().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.11.0 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 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 { MessageType } from \"@protobuf-ts/runtime\";\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI\n */\nexport interface StreamingAPI {\n}\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI): StreamingAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 11, name: \"chunk_size\", kind: \"scalar\", opt: true, T: 13 /*ScalarType.UINT32*/ },\n { no: 20, name: \"read_limit\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_StreamBinary>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_StreamBinary): StreamingAPI_StreamBinary {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_StreamBinary, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 11, name: \"chunk_size\", kind: \"scalar\", opt: true, T: 13 /*ScalarType.UINT32*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_ReadBinary>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_ReadBinary): StreamingAPI_ReadBinary {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_ReadBinary, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 20, name: \"read_limit\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 21, name: \"search\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ },\n { no: 22, name: \"search_re\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_StreamText>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_StreamText): StreamingAPI_StreamText {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_StreamText, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 20, name: \"read_limit\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 21, name: \"search\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ },\n { no: 22, name: \"search_re\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ }\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_ReadText): StreamingAPI_ReadText {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_ReadText, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"line_count\", kind: \"scalar\", opt: true, T: 5 /*ScalarType.INT32*/ },\n { no: 21, name: \"search\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ },\n { no: 22, name: \"search_re\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_LastLines>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_LastLines): StreamingAPI_LastLines {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_LastLines, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 2, name: \"size\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"new_offset\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_Response): StreamingAPI_Response {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(\"MiLaboratories.Controller.Shared.Streaming\", [\n { name: \"StreamBinary\", serverStreaming: true, options: {}, I: StreamingAPI_StreamBinary, O: StreamingAPI_Response },\n { name: \"ReadBinary\", options: {}, I: StreamingAPI_ReadBinary, O: StreamingAPI_Response },\n { name: \"StreamText\", serverStreaming: true, options: {}, I: StreamingAPI_StreamText, O: StreamingAPI_Response },\n { name: \"ReadText\", options: {}, I: StreamingAPI_ReadText, O: StreamingAPI_Response },\n { name: \"LastLines\", options: {}, I: StreamingAPI_LastLines, O: StreamingAPI_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n streamBinary(input: StreamingAPI_StreamBinary, options?: RpcOptions): 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\n */\n readBinary(input: StreamingAPI_ReadBinary, options?: RpcOptions): 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\n */\n streamText(input: StreamingAPI_StreamText, options?: RpcOptions): 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\n */\n readText(input: StreamingAPI_ReadText, options?: RpcOptions): 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\n */\n lastLines(input: StreamingAPI_LastLines, options?: RpcOptions): 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 /**\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\n */\n streamBinary(input: StreamingAPI_StreamBinary, options?: RpcOptions): ServerStreamingCall<StreamingAPI_StreamBinary, StreamingAPI_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamBinary, StreamingAPI_Response>(\"serverStreaming\", this._transport, method, opt, input);\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\n */\n readBinary(input: StreamingAPI_ReadBinary, options?: RpcOptions): UnaryCall<StreamingAPI_ReadBinary, StreamingAPI_Response> {\n const method = this.methods[1], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadBinary, StreamingAPI_Response>(\"unary\", this._transport, method, opt, input);\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\n */\n streamText(input: StreamingAPI_StreamText, options?: RpcOptions): ServerStreamingCall<StreamingAPI_StreamText, StreamingAPI_Response> {\n const method = this.methods[2], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamText, StreamingAPI_Response>(\"serverStreaming\", this._transport, method, opt, input);\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\n */\n readText(input: StreamingAPI_ReadText, options?: RpcOptions): UnaryCall<StreamingAPI_ReadText, StreamingAPI_Response> {\n const method = this.methods[3], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadText, StreamingAPI_Response>(\"unary\", this._transport, method, opt, input);\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\n */\n lastLines(input: StreamingAPI_LastLines, options?: RpcOptions): UnaryCall<StreamingAPI_LastLines, StreamingAPI_Response> {\n const method = this.methods[4], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_LastLines, StreamingAPI_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","import { StreamingClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport type { Dispatcher } from 'undici';\nimport type { GrpcClientProvider, GrpcClientProviderFactory } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLogs {\n public readonly grpcClient: GrpcClientProvider<StreamingClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new StreamingClient(transport));\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.get().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.get().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 type { GrpcClientProviderFactory, PlClient } from '@milaboratories/pl-client';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport type { 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 type { 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, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientDownload(grpcClientProviderFactory, httpDispatcher, logger, localProjections),\n });\n}\n\nexport function createLogsClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'StreamLogs',\n init: (_: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientLogs(grpcClientProviderFactory, httpDispatcher, logger),\n });\n}\n\nexport function createUploadProgressClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadProgress',\n init: (_: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientProgress(grpcClientProviderFactory, httpDispatcher, client, logger),\n });\n}\n\nexport function createUploadBlobClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadBlob',\n init: (_: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientUpload(grpcClientProviderFactory, httpDispatcher, client, logger),\n });\n}\n\nexport function createLsFilesClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'LsFiles',\n init: (_client: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, _httpDispatcher: Dispatcher) =>\n new ClientLs(grpcClientProviderFactory, logger),\n });\n}\n","import { ConcurrencyLimitingExecutor } from '@milaboratories/ts-helpers';\nimport type { RangeBytes } from '@milaboratories/pl-model-common';\nimport * as fs from 'node:fs';\nimport { buffer } from 'node:stream/consumers';\n\n// Global concurrency limiter for file reads - limit to 32 parallel reads\nconst fileReadLimiter = new ConcurrencyLimitingExecutor(32);\n\n/**\n * Reads file content with concurrency limiting and proper error handling.\n * Ensures file descriptors are properly cleaned up even in error cases.\n */\nexport async function readFileContent(path: string, range?: RangeBytes): Promise<Uint8Array> {\n return await fileReadLimiter.run(async () => {\n const ops: { start?: number; end?: number } = {};\n if (range) {\n ops.start = range.from;\n ops.end = range.to - 1;\n }\n\n let stream: fs.ReadStream | undefined;\n try {\n stream = fs.createReadStream(path, ops);\n return await buffer(stream);\n } catch (error) {\n if (stream && !stream.destroyed) {\n stream.destroy();\n }\n throw error;\n }\n });\n}\n","/** Handle of locally downloaded blob. This handle is issued only after the\n * blob's content is downloaded locally, and ready for quick access. */\n\nimport type { LocalBlobHandle } from '@milaboratories/pl-model-common';\nimport type { Signer } from '@milaboratories/ts-helpers';\n\n// https://regex101.com/r/kfnBVX/1\nconst localHandleRegex = /^blob\\+local:\\/\\/download\\/(?<path>.*)#(?<signature>.*)$/;\n\nexport function newLocalHandle(path: string, signer: Signer): LocalBlobHandle {\n return `blob+local://download/${path}#${signer.sign(path)}` as LocalBlobHandle;\n}\n\nexport function isLocalBlobHandle(handle: string): handle is LocalBlobHandle {\n return Boolean(handle.match(localHandleRegex));\n}\n\nexport function parseLocalHandle(handle: LocalBlobHandle, signer: Signer) {\n const parsed = handle.match(localHandleRegex);\n\n if (parsed === null) {\n throw new Error(`Local handle is malformed: ${handle}, matches: ${parsed}`);\n }\n\n const { path, signature } = parsed.groups!;\n signer.verify(path, signature, `Signature verification failed for: ${handle}`);\n\n return { path, signature };\n}\n","import { z } from 'zod';\nimport type { InferSnapshot } from '@milaboratories/pl-tree';\nimport { rsSchema } from '@milaboratories/pl-tree';\nimport { RangeBytes } from '@milaboratories/pl-model-common';\n\n//\n// 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 function getSize(bs: OnDemandBlobResourceSnapshot, range?: RangeBytes): number {\n const size = bs.kv['ctl/file/blobInfo'].sizeBytes;\n if (range) {\n const newSize = range.to - range.from;\n if (newSize > size) {\n throw new Error(`getSize: range (${JSON.stringify(range)}, newSize: ${newSize}) is greater than size (${size})`);\n }\n\n return newSize;\n }\n\n return size;\n}\n\n//\n// upload\n//\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/** 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\n//\n// ls\n//\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","/** Handle of remote blob. This handle is issued as soon as the data becomes\n * available on the remote server. */\n\nimport type { Signer } from '@milaboratories/ts-helpers';\nimport type { OnDemandBlobResourceSnapshot } from '../types';\nimport type { RemoteBlobHandle } from '@milaboratories/pl-model-common';\nimport { bigintToResourceId } from '@milaboratories/pl-client';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\nimport { getSize } from '../types';\n\n// https://regex101.com/r/Q4YdTa/5\nconst remoteHandleRegex\n = /^blob\\+remote:\\/\\/download\\/(?<content>(?<resourceType>.+)\\/(?<resourceVersion>.+?)\\/(?<resourceId>\\d+?)\\/(?<size>\\d+?))#(?<signature>.*)$/;\n\nexport function newRemoteHandle(\n rInfo: OnDemandBlobResourceSnapshot,\n signer: Signer,\n): RemoteBlobHandle {\n let content = `${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}/${getSize(rInfo)}`;\n\n return `blob+remote://download/${content}#${signer.sign(content)}` as RemoteBlobHandle;\n}\n\nexport function isRemoteBlobHandle(handle: string): handle is RemoteBlobHandle {\n return Boolean(handle.match(remoteHandleRegex));\n}\n\nexport function parseRemoteHandle(handle: RemoteBlobHandle, signer: Signer): {\n info: ResourceInfo;\n size: number;\n } {\n const parsed = handle.match(remoteHandleRegex);\n if (parsed === null) {\n throw new Error(`Remote handle is malformed: ${handle}, matches: ${parsed}`);\n }\n\n const { content, resourceType, resourceVersion, resourceId, size, signature } = parsed.groups!;\n\n signer.verify(content, signature, `Signature verification failed for ${handle}`);\n\n return {\n info:{\n id: bigintToResourceId(BigInt(resourceId)),\n type: { name: resourceType, version: resourceVersion },\n },\n size: Number(size),\n };\n}\n","import {\n BasicResourceData,\n getField,\n isNullResourceId,\n PlClient,\n ResourceId,\n valErr,\n} from '@milaboratories/pl-client';\n\n/** Throws when a driver gets a resource with a wrong resource type. */\nexport class WrongResourceTypeError extends Error {\n name = 'WrongResourceTypeError';\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","/** Handle of logs. This handle should be passed\n * to the driver for retrieving logs. */\n\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport { bigintToResourceId } from '@milaboratories/pl-client';\n\nexport function newLogHandle(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\n/** Handle of the live logs of a program.\n * The resource that represents a log can be deleted,\n * in this case the handle should be refreshed. */\n\nexport const 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\n/** Handle of the ready logs of a program. */\n\nexport const 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\nexport function getResourceInfoFromLogHandle(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","import { bigintToResourceId, ResourceId } from \"@milaboratories/pl-client\";\nimport * as path from 'node:path';\n\nexport function blobKey(rId: ResourceId): string {\n return `${BigInt(rId)}`;\n}\n\nexport function pathToKey(fPath: string): string {\n return path.basename(fPath);\n}\n\nexport function pathToBlobInfo(fPath: string): ResourceId | undefined {\n const base = path.basename(fPath);\n return bigintToResourceId(BigInt(base));\n}\n","import type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport type { LocalBlobHandle, LocalBlobHandleAndSize } from '@milaboratories/pl-model-common';\nimport type { ResourceSnapshot } from '@milaboratories/pl-tree';\nimport type {\n ValueOrError,\n MiLogger,\n} from '@milaboratories/ts-helpers';\nimport {\n ensureDirExists,\n fileExists,\n createPathAtomically,\n CallersCounter,\n} from '@milaboratories/ts-helpers';\nimport fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Writable } from 'node:stream';\nimport type { ClientDownload } from '../../clients/download';\nimport { UnknownStorageError, WrongLocalFileUrl } from '../../clients/download';\nimport { NetworkError400 } from '../../helpers/download';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\n\n/** Downloads a blob and holds callers and watchers for the blob. */\nexport class DownloadBlobTask {\n readonly change = new ChangeSource();\n private readonly signalCtl = new AbortController();\n public readonly counter = new CallersCounter();\n private error: unknown | undefined;\n private done = false;\n public size = 0;\n private state: DownloadState = {};\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientDownload: ClientDownload,\n readonly rInfo: ResourceSnapshot,\n private readonly handle: LocalBlobHandle,\n readonly path: string,\n ) {}\n\n /** Returns a simple object that describes this task for debugging purposes. */\n public info() {\n return {\n rInfo: this.rInfo,\n fPath: this.path,\n done: this.done,\n error: this.error,\n state: this.state,\n };\n }\n\n public attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n if (!this.done) this.change.attachWatcher(w);\n }\n\n public async download() {\n try {\n const size = await this.ensureDownloaded();\n this.setDone(size);\n this.change.markChanged(`blob download for ${resourceIdToString(this.rInfo.id)} finished`);\n } catch (e: any) {\n this.logger.error(`download blob ${stringifyWithResourceId(this.rInfo)} failed: ${e}, state: ${JSON.stringify(this.state)}`);\n if (nonRecoverableError(e)) {\n this.setError(e);\n this.change.markChanged(`blob download for ${resourceIdToString(this.rInfo.id)} failed`);\n // Just in case we were half-way extracting an archive.\n await fsp.rm(this.path, { force: true });\n }\n\n throw e;\n }\n }\n\n private async ensureDownloaded() {\n this.signalCtl.signal.throwIfAborted();\n\n this.state = {};\n this.state.filePath = this.path;\n await ensureDirExists(path.dirname(this.state.filePath));\n this.signalCtl.signal.throwIfAborted();\n this.state.dirExists = true;\n\n const alreadyExists = await fileExists(this.state.filePath);\n this.signalCtl.signal.throwIfAborted();\n if (alreadyExists) {\n this.state.fileExists = true;\n this.logger.info(`a blob was already downloaded: ${this.state.filePath}`);\n const stat = await fsp.stat(this.state.filePath);\n this.signalCtl.signal.throwIfAborted();\n this.state.fileSize = stat.size;\n\n return this.state.fileSize;\n }\n\n const fileSize = await this.clientDownload.withBlobContent(\n this.rInfo,\n {},\n { signal: this.signalCtl.signal },\n async (content, size) => {\n this.state.fileSize = size;\n this.state.downloaded = true;\n\n await createPathAtomically(this.logger, this.state.filePath!, async (fPath: string) => {\n const f = Writable.toWeb(fs.createWriteStream(fPath, { flags: 'wx' }));\n await content.pipeTo(f, { signal: this.signalCtl.signal });\n this.state.tempWritten = true;\n });\n\n this.state.done = true;\n return size;\n }\n );\n\n return fileSize;\n }\n\n public abort(reason: string) {\n this.signalCtl.abort(new DownloadAborted(reason));\n }\n\n public getBlob():\n | { done: false }\n | {\n done: true;\n result: ValueOrError<LocalBlobHandleAndSize>;\n } {\n if (!this.done) return { done: false };\n\n return {\n done: this.done,\n result: getDownloadedBlobResponse(this.handle, this.size, this.error),\n };\n }\n\n private setDone(sizeBytes: number) {\n this.done = true;\n this.size = sizeBytes;\n }\n\n private setError(e: unknown) {\n this.done = true;\n this.error = e;\n }\n}\n\nexport function nonRecoverableError(e: any) {\n return (\n e instanceof DownloadAborted\n || e instanceof NetworkError400\n || e instanceof UnknownStorageError\n || e instanceof WrongLocalFileUrl\n // file that we downloads from was moved or deleted.\n || e?.code == 'ENOENT'\n // A resource was deleted.\n || (e.name == 'RpcError' && (e.code == 'NOT_FOUND' || e.code == 'ABORTED'))\n );\n}\n\n/** The downloading task was aborted by a signal.\n * It may happen when the computable is done, for example. */\nclass DownloadAborted extends Error {\n name = 'DownloadAborted';\n}\n\nexport function getDownloadedBlobResponse(\n handle: LocalBlobHandle | undefined,\n size: number,\n error?: unknown,\n): ValueOrError<LocalBlobHandleAndSize> {\n if (error) {\n return { ok: false, error };\n }\n\n if (!handle) {\n return { ok: false, error: new Error('No file or handle provided') };\n }\n\n return {\n ok: true,\n value: {\n handle,\n size,\n },\n };\n}\n\ntype DownloadState = {\n filePath?: string;\n dirExists?: boolean;\n fileExists?: boolean;\n fileSize?: number;\n downloaded?: boolean;\n tempWritten?: boolean;\n done?: boolean;\n}\n","import type { CallersCounter } from '@milaboratories/ts-helpers';\nimport { mapEntries, mapGet } from '@milaboratories/ts-helpers';\n\ntype PathLike = string;\n\nexport interface CachedFile {\n /** Size in bytes. */\n size: 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) {\n return;\n }\n\n const file = mapGet(this.cache, path);\n freedBytes += file.size;\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.size < 0) {\n throw new Error(`empty sizeBytes: ${file}`);\n }\n\n if (created) {\n this.totalSizeBytes += file.size;\n }\n }\n\n removeCache(file: T) {\n this.cache.delete(file.path);\n this.totalSizeBytes -= file.size;\n }\n}\n","import { z } from \"zod\";\nimport * as fs from 'node:fs/promises';\nimport { RangeBytes } from \"@milaboratories/pl-model-common\";\nimport { createPathAtomically, MiLogger } from \"@milaboratories/ts-helpers\";\nimport { CorruptedRangesError } from \"./cache\";\n\n/** The content of the ranges file: ranges of bytes.\n * The ranges should be normalized: sorted and no overlaps.\n * For that, use `normalizeRanges` function. */\nconst Ranges = z.object({\n ranges: z.array(RangeBytes),\n});\n\nexport type Ranges = z.infer<typeof Ranges>;\n\nexport const rangesFilePostfix = '.ranges.json';\n\nexport function rangesFileName(fPath: string): string {\n return fPath + rangesFilePostfix;\n}\n\nexport async function readRangesFile(logger: MiLogger, path: string): Promise<Ranges> {\n let ranges: Ranges = { ranges: [] };\n try {\n const file = await fs.readFile(path, 'utf8');\n ranges = Ranges.parse(JSON.parse(file));\n } catch (e: unknown) {\n\n if (e instanceof SyntaxError || e instanceof z.ZodError) {\n const msg = `readRangesFile: the file ${path} was corrupted: ${e}`;\n logger.error(msg);\n throw new CorruptedRangesError(msg);\n }\n\n if (!(e instanceof Error && 'code' in e && e.code === 'ENOENT')) {\n throw e;\n }\n\n // If the file does not exist, assume the ranges are empty.\n }\n\n normalizeRanges(ranges);\n\n return ranges;\n}\n\n/** Writes to a temporal file and then renames it atomically. */\nexport async function writeRangesFile(logger: MiLogger, path: string, ranges: Ranges) {\n await createPathAtomically(logger, path, async (tempPath: string) => {\n await fs.writeFile(tempPath, JSON.stringify(ranges, null, 2), { flag: 'wx' });\n });\n}\n\n/** Sorts and merges overlapping ranges. */\nexport function normalizeRanges(s: Ranges) {\n s.ranges.sort((a, b) => a.from - b.from);\n\n for (let i = 0; i < s.ranges.length - 1; i++) {\n if (s.ranges[i].to >= s.ranges[i + 1].from) {\n mergeRanges(s, i);\n i--;\n }\n }\n}\n\nfunction mergeRanges(s: Ranges, i: number) {\n const from = Math.min(s.ranges[i].from, s.ranges[i + 1].from);\n const to = Math.max(s.ranges[i].to, s.ranges[i + 1].to);\n\n s.ranges.splice(i, 2, { from, to });\n}\n\nexport function rangesSize(s: Ranges) {\n return s.ranges.reduce((acc, range) => acc + range.to - range.from, 0);\n}\n\nexport function doesRangeExist(allRanges: Ranges, range: RangeBytes): boolean {\n for (const r of allRanges.ranges) {\n if (r.from <= range.from && range.to <= r.to) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function addRange(s: Ranges, range: RangeBytes) {\n s.ranges.push(range);\n normalizeRanges(s);\n\n return s;\n}\n\n","import { fileExists, MiLogger, spawnAsync } from \"@milaboratories/ts-helpers\";\nimport * as fs from 'node:fs/promises';\n\n/** Creates a sparse file for all systems\n * Table of what supports sparse files:\n * https://en.wikipedia.org/wiki/Comparison_of_file_systems#Allocation_and_layout_policies */\nexport async function createSparseFile(\n logger: MiLogger,\n path: string,\n platform: NodeJS.Platform,\n) {\n try {\n const ensureCreated = await fs.open(path, 'w');\n await ensureCreated.close();\n\n await ensureSparseOnWindows(path, platform);\n } catch (error: unknown) {\n logger.error(`Error creating file ${path} on platform ${platform}: ${error}`);\n }\n}\n\n/** Sets a sparse flag on Windows.\n * We could check the file is sparse by running:\n * `fsutil sparse queryflag <path>`\n * and\n * `fsutil sparse queryrange <path>`\n */\nasync function ensureSparseOnWindows(path: string, platform: NodeJS.Platform) {\n if (platform === 'win32') {\n await spawnAsync('fsutil', ['sparse', 'setflag', `\"${path}\"`], { stdio: 'pipe' });\n }\n}\n\n/** Ensures the file is created and writes to it. */\nexport async function writeToSparseFile(\n logger: MiLogger,\n platform: NodeJS.Platform,\n path: string,\n data: Uint8Array,\n from: number\n) {\n if (!(await fileExists(path))) {\n await createSparseFile(logger, path, platform);\n }\n\n const fileHandle = await fs.open(path, 'r+');\n await fileHandle.write(data, 0, data.length, from);\n await fileHandle.close();\n}\n","import { RangeBytes } from '@milaboratories/pl-model-common';\nimport { ensureDirExists, fileExists, mapEntries, MiLogger } from '@milaboratories/ts-helpers';\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { addRange, doesRangeExist, Ranges, rangesFileName, rangesFilePostfix, rangesSize, readRangesFile, writeRangesFile } from './ranges';\nimport { writeToSparseFile } from './file';\nimport { functions } from '@milaboratories/helpers';\n\n/** The implementer of SparseCacheRanges could throw it if ranges were corrupted. */\nexport class CorruptedRangesError extends Error {\n name = 'CorruptedRangesError';\n}\n\n/** Extracted ranges methods to be able to store ranges somewhere else (e.g. in memory for tests). */\nexport interface SparseCacheRanges {\n get(key: string): Promise<Ranges>;\n set(key: string, ranges: Ranges): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Stores ranges in a directory as JSON files (the default implementation). */\nexport class SparseCacheFsRanges implements SparseCacheRanges {\n constructor(\n private readonly logger: MiLogger,\n private readonly cacheDir: string,\n ) {}\n\n private fPath(key: string): string {\n return path.join(this.cacheDir, rangesFileName(key));\n }\n\n async get(key: string): Promise<Ranges> {\n return await readRangesFile(this.logger, this.fPath(key));\n }\n\n async set(key: string, ranges: Ranges) {\n return await writeRangesFile(this.logger, this.fPath(key), ranges);\n }\n\n async delete(key: string) {\n await fs.rm(this.fPath(key));\n }\n}\n\n/** Extracted interface for storing sparse files. */\nexport interface SparseFileStorage {\n all(): Promise<string[]>;\n exists(key: string): Promise<boolean>;\n path(key: string): string;\n write(key: string, data: Uint8Array, from: number): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Stores sparse files in a directory (the default implementation). */\nexport class SparseCacheFsFile implements SparseFileStorage {\n private readonly suffix = '.sparse.bin';\n\n constructor(\n private readonly logger: MiLogger,\n private readonly cacheDir: string,\n ) {}\n\n async all(): Promise<string[]> {\n await ensureDirExists(this.cacheDir);\n const files = await fs.readdir(this.cacheDir);\n return files.filter((f) => f.endsWith(this.suffix));\n }\n\n async exists(key: string): Promise<boolean> {\n return await fileExists(this.path(key));\n }\n\n path(key: string): string {\n return path.join(this.cacheDir, key + this.suffix);\n }\n\n async write(key: string, data: Uint8Array, from: number): Promise<void> {\n await ensureDirExists(this.cacheDir);\n await writeToSparseFile(this.logger, process.platform, this.path(key), data, from);\n }\n\n async delete(key: string): Promise<void> {\n await fs.rm(this.path(key));\n }\n}\n\n/** LRU cache for ranges of sparse files. */\nexport class SparseCache {\n /** Fields are public for tests. */\n\n /** The lock to make sure cache requests are done one by one. */\n private lock = new functions.AwaitLock()\n\n public keyToLastAccessTime = new Map<string, Date>();\n public size = 0;\n\n constructor(\n public readonly logger: MiLogger,\n /** The hard limit in bytes. */\n public readonly maxSize: number,\n public readonly ranges: SparseCacheRanges,\n public readonly storage: SparseFileStorage,\n ) {}\n\n /** Resets a cache's size by rereading everything we already store.\n * Safe for concurrent use. */\n async reset() {\n await withLock(this.lock, async () => {\n await this.resetUnsafe();\n })\n }\n\n /** Returns a path to the key if the range exists in a cache, otherwise returns undefined.\n * Safe for concurrent use. */\n async get(key: string, range: RangeBytes): Promise<string | undefined> {\n return await withLock(this.lock, async () => {\n return await this.getUnsafe(key, range);\n });\n }\n\n /** Sets data to the cache's file and clear the cache if it's needed.\n * Safe for concurrent use. */\n async set(key: string, range: RangeBytes, data: Uint8Array): Promise<void> {\n await withLock(this.lock, async () => {\n await this.setUnsafe(key, range, data);\n })\n }\n\n private async resetUnsafe() {\n this.size = 0;\n this.keyToLastAccessTime = new Map<string, Date>();\n\n const now = new Date();\n // In rmKey method we first deletes the key from a storage and only then from ranges,\n // so if something goes wrong between 2 operations,\n // on reset the logic will be correct.\n for (const key of await this.storage.all()) {\n const ranges = await this.ranges.get(key);\n this.size += rangesSize(ranges);\n this.keyToLastAccessTime.set(key, now);\n }\n }\n\n private async getUnsafe(key: string, range: RangeBytes): Promise<string | undefined> {\n // It first checks the storage, and then the ranges.\n // In another method, when we remove a key, it first deletes a key from a storage and then from ranges,\n // so if we don't have a key in storage but have it in ranges, the logic here is correct.\n // We probably could reverse the operations here and there, and everywhere we work with both storage and ranges.\n if (await this.storage.exists(key)) {\n this.keyToLastAccessTime.set(key, new Date());\n\n const ranges = await this.getRanges(key);\n if (doesRangeExist(ranges, range)) {\n return this.storage.path(key);\n }\n\n return undefined;\n }\n\n return undefined;\n }\n\n private async setUnsafe(key: string, range: { from: number; to: number; }, data: Uint8Array) {\n await this.setWithoutEviction(key, range, data);\n await this.ensureEvicted();\n }\n\n /** Sets a key and recalculates a size, but doesn't ensures that the size is less than the hard limit. */\n async setWithoutEviction(key: string, range: RangeBytes, data: Uint8Array): Promise<void> {\n if (range.to - range.from !== data.length) {\n throw new Error(\n `SparseCache.set: trying to set ${key} with wrong range length: `\n + `range: ${JSON.stringify(range)}, data: ${data.length}`\n );\n }\n\n this.keyToLastAccessTime.set(key, new Date());\n\n const ranges = await this.getRanges(key);\n this.size -= rangesSize(ranges);\n\n await this.storage.write(key, data, range.from);\n\n const newRanges = addRange(ranges, range);\n this.size += rangesSize(newRanges);\n\n await this.ranges.set(key, newRanges);\n }\n\n /** Ensures the size is less than hard limit by deleting the oldest keys. */\n async ensureEvicted(): Promise<void> {\n const byTime = mapEntries(this.keyToLastAccessTime);\n byTime.sort(([_, aDate], [__, bDate]) => bDate.getTime() - aDate.getTime());\n\n while (this.size > this.maxSize) {\n const keyAndDate = byTime.pop(); // removes the oldest\n if (!keyAndDate) {\n break;\n }\n const [key, _] = keyAndDate;\n\n const ranges = await this.getRanges(key);\n this.size -= rangesSize(ranges);\n this.rmKey(key);\n }\n }\n\n /** Gets ranges and if they were corrupted, then remove the file from the cache and reset the cache's size. */\n private async getRanges(key: string) {\n try {\n return await this.ranges.get(key);\n } catch (e: unknown) {\n if (e instanceof CorruptedRangesError) {\n // We need to reset a state of the cache and update current size,\n // it's the only way to calculate the real size when one of the ranges were corrupted.\n await this.rmKey(key);\n await this.resetUnsafe();\n\n return await this.ranges.get(key);\n }\n\n throw e;\n }\n }\n\n /** Removes a key the state of the cache. The size should be updated. */\n private async rmKey(key: string) {\n await this.storage.delete(key);\n await this.ranges.delete(key);\n this.keyToLastAccessTime.delete(key);\n }\n}\n\n/** Acquires the lock and executes a callback. */\nasync function withLock<T>(lock: functions.AwaitLock, cb: () => Promise<T>): Promise<T> {\n try {\n await lock.acquireAsync();\n return await cb();\n } finally {\n lock.release();\n }\n}\n","import type {\n ComputableCtx,\n ComputableStableDefined,\n Watcher,\n} from '@milaboratories/computable';\nimport {\n ChangeSource,\n Computable,\n} from '@milaboratories/computable';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type {\n AnyLogHandle,\n BlobDriver,\n LocalBlobHandle,\n LocalBlobHandleAndSize,\n ReadyLogHandle,\n RemoteBlobHandle,\n RemoteBlobHandleAndSize,\n StreamingApiResponse,\n} from '@milaboratories/pl-model-common';\nimport { type RangeBytes, validateRangeBytes } from '@milaboratories/pl-model-common';\nimport type {\n PlTreeEntry,\n ResourceInfo,\n ResourceSnapshot\n} from '@milaboratories/pl-tree';\nimport {\n isPlTreeEntry,\n makeResourceSnapshot,\n treeEntryToResourceInfo,\n} from '@milaboratories/pl-tree';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { CallersCounter, mapGet, TaskProcessor } from '@milaboratories/ts-helpers';\nimport Denque from 'denque';\nimport * as fs from 'fs';\nimport { randomUUID } from 'node:crypto';\nimport * as fsp from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport * as readline from 'node:readline/promises';\nimport { Writable } from 'node:stream';\nimport { buffer } from 'node:stream/consumers';\nimport type { ClientDownload } from '../../clients/download';\nimport type { ClientLogs } from '../../clients/logs';\nimport { readFileContent } from '../helpers/read_file';\nimport {\n isLocalBlobHandle,\n newLocalHandle,\n parseLocalHandle,\n} from '../helpers/download_local_handle';\nimport {\n isRemoteBlobHandle,\n newRemoteHandle,\n parseRemoteHandle,\n} from '../helpers/download_remote_handle';\nimport { Updater, WrongResourceTypeError } from '../helpers/helpers';\nimport { getResourceInfoFromLogHandle, newLogHandle } from '../helpers/logs_handle';\nimport { getSize, OnDemandBlobResourceSnapshot } from '../types';\nimport { blobKey, pathToKey } from './blob_key';\nimport { DownloadBlobTask, nonRecoverableError } from './download_blob_task';\nimport { FilesCache } from '../helpers/files_cache';\nimport { SparseCache, SparseCacheFsFile, SparseCacheFsRanges } from './sparse_cache/cache';\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 /**\n * A hard limit of the amount of sparse cache, in bytes.\n * Once exceeded, the download driver will start deleting blobs one by one.\n *\n * The sparse cache is used to store ranges of blobs.\n * */\n rangesCacheMaxSizeBytes: number;\n\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 unique key to the path of a blob as a map. */\n private keyToDownload: Map<string, DownloadBlobTask> = 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<DownloadBlobTask>;\n private rangesCache: SparseCache;\n\n /** Downloads files and writes them to the local dir. */\n private downloadQueue: TaskProcessor;\n\n private keyToOnDemand: Map<string, OnDemandBlobHolder> = new Map();\n\n private idToLastLines: Map<string, LastLinesGetter> = new Map();\n private idToProgressLog: Map<string, 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 rangesCacheDir: string,\n private readonly signer: Signer,\n private readonly ops: DownloadDriverOps,\n ) {\n this.cache = new FilesCache(this.ops.cacheSoftSizeBytes);\n\n const fsRanges = new SparseCacheFsRanges(this.logger, this.rangesCacheDir);\n const fsStorage = new SparseCacheFsFile(this.logger, this.rangesCacheDir);\n this.rangesCache = new SparseCache(this.logger, this.ops.rangesCacheMaxSizeBytes, fsRanges, fsStorage);\n\n this.downloadQueue = new TaskProcessor(this.logger, ops.nConcurrentDownloads);\n\n this.saveDir = path.resolve(saveDir);\n }\n\n static async init(\n logger: MiLogger,\n clientDownload: ClientDownload,\n clientLogs: ClientLogs,\n saveDir: string,\n rangesCacheDir: string,\n signer: Signer,\n ops: DownloadDriverOps,\n ): Promise<DownloadDriver> {\n const driver = new DownloadDriver(logger, clientDownload, clientLogs, saveDir, rangesCacheDir, signer, ops);\n await driver.rangesCache.reset();\n\n return driver;\n }\n\n /** Gets a blob or part of the blob by its resource id or downloads a blob and sets it in a cache. */\n public getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx: ComputableCtx,\n ): LocalBlobHandleAndSize | undefined;\n public getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ): ComputableStableDefined<LocalBlobHandleAndSize>;\n public getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx,\n ): Computable<LocalBlobHandleAndSize | undefined> | LocalBlobHandleAndSize | undefined {\n if (ctx === undefined) {\n return Computable.make((ctx) => this.getDownloadedBlob(res, ctx));\n }\n\n const rInfo = treeEntryToResourceInfo(res, ctx);\n\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(rInfo, callerId));\n\n const result = this.getDownloadedBlobNoCtx(ctx.watcher, rInfo as ResourceSnapshot, callerId);\n if (result == undefined) {\n ctx.markUnstable('download blob is still undefined');\n }\n\n return result;\n }\n\n private getDownloadedBlobNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n callerId: string,\n ): LocalBlobHandleAndSize | undefined {\n validateDownloadableResourceType('getDownloadedBlob', rInfo.type);\n\n // We don't need to request files with wider limits,\n // PFrame's engine does it disk-optimally by itself.\n\n const task = this.getOrSetNewTask(rInfo, callerId);\n task.attach(w, callerId);\n\n const result = task.getBlob();\n if (!result.done) {\n return undefined;\n }\n if (result.result.ok) {\n return result.result.value;\n }\n throw result.result.error;\n }\n\n private getOrSetNewTask(\n rInfo: ResourceSnapshot,\n callerId: string,\n ): DownloadBlobTask {\n const key = blobKey(rInfo.id);\n\n const inMemoryTask = this.keyToDownload.get(key);\n if (inMemoryTask) {\n return inMemoryTask;\n }\n\n // schedule the blob downloading, then it'll be added to the cache.\n const fPath = path.resolve(this.saveDir, key);\n\n const newTask = new DownloadBlobTask(\n this.logger,\n this.clientDownload,\n rInfo,\n newLocalHandle(fPath, this.signer),\n fPath,\n );\n this.keyToDownload.set(key, newTask);\n\n this.downloadQueue.push({\n fn: () => this.downloadBlob(newTask, callerId),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e),\n });\n\n return newTask;\n }\n\n private async downloadBlob(task: DownloadBlobTask, callerId: string) {\n await task.download();\n const blob = task.getBlob();\n if (blob.done && blob.result.ok) {\n this.cache.addCache(task, callerId);\n }\n }\n\n /** Gets on demand blob. */\n public getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ): Computable<RemoteBlobHandleAndSize>;\n public getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx?: undefined,\n fromBytes?: number,\n toBytes?: number,\n ): Computable<RemoteBlobHandleAndSize>;\n public getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx: ComputableCtx,\n fromBytes?: number,\n toBytes?: number,\n ): RemoteBlobHandleAndSize;\n public 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 // note that the watcher is not needed,\n // the handler never changes.\n const result = this.getOnDemandBlobNoCtx(rInfo, callerId);\n\n return result;\n }\n\n private getOnDemandBlobNoCtx(\n info: OnDemandBlobResourceSnapshot,\n callerId: string,\n ): RemoteBlobHandleAndSize {\n validateDownloadableResourceType('getOnDemandBlob', info.type);\n\n let blob = this.keyToOnDemand.get(blobKey(info.id));\n\n if (blob === undefined) {\n blob = new OnDemandBlobHolder(getSize(info), newRemoteHandle(info, this.signer));\n this.keyToOnDemand.set(blobKey(info.id), blob);\n }\n\n blob.attach(callerId);\n\n return blob.getHandle();\n }\n\n /** Gets a path from a handle. */\n public getLocalPath(handle: LocalBlobHandle): string {\n const { path } = parseLocalHandle(handle, this.signer);\n return path;\n }\n\n /** Gets a content of a blob by a handle. */\n public async getContent(handle: LocalBlobHandle | RemoteBlobHandle, range?: RangeBytes): Promise<Uint8Array> {\n if (range) {\n validateRangeBytes(range, `getContent`);\n }\n\n if (isLocalBlobHandle(handle)) {\n return await readFileContent(this.getLocalPath(handle), range);\n }\n\n if (isRemoteBlobHandle(handle)) {\n const result = parseRemoteHandle(handle, this.signer);\n\n const key = blobKey(result.info.id);\n const filePath = await this.rangesCache.get(key, range ?? { from: 0, to: result.size });\n if (filePath) {\n return await readFileContent(filePath, range);\n }\n\n const data = await this.clientDownload.withBlobContent(\n { id: result.info.id, type: result.info.type },\n undefined,\n { range },\n async (content) => await buffer(content)\n );\n await this.rangesCache.set(key, range ?? { from: 0, to: result.size }, data);\n\n return data;\n }\n\n throw new Error('Malformed remote handle');\n }\n\n /**\n * Creates computable that will return blob content once it is downloaded.\n * Uses downloaded blob handle under the hood, so stores corresponding blob in file system.\n */\n public getComputableContent(\n res: ResourceInfo | PlTreeEntry,\n range?: RangeBytes,\n ): ComputableStableDefined<Uint8Array> {\n if (range) {\n validateRangeBytes(range, `getComputableContent`);\n }\n\n return Computable.make((ctx) =>\n this.getDownloadedBlob(res, ctx), {\n postprocessValue: (v) => v ? this.getContent(v.handle, range) : undefined\n }\n ).withStableType()\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 public getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number\n ): Computable<string | undefined>;\n public getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx: ComputableCtx\n ): Computable<string | undefined>;\n public 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, 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 validateDownloadableResourceType('getLastLogs', rInfo.type);\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n\n const { path } = parseLocalHandle(blob.handle, this.signer);\n\n let logGetter = this.idToLastLines.get(blobKey(rInfo.id));\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, lines);\n this.idToLastLines.set(blobKey(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 public getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string\n ): Computable<string | undefined>;\n public getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx: ComputableCtx\n ): string | undefined;\n public 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, 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 validateDownloadableResourceType('getProgressLog', rInfo.type);\n\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n const { path } = parseLocalHandle(blob.handle, this.signer);\n\n let logGetter = this.idToProgressLog.get(blobKey(rInfo.id));\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, 1, patternToSearch);\n this.idToProgressLog.set(blobKey(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 public getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<AnyLogHandle>;\n public getLogHandle(res: ResourceInfo | PlTreeEntry, ctx: ComputableCtx): AnyLogHandle;\n public 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 validateDownloadableResourceType('getLogHandle', rInfo.type);\n return newLogHandle(false, rInfo);\n }\n\n public 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 getResourceInfoFromLogHandle(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 public 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 getResourceInfoFromLogHandle(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(rInfo: ResourceInfo, callerId: string) {\n const task = this.keyToDownload.get(blobKey(rInfo.id));\n if (task == undefined) {\n return;\n }\n\n if (this.cache.existsFile(blobKey(rInfo.id))) {\n const toDelete = this.cache.removeFile(blobKey(rInfo.id), callerId);\n\n await Promise.all(\n toDelete.map(async (cachedFile) => {\n await fsp.rm(cachedFile.path);\n\n this.cache.removeCache(cachedFile);\n\n this.removeTask(\n mapGet(this.keyToDownload, pathToKey(cachedFile.path)),\n `the task ${stringifyWithResourceId(cachedFile)} was removed`\n + `from cache along with ${stringifyWithResourceId(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) {\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed from cache`,\n );\n }\n }\n }\n\n private removeTask(task: DownloadBlobTask, reason: string) {\n task.abort(reason);\n task.change.markChanged(`download task for ${task.path} removed: ${reason}`);\n this.keyToDownload.delete(pathToKey(task.path));\n this.idToLastLines.delete(blobKey(task.rInfo.id));\n this.idToProgressLog.delete(blobKey(task.rInfo.id));\n }\n\n private async releaseOnDemandBlob(blobId: ResourceId, callerId: string) {\n const deleted = this.keyToOnDemand.get(blobKey(blobId))?.release(callerId) ?? false;\n if (deleted) this.keyToOnDemand.delete(blobKey(blobId));\n }\n\n /** Removes all files from a hard drive. */\n async releaseAll() {\n this.downloadQueue.stop();\n\n this.keyToDownload.forEach((task, key) => {\n this.keyToDownload.delete(key);\n task.change.markChanged(`task ${resourceIdToString(task.rInfo.id)} released`);\n });\n }\n}\n\n/** Keeps a counter to the on demand handle. */\nclass OnDemandBlobHolder {\n private readonly counter = new CallersCounter();\n\n constructor(\n private readonly size: number,\n private readonly handle: RemoteBlobHandle,\n ) {}\n\n public getHandle(): RemoteBlobHandleAndSize {\n return { handle: this.handle, size: this.size };\n }\n\n public attach(callerId: string) {\n this.counter.inc(callerId);\n }\n\n public release(callerId: string): boolean {\n return this.counter.dec(callerId);\n }\n}\n\nclass LastLinesGetter {\n private updater: 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 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(`logs for ${this.path} updated`);\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(`log update for ${this.path} failed, resource not found`);\n return;\n }\n\n throw e;\n }\n }\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. */\nasync function getLastLines(fPath: string, nLines: number, patternToSearch?: string): Promise<string> {\n let inStream: fs.ReadStream | undefined;\n let rl: readline.Interface | undefined;\n\n try {\n inStream = fs.createReadStream(fPath);\n rl = readline.createInterface({ input: inStream, crlfDelay: Infinity });\n\n const lines = new Denque();\n\n for await (const line of rl) {\n if (patternToSearch != undefined && !line.includes(patternToSearch)) continue;\n\n lines.push(line);\n if (lines.length > nLines) {\n lines.shift();\n }\n }\n\n // last EOL is for keeping backward compat with platforma implementation.\n return lines.toArray().join(os.EOL) + os.EOL;\n } finally {\n // Cleanup resources in finally block to ensure they're always cleaned up\n try {\n if (rl) {\n rl.close();\n }\n } catch (cleanupError) {\n console.error('Error closing readline interface:', cleanupError);\n }\n\n try {\n if (inStream && !inStream.destroyed) {\n inStream.destroy();\n }\n } catch (cleanupError) {\n console.error('Error destroying read stream:', cleanupError);\n }\n }\n}\n\nfunction validateDownloadableResourceType(methodName: string, rType: ResourceType) {\n if (!rType.name.startsWith('Blob/')) {\n let message = `${methodName}: wrong resource type: ${rType.name}, expected: a resource of type that starts with 'Blob/'.`;\n if (rType.name == 'Blob')\n message += ` If it's called from workflow, should a file be exported with 'file.exportFile' function?`;\n\n throw new WrongResourceTypeError(message);\n }\n}\n","import type { ComputableCtx } from '@milaboratories/computable';\nimport type { InferSnapshot, PlTreeEntry, PlTreeEntryAccessor, PlTreeNodeAccessor } from '@milaboratories/pl-tree';\nimport { isPlTreeEntry, isPlTreeEntryAccessor, makeResourceSnapshot, rsSchema } from '@milaboratories/pl-tree';\n\n/** We need only resource type for this driver. */\nexport const DownloadableBlobSnapshot = rsSchema({});\nexport type DownloadableBlobSnapshot = InferSnapshot<typeof DownloadableBlobSnapshot>;\n\nexport function makeDownloadableBlobSnapshot(\n entryOrAccessor: PlTreeEntry | PlTreeNodeAccessor | PlTreeEntryAccessor,\n ctx: ComputableCtx,\n): DownloadableBlobSnapshot {\n const node = isPlTreeEntry(entryOrAccessor)\n ? ctx.accessor(entryOrAccessor).node()\n : isPlTreeEntryAccessor(entryOrAccessor)\n ? entryOrAccessor.node()\n : entryOrAccessor;\n\n return makeResourceSnapshot(node, DownloadableBlobSnapshot);\n}\n","import type { FolderURL, BlockUIURL } from '@milaboratories/pl-model-common';\nimport type { Signer } from '@milaboratories/ts-helpers';\nimport path from 'path';\n\n/** Creates a new plblob+folder URL. */\nexport function newFolderURL(signer: Signer, saveDir: string, fPath: string): FolderURL {\n const p = path.relative(saveDir, fPath);\n const sign = signer.sign(p);\n\n return `plblob+folder://${sign}.${p}.blob`;\n}\n\n/** Creates a new block-ui URL. */\nexport function newBlockUIURL(signer: Signer, saveDir: string, fPath: string): BlockUIURL {\n const p = path.relative(saveDir, fPath);\n const sign = signer.sign(p);\n\n return `block-ui://${sign}.${p}.uidir`;\n}\n\n/** Checks the signature and path injections.\n * @returns the path to the file inside the root directory. */\nexport function getPathForFolderURL(signer: Signer, url: FolderURL, rootDir: string): string {\n return getPath(signer, url, rootDir);\n}\n\n/** Checks the signature and path injections.\n * @returns the path to the file inside the root directory. */\nexport function getPathForBlockUIURL(signer: Signer, url: BlockUIURL, rootDir: string): string {\n return getPath(signer, url, rootDir);\n}\n\n/** Parses URL,\n * checks the signature,\n * gets the absolute path by the given root directory.\n * If the path is empty, it returns the index.html file.\n * @returns an absolute path for the user. */\nfunction getPath(signer: Signer, url: string, rootDir: string): string {\n const parsed = new URL(url);\n const [sign, subfolder, _] = parsed.host.split('.');\n\n signer.verify(subfolder, sign, `signature verification failed for url: ${url}, subfolder: ${subfolder}`);\n\n // Decoding changes '%20' to ' ' for example.\n const pathname = decodeURIComponent(parsed.pathname.slice(1));\n\n let fPath = parseNestedPathNoEscape(path.join(rootDir, `${subfolder}`), pathname);\n\n if (parsed.pathname == '' || parsed.pathname == '/') {\n fPath = path.join(fPath, 'index.html');\n }\n\n return path.resolve(fPath);\n}\n\n/** Checks that the userInputPath is in baseDir.\n * @returns an absolute path for the user. */\nfunction parseNestedPathNoEscape(baseDir: string, userInputPath: string): string {\n const absolutePath = path.resolve(baseDir, userInputPath);\n\n const normalizedBase = path.resolve(baseDir);\n\n if (!absolutePath.startsWith(normalizedBase)) {\n throw new Error('Path validation failed.');\n }\n\n return absolutePath;\n}\n","import { Transform, Writable } from 'node:stream';\nimport * as zlib from 'node:zlib';\nimport * as tar from 'tar-fs';\nimport path from 'path';\nimport fs from 'fs';\nimport * as fsp from 'fs/promises';\nimport { NetworkError400 } from '../../helpers/download';\nimport type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { CallersCounter, createPathAtomically, ensureDirExists, fileExists, notEmpty } from '@milaboratories/ts-helpers';\nimport type { DownloadableBlobSnapshot } from './snapshot';\nimport { UnknownStorageError, WrongLocalFileUrl, type ClientDownload } from '../../clients/download';\nimport type { ArchiveFormat, FolderURL } from '@milaboratories/pl-model-common';\nimport { newFolderURL } from '../urls/url';\nimport decompress from 'decompress';\nimport { assertNever } from '@protobuf-ts/runtime';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\n\nexport type URLResult = {\n url?: FolderURL;\n error?: string;\n};\n\n/** Downloads and extracts an archive to a directory. */\nexport class DownloadAndUnarchiveTask {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n private readonly signalCtl = new AbortController();\n error: string | undefined;\n done = false;\n size = 0;\n private url: FolderURL | undefined;\n private state: DownloadCtx | undefined;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly signer: Signer,\n readonly saveDir: string,\n readonly path: string,\n readonly rInfo: DownloadableBlobSnapshot,\n readonly format: ArchiveFormat,\n private readonly clientDownload: ClientDownload,\n ) {}\n\n /** A debug info of the task. */\n public info() {\n return {\n rInfo: this.rInfo,\n format: this.format,\n path: this.path,\n done: this.done,\n size: this.size,\n error: this.error,\n taskHistory: this.state,\n };\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 const size = await this.downloadAndDecompress(this.signalCtl.signal);\n this.setDone(size);\n this.change.markChanged(`download and decompress for ${resourceIdToString(this.rInfo.id)} finished`);\n\n this.logger.info(`blob to URL task is done: ${stringifyWithResourceId(this.info())}`);\n } catch (e: any) {\n this.logger.warn(`a error was produced: ${e} for blob to URL task: ${stringifyWithResourceId(this.info())}`);\n\n if (nonRecoverableError(e)) {\n this.setError(e);\n this.change.markChanged(`download and decompress for ${resourceIdToString(this.rInfo.id)} failed`);\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 /** Does the download part and keeps a state of the process. */\n private async downloadAndDecompress(signal: AbortSignal): Promise<number> {\n this.state = {};\n\n this.state.parentDir = path.dirname(this.path);\n await ensureDirExists(this.state.parentDir);\n\n this.state.fileExisted = await fileExists(this.path);\n if (this.state.fileExisted) {\n return await dirSize(this.path);\n }\n\n const size = await this.clientDownload.withBlobContent(\n this.rInfo, \n {}, \n { signal },\n async (content, size) => {\n this.state!.downloaded = true;\n\n await createPathAtomically(this.logger, this.path, async (fPath: string) => {\n this.state!.tempPath = fPath;\n this.state!.archiveFormat = this.format;\n\n switch (this.format) {\n case 'tar':\n await fsp.mkdir(fPath); // throws if a directory already exists.\n const simpleUntar = Writable.toWeb(tar.extract(fPath));\n await content.pipeTo(simpleUntar, { signal });\n return;\n\n case 'tgz':\n await fsp.mkdir(fPath); // throws if a directory already exists.\n const gunzip = Transform.toWeb(zlib.createGunzip());\n const untar = Writable.toWeb(tar.extract(fPath));\n\n await content\n .pipeThrough(gunzip, { signal })\n .pipeTo(untar, { signal });\n return;\n\n case 'zip':\n this.state!.zipPath = this.path + '.zip';\n\n const f = Writable.toWeb(fs.createWriteStream(this.state!.zipPath));\n await content.pipeTo(f, { signal });\n this.state!.zipPathCreated = true;\n\n // Without this filter it fails with\n // \"EISDIR: illegal operation on a directory\".\n // The workaround is from\n // https://github.com/kevva/decompress/issues/46#issuecomment-525048104\n await decompress(this.state!.zipPath, fPath, {\n filter: file => !file.path.endsWith('/'),\n });\n this.state!.zipDecompressed = true;\n\n await fs.promises.rm(this.state!.zipPath);\n this.state!.zipPathDeleted = true;\n\n return;\n\n default:\n assertNever(this.format);\n }\n });\n\n this.state!.pathCreated = true;\n return size;\n }\n );\n\n return size;\n }\n\n getURL(): URLResult | undefined {\n if (this.done) return { url: notEmpty(this.url) };\n\n if (this.error) return { error: this.error };\n\n return undefined;\n }\n\n private setDone(size: number) {\n this.done = true;\n this.size = size;\n this.url = newFolderURL(this.signer, this.saveDir, this.path);\n }\n\n private setError(e: any) {\n this.error = String(e);\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new URLAborted(reason));\n }\n}\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: any) => {\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: any, size: any) => sum + size, 0);\n}\n\n/** Do rm -rf on dir. */\nexport async function rmRFDir(path: string) {\n await fsp.rm(path, { recursive: true, force: true });\n}\n\n/** Just a type that adds lots of context when the error happens. */\ntype DownloadCtx = {\n parentDir?: string;\n fileExisted?: boolean;\n downloaded?: boolean;\n archiveFormat?: ArchiveFormat;\n tempPath?: string;\n zipPath?: string;\n zipPathCreated?: boolean;\n zipDecompressed?: boolean;\n zipPathDeleted?: boolean;\n pathCreated?: boolean;\n};\n\n/** Throws when a downloading aborts. */\nclass URLAborted extends Error {\n name = 'URLAborted';\n}\n\nexport function nonRecoverableError(e: any) {\n return (\n e instanceof URLAborted\n || e instanceof NetworkError400\n || e instanceof UnknownStorageError\n || e instanceof WrongLocalFileUrl\n // file that we downloads from was moved or deleted.\n || e?.code == 'ENOENT'\n // A resource was deleted.\n || (e.name == 'RpcError' && (e.code == 'NOT_FOUND' || e.code == 'ABORTED'))\n // wrong archive format\n || (String(e).includes('incorrect header check'))\n );\n}\n","import type { ResourceId } from '@milaboratories/pl-client';\nimport type { ArchiveFormat } from '@milaboratories/pl-model-common';\n\n/** A key in the driver task queue. */\nexport type Id = string;\n\nexport function newId(id: ResourceId, format: ArchiveFormat): Id {\n return `id:${String(BigInt(id))}-${format}`;\n}\n\n// export function\n","import type { ComputableCtx, Watcher } from '@milaboratories/computable';\nimport { Computable } from '@milaboratories/computable';\nimport type {\n MiLogger,\n Signer } from '@milaboratories/ts-helpers';\nimport {\n TaskProcessor,\n} from '@milaboratories/ts-helpers';\nimport { randomUUID } from 'node:crypto';\nimport * as path from 'node:path';\nimport { FilesCache } from '../helpers/files_cache';\nimport type { ResourceId } from '@milaboratories/pl-client';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport { type ArchiveFormat, type BlobToURLDriver, type FolderURL, isFolderURL } from '@milaboratories/pl-model-common';\nimport type { DownloadableBlobSnapshot } from './snapshot';\nimport { makeDownloadableBlobSnapshot } from './snapshot';\nimport type { PlTreeEntry } from '@milaboratories/pl-tree';\nimport { isPlTreeEntry } from '@milaboratories/pl-tree';\nimport { DownloadAndUnarchiveTask, rmRFDir } from './task';\nimport type { ClientDownload } from '../../clients/download';\nimport { getPathForFolderURL } from '../urls/url';\nimport type { Id } from './driver_id';\nimport { newId } from './driver_id';\nimport { nonRecoverableError } from '../download_blob/download_blob_task';\n\nexport type DownloadBlobToURLDriverOps = {\n cacheSoftSizeBytes: number;\n nConcurrentDownloads: number;\n};\n\n/** Downloads .tar, .tar.gz or zip archives,\n * extracts them into saveDir and gets a url for it. */\nexport class DownloadBlobToURLDriver implements BlobToURLDriver {\n private idToDownload: Map<Id, DownloadAndUnarchiveTask> = 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<DownloadAndUnarchiveTask>;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly signer: Signer,\n private readonly clientDownload: ClientDownload,\n private readonly saveDir: string,\n private readonly opts: DownloadBlobToURLDriverOps = {\n cacheSoftSizeBytes: 50 * 1024 * 1024,\n nConcurrentDownloads: 50,\n },\n ) {\n this.downloadQueue = new TaskProcessor(this.logger, this.opts.nConcurrentDownloads, {\n type: 'exponentialWithMaxDelayBackoff',\n initialDelay: 10000,\n maxDelay: 30000,\n backoffMultiplier: 1.5,\n jitter: 0.5,\n });\n this.cache = new FilesCache(this.opts.cacheSoftSizeBytes);\n }\n\n public info(): any {\n return {\n saveDir: this.saveDir,\n opts: this.opts,\n idToDownloadSize: this.idToDownload.size,\n idToDownloadKeys: this.idToDownload.keys(),\n idToDownload: Array.from(this.idToDownload.entries()).map(([id, task]) => [id, task.info()]),\n };\n }\n\n /**\n * @returns full path to the referenced file\n */\n getPathForCustomProtocol(url: FolderURL): string {\n if (isFolderURL(url)) {\n return getPathForFolderURL(this.signer, url, this.saveDir);\n }\n\n throw new Error(`getPathForCustomProtocol: ${url} is invalid`);\n }\n\n extractArchiveAndGetURL(\n res: DownloadableBlobSnapshot | PlTreeEntry,\n format: ArchiveFormat,\n ctx: ComputableCtx,\n ): FolderURL | undefined;\n\n extractArchiveAndGetURL(\n res: DownloadableBlobSnapshot | PlTreeEntry,\n format: ArchiveFormat,\n ): Computable<FolderURL | undefined>;\n\n extractArchiveAndGetURL(\n res: DownloadableBlobSnapshot | PlTreeEntry,\n format: ArchiveFormat,\n ctx?: ComputableCtx,\n ): Computable<FolderURL | undefined> | FolderURL | undefined {\n // wrap result as computable, if we were not given an existing computable context\n if (ctx === undefined)\n return Computable.make((c) => this.extractArchiveAndGetURL(res, format, c));\n\n const rInfo: DownloadableBlobSnapshot = isPlTreeEntry(res)\n ? makeDownloadableBlobSnapshot(res, ctx)\n : res;\n\n const callerId = randomUUID();\n\n ctx.addOnDestroy(() => this.releasePath(rInfo.id, format, callerId));\n\n const result = this.extractArchiveAndGetURLNoCtx(rInfo, format, ctx.watcher, callerId);\n if (result?.url === undefined)\n ctx.markUnstable(\n `a path to the downloaded archive might be undefined. The current result: ${result}`,\n );\n\n if (result?.error !== undefined)\n throw result?.error;\n\n return result?.url;\n }\n\n private extractArchiveAndGetURLNoCtx(\n rInfo: DownloadableBlobSnapshot,\n format: ArchiveFormat,\n w: Watcher,\n callerId: string,\n ) {\n const task = this.idToDownload.get(newId(rInfo.id, format));\n\n if (task != undefined) {\n task.attach(w, callerId);\n return task.getURL();\n }\n\n const newTask = this.setNewTask(w, rInfo, format, callerId);\n this.downloadQueue.push({\n fn: async () => this.downloadUrl(newTask, callerId),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e),\n });\n\n return newTask.getURL();\n }\n\n /** Downloads and extracts a tar archive if it wasn't downloaded yet. */\n async downloadUrl(task: DownloadAndUnarchiveTask, callerId: string) {\n await task.download();\n // Might be undefined if a error happened\n if (task.getURL()?.url != 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(id: ResourceId, format: ArchiveFormat, callerId: string): Promise<void> {\n const task = this.idToDownload.get(newId(id, format));\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: DownloadAndUnarchiveTask) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed`\n + `from cache along with ${stringifyWithResourceId(toDelete.map((t) => t.info()))}`,\n );\n }),\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted)\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed from cache`,\n );\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.idToDownload.entries()).map(async ([_, task]) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was released when the driver was closed`,\n );\n }),\n );\n }\n\n private setNewTask(w: Watcher, rInfo: DownloadableBlobSnapshot, format: ArchiveFormat, callerId: string) {\n const result = new DownloadAndUnarchiveTask(\n this.logger,\n this.signer,\n this.saveDir,\n this.getFilePath(rInfo.id, format),\n rInfo,\n format,\n this.clientDownload,\n );\n result.attach(w, callerId);\n this.idToDownload.set(newId(rInfo.id, format), result);\n\n return result;\n }\n\n private removeTask(task: DownloadAndUnarchiveTask, reason: string) {\n task.abort(reason);\n task.change.markChanged(`task for ${resourceIdToString(task.rInfo.id)} removed: ${reason}`);\n this.idToDownload.delete(newId(task.rInfo.id, task.format));\n }\n\n private getFilePath(id: ResourceId, format: ArchiveFormat): string {\n return path.join(this.saveDir, `${String(BigInt(id))}_${format}`);\n }\n}\n","import type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { AsyncPoolController, MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { asyncPool, CallersCounter } from '@milaboratories/ts-helpers';\nimport type { ClientProgress, ProgressStatus } from '../clients/progress';\nimport type { ClientUpload } from '../clients/upload';\nimport { MTimeError, NoFileForUploading, UnexpectedEOF } from '../clients/upload';\nimport type { ImportResourceSnapshot } from './types';\nimport { ImportFileHandleUploadData } from './types';\nimport assert from 'node:assert';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\n/** Holds all info needed to upload a file and a status of uploading\n * and indexing. Also, has a method to update a status of the progress.\n * And holds a change source. */\nexport class UploadTask {\n private readonly change: ChangeSource = new ChangeSource();\n private readonly counter: CallersCounter = new CallersCounter();\n private nMaxUploads: number;\n private nPartsWithThisUploadSpeed = 0;\n private nPartsToIncreaseUpload = 10; // how many parts we have to wait to increase concurrency, 50 mb, 10 parts by 5 mb each.\n\n /** If this is upload progress this field will be defined */\n private uploadData?: ImportFileHandleUploadData;\n public progress: sdk.ImportProgress;\n\n /** If failed, then getting a progress is terminally failed. */\n public failed?: boolean;\n\n /** True if the blob was existed.\n * At this case, the task will show progress == 1.0. */\n private alreadyExisted = false;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientBlob: ClientUpload,\n private readonly clientProgress: ClientProgress,\n private readonly maxNConcurrentPartsUpload: number,\n signer: Signer,\n public readonly res: ImportResourceSnapshot,\n ) {\n this.nMaxUploads = this.maxNConcurrentPartsUpload;\n const { uploadData, progress } = newProgress(res, signer);\n this.uploadData = uploadData;\n this.progress = progress;\n }\n\n public getProgress(w: Watcher, callerId: string) {\n this.incCounter(w, callerId);\n\n if (this.failed) {\n this.logger.error(`Uploading terminally failed: ${this.progress.lastError}`);\n throw new Error(this.progress.lastError);\n }\n\n return cloneProgress(this.progress);\n }\n\n public shouldScheduleUpload(): boolean {\n return isMyUpload(this.progress);\n }\n\n /** Uploads a blob if it's not BlobIndex. */\n public async uploadBlobTask() {\n try {\n await uploadBlob(\n this.logger,\n this.clientBlob,\n this.res,\n this.uploadData!,\n this.isComputableDone.bind(this),\n {\n nPartsWithThisUploadSpeed: this.nPartsWithThisUploadSpeed,\n nPartsToIncreaseUpload: this.nPartsToIncreaseUpload,\n currentSpeed: this.nMaxUploads,\n maxSpeed: this.maxNConcurrentPartsUpload,\n },\n );\n this.change.markChanged(`blob upload for ${resourceIdToString(this.res.id)} finished`);\n } catch (e: any) {\n this.setRetriableError(e);\n\n if (isResourceWasDeletedError(e)) {\n this.logger.warn(`resource was deleted while uploading a blob: ${e}`);\n this.change.markChanged(`blob upload for ${resourceIdToString(this.res.id)} aborted, resource was deleted`);\n this.setDone(true);\n\n return;\n }\n\n this.logger.error(`error while uploading a blob: ${e}`);\n this.change.markChanged(`blob upload for ${resourceIdToString(this.res.id)} failed`);\n\n if (nonRecoverableError(e)) {\n this.setTerminalError(e);\n return;\n }\n\n if (isHeadersTimeoutError(e)) {\n // we probably have a slow internet, we need to slow things a bit.\n this.nMaxUploads = decreaseConcurrency(this.logger, this.nMaxUploads, 1);\n }\n\n throw e;\n }\n }\n\n public async updateStatus() {\n try {\n // we do it with timeout in case we have slow internet.\n const status = await this.clientProgress.getStatus(this.res, { timeout: 10000 });\n\n const oldStatus = this.progress.status;\n const newStatus = doneProgressIfExisted(this.alreadyExisted, protoToStatus(status));\n this.progress.status = newStatus;\n this.setDone(status.done);\n\n if (status.done || this.progress.status.progress != oldStatus?.progress) {\n this.change.markChanged(`upload status for ${resourceIdToString(this.res.id)} changed`);\n }\n } catch (e: any) {\n this.setRetriableError(e);\n\n if ((e.name == 'RpcError' && e.code == 'DEADLINE_EXCEEDED') || e?.message?.includes('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(`upload status for ${resourceIdToString(this.res.id)} changed, resource not found`);\n this.setDone(true);\n return;\n }\n\n this.logger.error(`retryable error while updating a status of BlobImport: ${e}`);\n // It was a terminal error, but when a connection drops,\n // this will stop the whole task, so we make it retryable.\n // It was like that:\n // this.change.markChanged();\n // this.setTerminalError(e);\n }\n }\n\n /** Set non-terminal error, that task can be retried. */\n private setRetriableError(e: unknown) {\n this.progress.lastError = String(e);\n }\n\n /** Set a terminal error, the task will throw a error instead of a progress. */\n private setTerminalError(e: unknown) {\n this.progress.lastError = String(e);\n this.progress.done = false;\n this.failed = true;\n }\n\n public setDoneIfOutputSet(res: ImportResourceSnapshot) {\n if (isImportResourceOutputSet(res)) {\n this.setDone(true);\n this.alreadyExisted = true;\n }\n }\n\n private setDone(done: boolean) {\n this.progress.done = done;\n if (done) this.progress.lastError = undefined;\n }\n\n public incCounter(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 private isComputableDone() {\n return this.counter.isZero();\n }\n}\n\n/** Uploads a blob if it's not BlobIndex. */\nexport async function uploadBlob(\n logger: MiLogger,\n clientBlob: ClientUpload,\n res: ResourceInfo,\n uploadData: ImportFileHandleUploadData,\n isDoneFn: () => boolean,\n speed: {\n nPartsWithThisUploadSpeed: number,\n nPartsToIncreaseUpload: number,\n currentSpeed: number,\n maxSpeed: number,\n },\n) {\n assert(isUpload(res), 'the upload operation can be done only for BlobUploads');\n const timeout = 10000; // 10 sec instead of standard 5 sec, things might be slow with a slow connection.\n\n if (isDoneFn()) return;\n const parts = await clientBlob.initUpload(res, { timeout });\n logger.info(\n `started to upload blob ${res.id},`\n + ` parts overall: ${parts.overall}, parts remained: ${parts.toUpload.length},`\n + ` number of concurrent uploads: ${speed.currentSpeed}`,\n );\n\n const partUploadFn = (part: bigint) => async (controller: AsyncPoolController) => {\n if (isDoneFn()) return;\n await clientBlob.partUpload(\n res,\n uploadData.localPath,\n BigInt(uploadData.modificationTime),\n part,\n { timeout }\n );\n logger.info(`uploaded chunk ${part}/${parts.overall} of resource: ${res.id}`);\n\n // if we had a network freeze, it will be increased slowly.\n speed.nPartsWithThisUploadSpeed++;\n if (speed.nPartsWithThisUploadSpeed >= speed.nPartsToIncreaseUpload) {\n speed.nPartsWithThisUploadSpeed = 0;\n speed.currentSpeed = increaseConcurrency(logger, speed.currentSpeed, speed.maxSpeed);\n controller.setConcurrency(speed.currentSpeed);\n }\n };\n\n await asyncPool(speed.currentSpeed, parts.toUpload.map(partUploadFn));\n\n if (isDoneFn()) return;\n await clientBlob.finalize(res, { timeout });\n\n logger.info(`uploading of resource ${res.id} finished.`);\n}\n\nfunction newProgress(res: ImportResourceSnapshot, signer: Signer) {\n let isUploadSignMatch: boolean | undefined;\n let uploadData: ImportFileHandleUploadData | undefined;\n if (isUpload(res)) {\n uploadData = ImportFileHandleUploadData.parse(res.data);\n isUploadSignMatch = isSignMatch(signer, uploadData.localPath, uploadData.pathSignature);\n }\n\n return {\n uploadData: uploadData,\n progress: {\n done: false,\n status: undefined,\n isUpload: isUpload(res),\n isUploadSignMatch: isUploadSignMatch,\n lastError: undefined,\n } satisfies sdk.ImportProgress,\n };\n}\n\n/** Returns true if we need to upload the blob that got from this progress. */\nexport function isMyUpload(p: sdk.ImportProgress): boolean {\n return p.isUpload && (p.isUploadSignMatch ?? false);\n}\n\n/** Creates 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 * We do not use '...' cloning syntax\n * for the compiler to fail here if we change API. */\nfunction cloneProgress(progress: sdk.ImportProgress): sdk.ImportProgress {\n const cloned: sdk.ImportProgress = {\n done: progress.done,\n isUpload: progress.isUpload,\n isUploadSignMatch: progress.isUploadSignMatch,\n lastError: progress.lastError,\n };\n\n if (progress.status)\n cloned.status = {\n progress: progress.status.progress,\n bytesProcessed: progress.status.bytesProcessed,\n bytesTotal: progress.status.bytesTotal,\n };\n\n return progress;\n}\n\nfunction isImportResourceOutputSet(res: ImportResourceSnapshot) {\n return 'blob' in res.fields\n ? res.fields.blob !== undefined\n : res.fields.incarnation !== undefined;\n}\n\nexport function isUpload(res: ResourceInfo) {\n return res.type.name.startsWith('BlobUpload');\n}\n\nexport function 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 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\n/** Special hack: if we didn't even start to upload the blob\n * to backend because the result was already there,\n * the backend does show us a status that nothing were uploaded,\n * but we need to show the client that everything is OK.\n * Thus, here we set progress to be 1.0 and all bytes are become processed. */\nfunction doneProgressIfExisted(alreadyExisted: boolean, status: sdk.ImportStatus) {\n if (alreadyExisted && status.bytesTotal != 0 && status.bytesProcessed == 0) {\n return {\n progress: 1.0,\n bytesProcessed: Number(status.bytesTotal),\n bytesTotal: Number(status.bytesTotal),\n };\n }\n\n return status;\n}\n\nexport function isResourceWasDeletedError(e: any) {\n return (\n e.name == 'RpcError'\n && (e.code == 'NOT_FOUND' || e.code == 'ABORTED' || e.code == 'ALREADY_EXISTS')\n );\n}\n\nexport function nonRecoverableError(e: any) {\n return e instanceof MTimeError || e instanceof UnexpectedEOF || e instanceof NoFileForUploading;\n}\n\nfunction isHeadersTimeoutError(e: any) {\n return (e as Error)?.message.includes(`UND_ERR_HEADERS_TIMEOUT`);\n}\n\n/** It's called for every upload success so if everyone is succeeded, we'll double the concurrency. */\nfunction increaseConcurrency(logger: MiLogger, current: number, max: number): number {\n const newConcurrency = Math.min(current + 2, max);\n if (newConcurrency != current)\n logger.info(`uploadTask.increaseConcurrency: increased from ${current} to ${newConcurrency}`)\n\n return newConcurrency;\n}\n\n/** When a error happens, this will half the concurrency level, so the next time\n * we'll try to upload blobs slower. */\nfunction decreaseConcurrency(logger: MiLogger, current: number, min: number): number {\n const newConcurrency = Math.max(Math.round(current / 2), min);\n if (newConcurrency != current)\n logger.info(`uploadTask.decreaseConcurrency: decreased from ${current} to ${newConcurrency}`)\n\n return newConcurrency;\n}\n","import { randomUUID } from 'node:crypto';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport type {\n Watcher,\n ComputableCtx } from '@milaboratories/computable';\nimport {\n Computable,\n PollingComputableHooks,\n} from '@milaboratories/computable';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { asyncPool, TaskProcessor } from '@milaboratories/ts-helpers';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { ClientProgress } from '../clients/progress';\nimport type { ClientUpload } from '../clients/upload';\nimport type {\n PlTreeEntry,\n PlTreeEntryAccessor,\n PlTreeNodeAccessor,\n} from '@milaboratories/pl-tree';\nimport {\n isPlTreeEntry,\n isPlTreeEntryAccessor,\n makeResourceSnapshot,\n} from '@milaboratories/pl-tree';\nimport { scheduler } from 'node:timers/promises';\nimport type { PollingOps } from './helpers/polling_ops';\nimport type { ImportResourceSnapshot } from './types';\nimport { IndexResourceSnapshot, UploadResourceSnapshot } from './types';\nimport { isMyUpload, nonRecoverableError, UploadTask } from './upload_task';\nimport { WrongResourceTypeError } from './helpers/helpers';\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\n if (node.resourceType.name.startsWith('BlobUpload'))\n return makeResourceSnapshot(node, UploadResourceSnapshot);\n 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, UploadTask> = 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\n return result;\n }\n\n private getProgressIdNoCtx(\n w: Watcher,\n res: ImportResourceSnapshot,\n callerId: string,\n ): sdk.ImportProgress {\n validateResourceType('getProgressId', res.type);\n\n const task = this.idToProgress.get(res.id);\n\n if (task != undefined) {\n task.setDoneIfOutputSet(res);\n return task.getProgress(w, callerId);\n }\n\n const newTask = new UploadTask(\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, newTask);\n\n if (newTask.shouldScheduleUpload()) {\n this.uploadQueue.push({\n fn: () => newTask.uploadBlobTask(),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e),\n });\n }\n\n newTask.setDoneIfOutputSet(res);\n return newTask.getProgress(w, callerId);\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 task = this.idToProgress.get(id);\n if (task === undefined) return;\n\n const deleted = task.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<UploadTask> {\n return Array.from(this.idToProgress.entries())\n .filter(([_, p]) => !isProgressDone(p.progress))\n .map(([_, p]) => p);\n }\n}\n\nfunction isProgressDone(p: sdk.ImportProgress) {\n return p.done && (p.status?.progress ?? 0.0) >= 1.0;\n}\n\ntype ScheduledRefresh = {\n resolve: () => void;\n reject: (err: any) => void;\n};\n\nfunction validateResourceType(methodName: string, rType: ResourceType) {\n if (!rType.name.startsWith('BlobUpload') && !rType.name.startsWith('BlobIndex')) {\n throw new WrongResourceTypeError(\n `${methodName}: wrong resource type: ${rType.name}, `\n + `expected: a resource of either type 'BlobUpload' or 'BlobIndex'.`,\n );\n }\n}\n","import type {\n ComputableCtx,\n Watcher,\n} from '@milaboratories/computable';\nimport {\n ChangeSource,\n Computable,\n PollingComputableHooks,\n} from '@milaboratories/computable';\nimport type {\n ResourceId,\n ResourceType } from '@milaboratories/pl-client';\nimport {\n resourceIdToString,\n stringifyWithResourceId,\n} from '@milaboratories/pl-client';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { asyncPool, CallersCounter } from '@milaboratories/ts-helpers';\nimport type { ClientLogs } from '../clients/logs';\nimport { randomUUID } from 'node:crypto';\nimport type { PlTreeEntry, ResourceInfo } from '@milaboratories/pl-tree';\nimport { treeEntryToResourceInfo } from '@milaboratories/pl-tree';\nimport { scheduler } from 'node:timers/promises';\nimport type { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { PollingOps } from './helpers/polling_ops';\nimport type { RpcError } from '@protobuf-ts/runtime-rpc';\nimport { getResourceInfoFromLogHandle, isLiveLogHandle, newLogHandle } from './helpers/logs_handle';\nimport { WrongResourceTypeError } from './helpers/helpers';\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 validateResourceType('getLastLogs', rInfo.type);\n\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 validateResourceType('getProgressLog', rInfo.type);\n\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 validateResourceType('getLogHandle', rInfo.type);\n\n return newLogHandle(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 getResourceInfoFromLogHandle(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(\n getResourceInfoFromLogHandle(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr,\n ),\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 = new TextDecoder().decode(resp.data);\n if (this.logs != newLogs) this.change.markChanged(`logs for ${resourceIdToString(this.rInfo.id)} updated`);\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\nfunction validateResourceType(methodName: string, rType: ResourceType) {\n if (!rType.name.startsWith('StreamWorkdir')) {\n throw new WrongResourceTypeError(\n `${methodName}: wrong resource type: ${rType.name}, `\n + `expected: a resource of type 'StreamWorkdir'.`,\n );\n }\n}\n","import type { ComputableCtx } from '@milaboratories/computable';\nimport { Computable } from '@milaboratories/computable';\nimport type { PlTreeEntry, ResourceInfo } from '@milaboratories/pl-tree';\nimport type { LogsStreamDriver } from './logs_stream';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport type { DownloadDriver } from './download_blob/download_blob';\nimport { isLiveLogHandle } from './helpers/logs_handle';\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 /** Same as getProgressLog but also returns a liveliness of the log.\n * The previous getProgressLog couldn't be extended.\n * Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLogWithInfo(res: PlTreeEntry, patternToSearch: string): Computable<sdk.ProgressLogWithInfo | undefined>;\n getProgressLogWithInfo(res: PlTreeEntry, patternToSearch: string, ctx: ComputableCtx): sdk.ProgressLogWithInfo | undefined;\n getProgressLogWithInfo(\n res: PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx,\n ): Computable<sdk.ProgressLogWithInfo | undefined> | sdk.ProgressLogWithInfo | undefined {\n if (ctx === undefined)\n return Computable.make((ctx) => this.getProgressLogWithInfo(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)) {\n const log = this.downloadDriver.getProgressLog(stream, patternToSearch, ctx);\n return {\n progressLine: log,\n live: false,\n }\n }\n\n try {\n const log = this.logsStreamDriver.getProgressLog(stream, patternToSearch, ctx);\n return {\n progressLine: log,\n live: true,\n }\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 with info: ${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","import type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport type {\n MiLogger,\n Signer,\n} from '@milaboratories/ts-helpers';\nimport {\n CallersCounter,\n createPathAtomically,\n ensureDirExists,\n fileExists,\n notEmpty,\n} from '@milaboratories/ts-helpers';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Transform, Writable } from 'node:stream';\nimport * as zlib from 'node:zlib';\nimport * as tar from 'tar-fs';\nimport type { RemoteFileDownloader } from '../../helpers/download';\nimport { NetworkError400 } from '../../helpers/download';\nimport type { UrlResult } from './driver';\nimport { newBlockUIURL } from '../urls/url';\n\n/** Downloads and extracts an archive to a directory. */\nexport class DownloadByUrlTask {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n private readonly signalCtl = new AbortController();\n error: string | undefined;\n done = false;\n size = 0;\n\n constructor(\n private readonly logger: MiLogger,\n readonly path: string,\n readonly url: URL,\n readonly signer: Signer,\n readonly saveDir: string,\n ) { }\n\n public info() {\n return {\n url: this.url.toString(),\n path: this.path,\n done: this.done,\n size: this.size,\n error: this.error,\n };\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: RemoteFileDownloader, withGunzip: boolean) {\n try {\n const size = await this.downloadAndUntar(clientDownload, withGunzip, this.signalCtl.signal);\n this.setDone(size);\n this.change.markChanged(`download of ${this.url} finished`);\n } catch (e: unknown) {\n if (e instanceof URLAborted || e instanceof NetworkError400) {\n this.setError(e);\n this.change.markChanged(`download of ${this.url} failed`);\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: RemoteFileDownloader,\n withGunzip: boolean,\n signal: AbortSignal,\n ): Promise<number> {\n await ensureDirExists(path.dirname(this.path));\n\n if (await fileExists(this.path)) {\n return await dirSize(this.path);\n }\n\n const size = await clientDownload.withContent(\n this.url.toString(), \n {}, \n { signal },\n async (content, size) => {\n let processedContent = content;\n if (withGunzip) {\n const gunzip = Transform.toWeb(zlib.createGunzip());\n processedContent = content.pipeThrough(gunzip, { signal });\n }\n\n await createPathAtomically(this.logger, this.path, async (fPath: string) => {\n await fsp.mkdir(fPath); // throws if a directory already exists.\n const untar = Writable.toWeb(tar.extract(fPath));\n await processedContent.pipeTo(untar, { signal });\n });\n\n return size;\n }\n );\n\n return size;\n }\n\n getUrl(): UrlResult | undefined {\n if (this.done) return {\n url: newBlockUIURL(this.signer, this.saveDir, notEmpty(this.path))\n };\n\n if (this.error) return { error: this.error };\n\n return undefined;\n }\n\n private setDone(size: number) {\n this.done = true;\n this.size = size;\n }\n\n private setError(e: any) {\n this.error = String(e);\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new URLAborted(reason));\n }\n}\n\n/** Throws when a downloading aborts. */\nexport class URLAborted extends Error {\n name = 'URLAborted';\n}\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: any) => {\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: any, size: any) => sum + size, 0);\n}\n\n/** Do rm -rf on dir. */\nexport async function rmRFDir(path: string) {\n await fsp.rm(path, { recursive: true, force: true });\n}\n","import type { ComputableCtx, Watcher } from '@milaboratories/computable';\nimport { Computable } from '@milaboratories/computable';\nimport type {\n MiLogger,\n Signer,\n} from '@milaboratories/ts-helpers';\nimport {\n TaskProcessor,\n} from '@milaboratories/ts-helpers';\nimport { createHash, randomUUID } from 'node:crypto';\nimport * as path from 'node:path';\nimport type { Dispatcher } from 'undici';\nimport { RemoteFileDownloader } from '../../helpers/download';\nimport { FilesCache } from '../helpers/files_cache';\nimport { stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type { BlockUIURL, FrontendDriver } from '@milaboratories/pl-model-common';\nimport { isBlockUIURL } from '@milaboratories/pl-model-common';\nimport { getPathForBlockUIURL } from '../urls/url';\nimport { DownloadByUrlTask, rmRFDir } from './task';\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 getUrl(url: URL): Computable<UrlResult | undefined>;\n}\n\nexport interface UrlResult {\n /** Path to the downloadable blob along with the signature and a custom protocol,\n * might be undefined when the error happened. */\n url?: BlockUIURL;\n /** Error that happened when the archive were downloaded. */\n error?: string;\n}\n\nexport type DownloadUrlDriverOps = {\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 /** Whether to gunzip the downloaded archive (it will be untared automatically). */\n withGunzip: boolean;\n\n /** Max number of concurrent downloads while calculating computable states\n * derived from this driver.\n * */\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, FrontendDriver {\n private readonly downloadHelper: RemoteFileDownloader;\n\n private urlToDownload: Map<string, DownloadByUrlTask> = 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<DownloadByUrlTask>;\n\n constructor(\n private readonly logger: MiLogger,\n httpClient: Dispatcher,\n private readonly saveDir: string,\n private readonly signer: Signer,\n private readonly opts: DownloadUrlDriverOps = {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\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 RemoteFileDownloader(httpClient);\n }\n\n /** Use to get a path result inside a computable context */\n getUrl(url: URL, ctx: ComputableCtx): UrlResult | undefined;\n\n /** Returns a Computable that do the work */\n getUrl(url: URL): Computable<UrlResult | undefined>;\n\n /** Returns a computable that returns a custom protocol URL to the downloaded and unarchived path. */\n getUrl(\n url: URL,\n ctx?: ComputableCtx,\n ): Computable<UrlResult | undefined> | UrlResult | undefined {\n // wrap result as computable, if we were not given an existing computable context\n if (ctx === undefined) return Computable.make((c) => this.getUrl(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.getUrlNoCtx(url, ctx.watcher, callerId);\n if (result?.url === 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 getUrlNoCtx(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.getUrl();\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.getUrl();\n }\n\n getPathForBlockUI(url: string): string {\n if (!isBlockUIURL(url)) {\n throw new Error(`getPathForBlockUI: ${url} is invalid`);\n }\n\n return getPathForBlockUIURL(this.signer, url, this.saveDir);\n }\n\n /** Downloads and extracts a tar archive if it wasn't downloaded yet. */\n async downloadUrl(task: DownloadByUrlTask, callerId: string) {\n await task.download(this.downloadHelper, this.opts.withGunzip);\n // Might be undefined if a error happened\n if (task.getUrl()?.url !== 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: DownloadByUrlTask) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed`\n + `from cache along with ${stringifyWithResourceId(toDelete.map((t) => t.info()))}`,\n );\n }),\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted)\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed from cache`,\n );\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(\n task,\n `the task ${stringifyWithResourceId(task.info())} was released when the driver was closed`,\n );\n }),\n );\n }\n\n private setNewTask(w: Watcher, url: URL, callerId: string) {\n const result = new DownloadByUrlTask(\n this.logger,\n this.getFilePath(url),\n url,\n this.signer,\n this.saveDir,\n );\n result.attach(w, callerId);\n this.urlToDownload.set(url.toString(), result);\n\n return result;\n }\n\n private removeTask(task: DownloadByUrlTask, reason: string) {\n task.abort(reason);\n task.change.markChanged(`task for url ${task.url} removed: ${reason}`);\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","import type * as sdk from '@milaboratories/pl-model-common';\nimport type { Signer } from '@milaboratories/ts-helpers';\nimport { ImportFileHandleIndexData, ImportFileHandleUploadData } from '../types';\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","import type * as sdk from '@milaboratories/pl-model-common';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { bigintToResourceId } 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 type { 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 type { PlClient, ResourceData, ResourceId } from '@milaboratories/pl-client';\nimport { isNotNullResourceId } from '@milaboratories/pl-client';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type {\n LocalImportFileHandle,\n LsEntry,\n OpenDialogOps,\n OpenMultipleFilesResponse,\n OpenSingleFileResponse,\n TableRange,\n} from '@milaboratories/pl-model-common';\nimport {\n isImportFileHandleIndex,\n} from '@milaboratories/pl-model-common';\nimport type { 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_remote_import_handle';\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle,\n} from './helpers/ls_storage_entry';\nimport type { LocalStorageProjection, VirtualLocalStorageSpec } from './types';\nimport { validateAbsolute } from '../helpers/validate';\nimport { DefaultVirtualLocalStorages } from './virtual_storages';\nimport { createLsFilesClient } from '../clients/constructors';\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 listRemoteFilesWithAdditionalInfo(storage: sdk.StorageHandle, fullPath: string): Promise<ListRemoteFilesResultWithAdditionalInfo>;\n}\n\nexport type ListRemoteFilesResultWithAdditionalInfo = {\n parent?: string;\n entries: LsEntryWithAdditionalInfo[];\n};\n\nexport type LsEntryWithAdditionalInfo = LsEntry & {\n size: number;\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 }\n\n if (path.sep === '/' && fullPath === '') fullPath = '/';\n\n if (storageData.rootPath === '') {\n validateAbsolute(fullPath);\n }\n const lsRoot = path.isAbsolute(fullPath) ? fullPath : 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 public async listRemoteFilesWithAdditionalInfo(\n storageHandle: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithAdditionalInfo> {\n const storageData = parseStorageHandle(storageHandle);\n if (!storageData.isRemote) {\n throw new Error(`Storage ${storageData.name} is not remote`);\n }\n\n const response = await this.lsClient.list(storageData, fullPath);\n\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 size: Number(e.size),\n })),\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","end","fieldNo","wireType","u","UnknownFieldHandler","writer","uploadapi_Init$Type","uploadapi_Init_Request$Type","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","grpcClientProviderFactory","httpClient","_","logger","transport","id","type","init","path","expectedMTimeUnix","partNumber","info","chunk","readFileChunk","checkExpectedMTime","rawBody","statusCode","headers","request","name","body","checkStatusCodeOk","partsCount","uploadedParts","toUpload","uploaded","addRTypeToMetadata","uploadedPartSize","bytesProcessed","chunkStart","chunkEnd","f","fs","len","pos","b","bytesRead","readBytesFromPosition","position","bytesReadTotal","mTime","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","NetworkError400","RemoteFileDownloader","url","reqHeaders","ops","handler","responseHeaders","webBody","Readable","handlerSuccess","size","result","error","beginning","validateAbsolute","p","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","ClientDownload","localProjections","ConcurrencyLimitingExecutor","newLocalStorageIdsToRoot","downloadUrl","remoteHeaders","stringifyWithResourceId","isLocal","storageId","relativePath","parseLocalUrl","fullPath","getFullPath","readOps","_a","_b","stream","stat","fsp","webStream","signal","withAbort","parsed","WrongLocalFileUrl","localStorageIdsToRoot","root","UnknownStorageError","storageProtocol","projections","idToRoot","lp","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","fileReadLimiter","readFileContent","range","buffer","localHandleRegex","newLocalHandle","signer","isLocalBlobHandle","handle","parseLocalHandle","signature","OnDemandBlobResourceSnapshot","rsSchema","getSize","bs","newSize","ImportFileHandleUploadData","ImportFileHandleIndexData","ImportFileHandleData","UploadResourceSnapshot","IndexResourceSnapshot","remoteHandleRegex","newRemoteHandle","content","isRemoteBlobHandle","parseRemoteHandle","resourceType","resourceVersion","resourceId","bigintToResourceId","WrongResourceTypeError","Updater","onUpdate","newLogHandle","live","liveHandleRegex","isLiveLogHandle","readyHandleRegex","isReadyLogHandle","getResourceInfoFromLogHandle","blobKey","pathToKey","fPath","DownloadBlobTask","clientDownload","ChangeSource","CallersCounter","w","callerId","resourceIdToString","nonRecoverableError","ensureDirExists","alreadyExists","fileExists","createPathAtomically","Writable","reason","DownloadAborted","getDownloadedBlobResponse","sizeBytes","FilesCache","softSizeBytes","file","mapGet","freedBytes","mapEntries","created","Ranges","RangeBytes","rangesFilePostfix","rangesFileName","readRangesFile","ranges","CorruptedRangesError","normalizeRanges","writeRangesFile","tempPath","a","mergeRanges","from","to","rangesSize","acc","doesRangeExist","allRanges","r","addRange","createSparseFile","platform","ensureSparseOnWindows","spawnAsync","writeToSparseFile","data","fileHandle","SparseCacheFsRanges","cacheDir","key","SparseCacheFsFile","SparseCache","maxSize","storage","functions","withLock","now","newRanges","byTime","aDate","__","bDate","keyAndDate","lock","cb","DownloadDriver","clientLogs","saveDir","rangesCacheDir","fsRanges","fsStorage","TaskProcessor","driver","res","ctx","Computable","treeEntryToResourceInfo","randomUUID","validateDownloadableResourceType","task","inMemoryTask","newTask","blob","isPlTreeEntry","makeResourceSnapshot","OnDemandBlobHolder","validateRangeBytes","filePath","v","lines","logGetter","newLogGetter","LastLinesGetter","patternToSearch","resp","toDelete","cachedFile","d","blobId","newLogs","getLastLines","nLines","inStream","rl","readline","Denque","line","os","cleanupError","methodName","DownloadableBlobSnapshot","makeDownloadableBlobSnapshot","entryOrAccessor","node","isPlTreeEntryAccessor","newFolderURL","newBlockUIURL","getPathForFolderURL","rootDir","getPath","getPathForBlockUIURL","subfolder","pathname","parseNestedPathNoEscape","baseDir","userInputPath","absolutePath","normalizedBase","DownloadAndUnarchiveTask","format","rmRFDir","dirSize","simpleUntar","tar","gunzip","Transform","zlib","untar","decompress","assertNever","URLAborted","dir","files","sum","newId","DownloadBlobToURLDriver","opts","isFolderURL","c","t","UploadTask","clientBlob","clientProgress","maxNConcurrentPartsUpload","uploadData","progress","newProgress","cloneProgress","isMyUpload","uploadBlob","isResourceWasDeletedError","isHeadersTimeoutError","decreaseConcurrency","oldStatus","newStatus","doneProgressIfExisted","protoToStatus","isImportResourceOutputSet","done","isDoneFn","speed","assert","isUpload","timeout","parts","partUploadFn","part","controller","increaseConcurrency","asyncPool","isUploadSignMatch","isSignMatch","proto","alreadyExisted","current","max","newConcurrency","min","makeBlobImportSnapshot","UploadDriver","PollingComputableHooks","resolve","reject","handleResource","validateResourceType","toNotify","n","scheduler","isProgressDone","LogsStreamDriver","LogGetter","logs","getter","LogsDriver","logsStreamDriver","downloadDriver","streamManagerGetStream","isBlob","manager","DownloadByUrlTask","withGunzip","processedContent","DownloadUrlDriver","isBlockUIURL","sha256","createHash","createIndexImportHandle","storageName","createUploadImportHandle","localPath","modificationTimeSeconds","parseUploadHandle","parseIndexHandle","parseStorageHandle","isRemoteStorageHandle","parseRemoteStorageHandle","isLocalStorageHandle","parseLocalStorageHandle","createLocalStorageHandle","createRemoteStorageHandle","storageType","DefaultVirtualLocalStorages","home","homeDrive","util","exec","drive","isHomeDrive","LsDriver","lsClient","storageIdToResourceId","virtualStoragesMap","localProjectionsMap","openFileDialogCallback","isImportFileHandleIndex","handleData","localProjection","pathWithinStorage","virtualStorages","noRoot","it","storageHandle","storageData","lsRoot","entries","dirent","vp","doGetAvailableStorageIds","tx","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/helpers/download.ts","../src/helpers/validate.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/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/constructors.ts","../src/drivers/helpers/read_file.ts","../src/drivers/helpers/download_local_handle.ts","../src/drivers/types.ts","../src/drivers/helpers/download_remote_handle.ts","../src/drivers/helpers/helpers.ts","../src/drivers/helpers/logs_handle.ts","../src/drivers/download_blob/blob_key.ts","../src/drivers/download_blob/download_blob_task.ts","../src/drivers/helpers/files_cache.ts","../src/drivers/download_blob/sparse_cache/ranges.ts","../src/drivers/download_blob/sparse_cache/file.ts","../src/drivers/download_blob/sparse_cache/cache.ts","../src/drivers/download_blob/download_blob.ts","../src/drivers/download_blob_url/snapshot.ts","../src/drivers/urls/url.ts","../src/drivers/download_blob_url/task.ts","../src/drivers/download_blob_url/driver_id.ts","../src/drivers/download_blob_url/driver.ts","../src/drivers/upload_task.ts","../src/drivers/upload.ts","../src/drivers/logs_stream.ts","../src/drivers/logs.ts","../src/drivers/download_url/task.ts","../src/drivers/download_url/driver.ts","../src/drivers/helpers/ls_remote_import_handle.ts","../src/drivers/helpers/ls_storage_entry.ts","../src/drivers/virtual_storages.ts","../src/drivers/ls.ts"],"sourcesContent":["// @generated by protobuf-ts 2.11.0 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 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 { MessageType } from \"@protobuf-ts/runtime\";\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi\n */\nexport interface uploadapi {\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.Init\n */\nexport interface uploadapi_Init {\n}\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/**\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/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL\n */\nexport interface uploadapi_GetPartURL {\n}\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 * Do we need to presign URL for internal use.\n * Controllers could use this if they are trying to download something from internal network.\n * For backward compatibility, by default pl backend will presign external urls.\n *\n * @generated from protobuf field: bool is_internal_use = 4\n */\n isInternalUse: boolean;\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\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2\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/**\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}\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi): uploadapi {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Init): uploadapi_Init {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Init, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_Init_Request>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Init_Request): uploadapi_Init_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Init_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"parts_count\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"uploaded_parts\", kind: \"scalar\", repeat: 1 /*RepeatType.PACKED*/, T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_Init_Response>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Init_Response): uploadapi_Init_Response {\n let message = target ?? this.create(), 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\n message.uploadedParts.push(reader.uint64().toBigInt());\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Init_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(value?: PartialMessage<uploadapi_UpdateProgress>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_UpdateProgress): uploadapi_UpdateProgress {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_UpdateProgress, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"bytes_processed\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_UpdateProgress_Request>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_UpdateProgress_Request): uploadapi_UpdateProgress_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_UpdateProgress_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Request\n */\nexport const uploadapi_UpdateProgress_Request = 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(\"MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\", []);\n }\n create(value?: PartialMessage<uploadapi_UpdateProgress_Response>): uploadapi_UpdateProgress_Response {\n const message = globalThis.Object.create((this.messagePrototype!));\n if (value !== undefined)\n reflectionMergePartial<uploadapi_UpdateProgress_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_UpdateProgress_Response): uploadapi_UpdateProgress_Response {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_UpdateProgress_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.UpdateProgress.Response\n */\nexport const uploadapi_UpdateProgress_Response = 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL): uploadapi_GetPartURL {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"part_number\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"uploaded_part_size\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 4, name: \"is_internal_use\", kind: \"scalar\", T: 8 /*ScalarType.BOOL*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL_Request>): uploadapi_GetPartURL_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n message.partNumber = 0n;\n message.uploadedPartSize = 0n;\n message.isInternalUse = false;\n if (value !== undefined)\n reflectionMergePartial<uploadapi_GetPartURL_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL_Request): uploadapi_GetPartURL_Request {\n let message = target ?? this.create(), 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 case /* bool is_internal_use */ 4:\n message.isInternalUse = reader.bool();\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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 /* bool is_internal_use = 4; */\n if (message.isInternalUse !== false)\n writer.tag(4, WireType.Varint).bool(message.isInternalUse);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Request\n */\nexport const uploadapi_GetPartURL_Request = 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 { no: 1, name: \"Name\", kind: \"scalar\", jsonName: \"Name\", T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: \"Value\", kind: \"scalar\", jsonName: \"Value\", T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL_HTTPHeader>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL_HTTPHeader): uploadapi_GetPartURL_HTTPHeader {\n let message = target ?? this.create(), 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 /* string 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL_HTTPHeader, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* string Name = 1; */\n if (message.name !== \"\")\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2; */\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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.HTTPHeader\n */\nexport const uploadapi_GetPartURL_HTTPHeader = 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 { no: 3, name: \"headers\", kind: \"message\", repeat: 2 /*RepeatType.UNPACKED*/, T: () => uploadapi_GetPartURL_HTTPHeader },\n { no: 4, name: \"chunk_start\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 5, name: \"chunk_end\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_GetPartURL_Response>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_GetPartURL_Response): uploadapi_GetPartURL_Response {\n let message = target ?? this.create(), 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(uploadapi_GetPartURL_HTTPHeader.internalBinaryRead(reader, reader.uint32(), options));\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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_GetPartURL_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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.internalBinaryWrite(message.headers[i], writer.tag(3, WireType.LengthDelimited).fork(), options).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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.GetPartURL.Response\n */\nexport const uploadapi_GetPartURL_Response = 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Finalize): uploadapi_Finalize {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Finalize, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<uploadapi_Finalize_Request>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Finalize_Request): uploadapi_Finalize_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Finalize_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(value?: PartialMessage<uploadapi_Finalize_Response>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: uploadapi_Finalize_Response): uploadapi_Finalize_Response {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: uploadapi_Finalize_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.uploadapi.Finalize.Response\n */\nexport const uploadapi_Finalize_Response = new uploadapi_Finalize_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Upload\n */\nexport const Upload = new ServiceType(\"MiLaboratories.Controller.Shared.Upload\", [\n { name: \"Init\", options: {}, I: uploadapi_Init_Request, O: uploadapi_Init_Response },\n { name: \"GetPartURL\", options: {}, I: uploadapi_GetPartURL_Request, O: uploadapi_GetPartURL_Response },\n { name: \"UpdateProgress\", options: {}, I: uploadapi_UpdateProgress_Request, O: uploadapi_UpdateProgress_Response },\n { name: \"Finalize\", options: {}, I: uploadapi_Finalize_Request, O: uploadapi_Finalize_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n init(input: uploadapi_Init_Request, options?: RpcOptions): 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\n */\n getPartURL(input: uploadapi_GetPartURL_Request, options?: RpcOptions): 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\n */\n updateProgress(input: uploadapi_UpdateProgress_Request, options?: RpcOptions): UnaryCall<uploadapi_UpdateProgress_Request, uploadapi_UpdateProgress_Response>;\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\n */\n finalize(input: uploadapi_Finalize_Request, options?: RpcOptions): 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 *\n * Init upload, making controller to do all required preparation steps.\n *\n *\n * @generated from protobuf rpc: Init\n */\n init(input: uploadapi_Init_Request, options?: RpcOptions): UnaryCall<uploadapi_Init_Request, uploadapi_Init_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_Init_Request, uploadapi_Init_Response>(\"unary\", this._transport, method, opt, input);\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\n */\n getPartURL(input: uploadapi_GetPartURL_Request, options?: RpcOptions): UnaryCall<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response> {\n const method = this.methods[1], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_GetPartURL_Request, uploadapi_GetPartURL_Response>(\"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\n */\n updateProgress(input: uploadapi_UpdateProgress_Request, options?: RpcOptions): UnaryCall<uploadapi_UpdateProgress_Request, uploadapi_UpdateProgress_Response> {\n const method = this.methods[2], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_UpdateProgress_Request, uploadapi_UpdateProgress_Response>(\"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\n */\n finalize(input: uploadapi_Finalize_Request, options?: RpcOptions): UnaryCall<uploadapi_Finalize_Request, uploadapi_Finalize_Response> {\n const method = this.methods[3], opt = this._transport.mergeOptions(options);\n return stackIntercept<uploadapi_Finalize_Request, uploadapi_Finalize_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","import type { GrpcClientProvider, GrpcClientProviderFactory, PlClient, ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport * as fs from 'node:fs/promises';\nimport type { Dispatcher } from 'undici';\nimport { request } from 'undici';\nimport type { uploadapi_GetPartURL_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol';\nimport { UploadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client';\n\nimport type { IncomingHttpHeaders } from 'undici/types/header';\n\nexport class MTimeError extends Error {\n name = 'MTimeError';\n}\n\nexport class UnexpectedEOF extends Error {\n name = 'UnexpectedEOF';\n}\n\nexport class NetworkError extends Error {\n name = 'NetworkError';\n}\n\n/** Happens when the file doesn't exist */\nexport class NoFileForUploading extends Error {\n name = 'NoFileForUploading';\n}\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: GrpcClientProvider<UploadClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n public readonly httpClient: Dispatcher,\n _: PlClient,\n public readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new UploadClient(transport));\n }\n\n close() {}\n\n public async initUpload(\n { id, type }: ResourceInfo,\n options?: RpcOptions,\n ): Promise<{\n overall: bigint;\n toUpload: bigint[];\n }> {\n const init = await this.grpcInit(id, type, options);\n return {\n overall: init.partsCount,\n toUpload: this.partsToUpload(init.partsCount, init.uploadedParts),\n };\n }\n\n public async partUpload(\n { id, type }: ResourceInfo,\n path: string,\n expectedMTimeUnix: bigint,\n partNumber: bigint,\n options?: RpcOptions,\n ) {\n const info = await this.grpcGetPartUrl(\n { id, type },\n partNumber,\n 0n, // we update progress as a separate call later.\n options,\n );\n\n const chunk = await readFileChunk(path, info.chunkStart, info.chunkEnd);\n await checkExpectedMTime(path, expectedMTimeUnix);\n\n const contentLength = Number(info.chunkEnd - info.chunkStart);\n if (chunk.length !== contentLength) {\n throw new Error(\n `Chunk size mismatch: expected ${contentLength} bytes, but read ${chunk.length} bytes from file`,\n );\n }\n\n const headers = Object.fromEntries(info.headers.map(({ name, value }) => [name, value]));\n\n const contentLengthKey = Object.keys(headers).find((key) => key.toLowerCase() === 'content-length');\n if (contentLengthKey) {\n const existingContentLength = Number(headers[contentLengthKey]);\n if (existingContentLength !== contentLength) {\n throw new Error(\n `Content-Length mismatch: expected ${contentLength}, but got ${existingContentLength} in headers`,\n );\n }\n }\n\n // content length will be automatically added by undici, so we don't need to set it here\n\n try {\n const {\n body: rawBody,\n statusCode,\n headers: responseHeaders,\n } = await request(info.uploadUrl, {\n dispatcher: this.httpClient,\n body: chunk,\n // We got headers only after we send\n // the whole body (in case of S3 PUT requests it's 5 MB).\n // It might be slow with a slow connection (or with SSH),\n // that's why we got big timeout here.\n headersTimeout: 60000,\n bodyTimeout: 60000,\n // Prevent connection reuse by setting \"Connection: close\" header.\n // This works around an issue with the backend's built-in S3 implementation\n // that caused HTTP/1.1 protocol lines to be included in the uploaded file content.\n reset: true,\n headers,\n method: info.method.toUpperCase() as Dispatcher.HttpMethod,\n });\n\n // always read the body for resources to be garbage collected.\n const body = await rawBody.text();\n checkStatusCodeOk(statusCode, body, responseHeaders, info);\n } catch (e: unknown) {\n if (e instanceof NetworkError)\n throw e;\n\n throw new Error(`partUpload: error ${JSON.stringify(e)} happened while trying to do part upload to the url ${info.uploadUrl}, headers: ${JSON.stringify(info.headers)}`);\n }\n\n await this.grpcUpdateProgress({ id, type }, BigInt(info.chunkEnd - info.chunkStart), options);\n }\n\n public async finalize(info: ResourceInfo, options?: RpcOptions) {\n return await this.grpcFinalize(info, options);\n }\n\n /** Calculates parts that need to be uploaded from the parts that were\n * already uploaded. */\n private partsToUpload(partsCount: bigint, uploadedParts: bigint[]): bigint[] {\n const toUpload: bigint[] = [];\n const uploaded = new Set(uploadedParts);\n\n for (let i = 1n; i <= partsCount; i++) {\n if (!uploaded.has(i)) toUpload.push(i);\n }\n\n return toUpload;\n }\n\n private async grpcInit(id: ResourceId, type: ResourceType, options?: RpcOptions) {\n return await this.grpcClient.get().init({ resourceId: id }, addRTypeToMetadata(type, options))\n .response;\n }\n\n private async grpcGetPartUrl(\n { id, type }: ResourceInfo,\n partNumber: bigint,\n uploadedPartSize: bigint,\n options?: RpcOptions,\n ) {\n return await this.grpcClient.get().getPartURL(\n { resourceId: id, partNumber, uploadedPartSize, isInternalUse: false },\n addRTypeToMetadata(type, options),\n ).response;\n }\n\n private async grpcUpdateProgress(\n { id, type }: ResourceInfo,\n bytesProcessed: bigint,\n options?: RpcOptions,\n ) {\n await this.grpcClient.get().updateProgress(\n {\n resourceId: id,\n bytesProcessed,\n },\n addRTypeToMetadata(type, options),\n ).response;\n }\n\n private async grpcFinalize({ id, type }: ResourceInfo, options?: RpcOptions) {\n return await this.grpcClient.get().finalize({ resourceId: id }, addRTypeToMetadata(type, options))\n .response;\n }\n}\n\nasync function readFileChunk(path: string, chunkStart: bigint, chunkEnd: bigint): Promise<Buffer> {\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 readBytesFromPosition(f, b, len, pos);\n\n return b.subarray(0, bytesRead);\n } catch (e: unknown) {\n if (e && typeof e === 'object' && ('code' in e) && e.code == 'ENOENT') throw new NoFileForUploading(`there is no file ${path} for uploading`);\n throw e;\n } finally {\n await f?.close();\n }\n}\n\n/** Read len bytes from a given position.\n * Without this, `FileHandle.read` can read less bytes than needed. */\nasync function 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\nasync function checkExpectedMTime(path: string, expectedMTimeUnix: bigint) {\n const mTime = BigInt(Math.floor((await fs.stat(path)).mtimeMs / 1000));\n if (mTime > expectedMTimeUnix) {\n throw new MTimeError(`file was modified, expected mtime: ${expectedMTimeUnix}, got: ${mTime}.`);\n }\n}\n\nfunction checkStatusCodeOk(\n statusCode: number,\n body: string,\n headers: IncomingHttpHeaders,\n info: uploadapi_GetPartURL_Response,\n) {\n if (statusCode != 200) {\n throw new NetworkError(\n `response is not ok, status code: ${statusCode},`\n + ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`,\n );\n }\n}\n","// @generated by protobuf-ts 2.11.0 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 * @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 { no: 1, name: \"seconds\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\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)\n 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(json: JsonValue, options: JsonReadOptions, target?: Duration): Duration {\n if (typeof json !== \"string\")\n throw new Error(\"Unable to parse Duration from JSON \" + typeofJsonValue(json) + \". Expected string.\");\n let match = json.match(/^(-?)([0-9]+)(?:\\.([0-9]+))?s/);\n if (match === null)\n throw new Error(\"Unable to parse Duration from JSON string. Invalid format.\");\n if (!target)\n target = this.create();\n let [, sign, secs, nanos] = match;\n let longSeconds = PbLong.from(sign + secs);\n if (longSeconds.toNumber() > 315576000000 || longSeconds.toNumber() < -315576000000)\n throw new Error(\"Unable to parse Duration from JSON string. Value out of range.\");\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Duration): Duration {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: Duration, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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.11.0 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 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 { 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/**\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/**\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/**\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI): ProgressAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 2, name: \"bytes_processed\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"bytes_total\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_Report): ProgressAPI_Report {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_Report, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_GetStatus): ProgressAPI_GetStatus {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_GetStatus, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_GetStatus_Request>): ProgressAPI_GetStatus_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_GetStatus_Request): ProgressAPI_GetStatus_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_GetStatus_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Request\n */\nexport const ProgressAPI_GetStatus_Request = 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(value?: PartialMessage<ProgressAPI_GetStatus_Response>): ProgressAPI_GetStatus_Response {\n const message = globalThis.Object.create((this.messagePrototype!));\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_GetStatus_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_GetStatus_Response): ProgressAPI_GetStatus_Response {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.report);\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_GetStatus_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(message.report, writer.tag(1, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.GetStatus.Response\n */\nexport const ProgressAPI_GetStatus_Response = 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(value?: PartialMessage<ProgressAPI_RealtimeStatus>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_RealtimeStatus): ProgressAPI_RealtimeStatus {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_RealtimeStatus, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(\"MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\", [\n { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"update_interval\", kind: \"message\", T: () => Duration }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_RealtimeStatus_Request>): ProgressAPI_RealtimeStatus_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_RealtimeStatus_Request): ProgressAPI_RealtimeStatus_Request {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.updateInterval);\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_RealtimeStatus_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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(message.updateInterval, writer.tag(2, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Request\n */\nexport const ProgressAPI_RealtimeStatus_Request = 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(\"MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\", [\n { no: 1, name: \"report\", kind: \"message\", T: () => ProgressAPI_Report }\n ]);\n }\n create(value?: PartialMessage<ProgressAPI_RealtimeStatus_Response>): ProgressAPI_RealtimeStatus_Response {\n const message = globalThis.Object.create((this.messagePrototype!));\n if (value !== undefined)\n reflectionMergePartial<ProgressAPI_RealtimeStatus_Response>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ProgressAPI_RealtimeStatus_Response): ProgressAPI_RealtimeStatus_Response {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.report);\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: ProgressAPI_RealtimeStatus_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* MiLaboratories.Controller.Shared.ProgressAPI.Report report = 1; */\n if (message.report)\n ProgressAPI_Report.internalBinaryWrite(message.report, writer.tag(1, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.ProgressAPI.RealtimeStatus.Response\n */\nexport const ProgressAPI_RealtimeStatus_Response = new ProgressAPI_RealtimeStatus_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Progress\n */\nexport const Progress = new ServiceType(\"MiLaboratories.Controller.Shared.Progress\", [\n { name: \"GetStatus\", options: { \"google.api.http\": { get: \"/resources/{resource_id}/get-progress\" } }, I: ProgressAPI_GetStatus_Request, O: ProgressAPI_GetStatus_Response },\n { name: \"RealtimeStatus\", serverStreaming: true, options: {}, I: ProgressAPI_RealtimeStatus_Request, O: ProgressAPI_RealtimeStatus_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n getStatus(input: ProgressAPI_GetStatus_Request, options?: RpcOptions): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response>;\n /**\n * @generated from protobuf rpc: RealtimeStatus\n */\n realtimeStatus(input: ProgressAPI_RealtimeStatus_Request, options?: RpcOptions): ServerStreamingCall<ProgressAPI_RealtimeStatus_Request, ProgressAPI_RealtimeStatus_Response>;\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 /**\n * @generated from protobuf rpc: GetStatus\n */\n getStatus(input: ProgressAPI_GetStatus_Request, options?: RpcOptions): UnaryCall<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<ProgressAPI_GetStatus_Request, ProgressAPI_GetStatus_Response>(\"unary\", this._transport, method, opt, input);\n }\n /**\n * @generated from protobuf rpc: RealtimeStatus\n */\n realtimeStatus(input: ProgressAPI_RealtimeStatus_Request, options?: RpcOptions): ServerStreamingCall<ProgressAPI_RealtimeStatus_Request, ProgressAPI_RealtimeStatus_Response> {\n const method = this.methods[1], opt = this._transport.mergeOptions(options);\n return stackIntercept<ProgressAPI_RealtimeStatus_Request, ProgressAPI_RealtimeStatus_Response>(\"serverStreaming\", this._transport, method, opt, input);\n }\n}\n","import { ProgressClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport { Duration } from '../proto/google/protobuf/duration';\nimport type { GrpcClientProvider, GrpcClientProviderFactory, PlClient } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport type { Dispatcher } from 'undici';\nimport type { 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: GrpcClientProvider<ProgressClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n _: Dispatcher,\n public readonly client: PlClient,\n public readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new ProgressClient(transport));\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.get().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.get().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' + String(e));\n throw e;\n }\n }\n}\n","// @TODO Gleb Zakharov\n/* eslint-disable n/no-unsupported-features/node-builtins */\nimport type { Dispatcher } from 'undici';\nimport { request } from 'undici';\nimport { Readable } from 'node:stream';\nimport type { ReadableStream } from 'node:stream/web';\nimport { text } from 'node:stream/consumers';\nimport type { RangeBytes } from '@milaboratories/pl-model-common';\n\nexport interface DownloadOps {\n signal?: AbortSignal;\n range?: RangeBytes;\n}\n\nexport type ContentHandler<T> = (content: ReadableStream, size: number) => Promise<T>;\n\n/** Throws when a status code of the downloading URL was in range [400, 500). */\nexport class NetworkError400 extends Error {\n name = 'NetworkError400';\n}\n\nexport class RemoteFileDownloader {\n constructor(public readonly httpClient: Dispatcher) {}\n\n async withContent<T>(\n url: string,\n reqHeaders: Record<string, string>,\n ops: DownloadOps,\n handler: ContentHandler<T>,\n ): Promise<T> {\n const headers = { ...reqHeaders };\n\n // Add range header if specified\n if (ops.range) {\n headers['Range'] = `bytes=${ops.range.from}-${ops.range.to - 1}`;\n }\n\n const { statusCode, body, headers: responseHeaders } = await request(url, {\n dispatcher: this.httpClient,\n headers,\n signal: ops.signal,\n });\n\n const webBody = Readable.toWeb(body);\n let handlerSuccess = false;\n\n try {\n await checkStatusCodeOk(statusCode, webBody, url);\n const size = Number(responseHeaders['content-length']);\n const result = await handler(webBody, size);\n handlerSuccess = true;\n return result;\n } catch (error) {\n // Cleanup on error (including handler errors)\n if (!handlerSuccess && !webBody.locked) {\n try {\n await webBody.cancel();\n } catch {\n // Ignore cleanup errors\n }\n }\n throw error;\n }\n }\n}\n\nasync function checkStatusCodeOk(statusCode: number, webBody: ReadableStream, url: string) {\n if (statusCode != 200 && statusCode != 206 /* partial content from range request */) {\n const beginning = (await text(webBody)).substring(0, 1000);\n\n if (400 <= statusCode && statusCode < 500) {\n throw new NetworkError400(\n `Http error: statusCode: ${statusCode} `\n + `url: ${url.toString()}, beginning of body: ${beginning}`);\n }\n\n throw new Error(`Http error: statusCode: ${statusCode} url: ${url.toString()}`);\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","// @generated by protobuf-ts 2.11.0 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 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 { MessageType } from \"@protobuf-ts/runtime\";\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI\n */\nexport interface DownloadAPI {\n}\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL\n */\nexport interface DownloadAPI_GetDownloadURL {\n}\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 * Pass `true` here if the blob will be downloaded from internal network,\n * e.g. controllers could use this if they are trying to download something from internal network.\n * For backward compatibility, by default pl treats all requests as from external network.\n *\n * @generated from protobuf field: bool is_internal_use = 2\n */\n isInternalUse: boolean;\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\n */\n name: string;\n /**\n * @generated from protobuf field: string Value = 2\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI): DownloadAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(value?: PartialMessage<DownloadAPI_GetDownloadURL>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL): DownloadAPI_GetDownloadURL {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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(\"MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\", [\n { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"is_internal_use\", kind: \"scalar\", T: 8 /*ScalarType.BOOL*/ }\n ]);\n }\n create(value?: PartialMessage<DownloadAPI_GetDownloadURL_Request>): DownloadAPI_GetDownloadURL_Request {\n const message = globalThis.Object.create((this.messagePrototype!));\n message.resourceId = 0n;\n message.isInternalUse = false;\n if (value !== undefined)\n reflectionMergePartial<DownloadAPI_GetDownloadURL_Request>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL_Request): DownloadAPI_GetDownloadURL_Request {\n let message = target ?? this.create(), 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 /* bool is_internal_use */ 2:\n message.isInternalUse = reader.bool();\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL_Request, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* uint64 resource_id = 1; */\n if (message.resourceId !== 0n)\n writer.tag(1, WireType.Varint).uint64(message.resourceId);\n /* bool is_internal_use = 2; */\n if (message.isInternalUse !== false)\n writer.tag(2, WireType.Varint).bool(message.isInternalUse);\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Request\n */\nexport const DownloadAPI_GetDownloadURL_Request = 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(\"MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\", [\n { no: 1, name: \"Name\", kind: \"scalar\", jsonName: \"Name\", T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: \"Value\", kind: \"scalar\", jsonName: \"Value\", T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<DownloadAPI_GetDownloadURL_HTTPHeader>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL_HTTPHeader): DownloadAPI_GetDownloadURL_HTTPHeader {\n let message = target ?? this.create(), 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 /* string 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL_HTTPHeader, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* string Name = 1; */\n if (message.name !== \"\")\n writer.tag(1, WireType.LengthDelimited).string(message.name);\n /* string Value = 2; */\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)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.HTTPHeader\n */\nexport const DownloadAPI_GetDownloadURL_HTTPHeader = 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(\"MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\", [\n { no: 1, name: \"download_url\", kind: \"scalar\", T: 9 /*ScalarType.STRING*/ },\n { no: 2, name: \"headers\", kind: \"message\", repeat: 2 /*RepeatType.UNPACKED*/, T: () => DownloadAPI_GetDownloadURL_HTTPHeader }\n ]);\n }\n create(value?: PartialMessage<DownloadAPI_GetDownloadURL_Response>): 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>(this, message, value);\n return message;\n }\n internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: DownloadAPI_GetDownloadURL_Response): DownloadAPI_GetDownloadURL_Response {\n let message = target ?? this.create(), 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(DownloadAPI_GetDownloadURL_HTTPHeader.internalBinaryRead(reader, reader.uint32(), options));\n break;\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: DownloadAPI_GetDownloadURL_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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(message.headers[i], writer.tag(2, WireType.LengthDelimited).fork(), options).join();\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\n return writer;\n }\n}\n/**\n * @generated MessageType for protobuf message MiLaboratories.Controller.Shared.DownloadAPI.GetDownloadURL.Response\n */\nexport const DownloadAPI_GetDownloadURL_Response = new DownloadAPI_GetDownloadURL_Response$Type();\n/**\n * @generated ServiceType for protobuf service MiLaboratories.Controller.Shared.Download\n */\nexport const Download = new ServiceType(\"MiLaboratories.Controller.Shared.Download\", [\n { name: \"GetDownloadURL\", options: { \"google.api.http\": { get: \"/resources/{resource_id}/get-download-url\" } }, I: DownloadAPI_GetDownloadURL_Request, O: DownloadAPI_GetDownloadURL_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n getDownloadURL(input: DownloadAPI_GetDownloadURL_Request, options?: RpcOptions): UnaryCall<DownloadAPI_GetDownloadURL_Request, DownloadAPI_GetDownloadURL_Response>;\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 /**\n * @generated from protobuf rpc: GetDownloadURL\n */\n getDownloadURL(input: DownloadAPI_GetDownloadURL_Request, options?: RpcOptions): UnaryCall<DownloadAPI_GetDownloadURL_Request, DownloadAPI_GetDownloadURL_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<DownloadAPI_GetDownloadURL_Request, DownloadAPI_GetDownloadURL_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","/* eslint-disable n/no-unsupported-features/node-builtins */\nimport type { GrpcClientProvider, GrpcClientProviderFactory } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { ConcurrencyLimitingExecutor } from '@milaboratories/ts-helpers';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Readable } from 'node:stream';\nimport type { Dispatcher } from 'undici';\nimport type { LocalStorageProjection } from '../drivers/types';\nimport type { DownloadOps, ContentHandler } from '../helpers/download';\nimport { RemoteFileDownloader } from '../helpers/download';\nimport { validateAbsolute } from '../helpers/validate';\nimport type { DownloadAPI_GetDownloadURL_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol';\nimport { DownloadClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client';\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: GrpcClientProvider<DownloadClient>;\n private readonly remoteFileDownloader: RemoteFileDownloader;\n\n /** Helps to find a storage root directory by a storage id from URL scheme. */\n private readonly localStorageIdsToRoot: Map<string, string>;\n\n /** Concurrency limiter for local file reads - limit to 32 parallel reads */\n private readonly localFileReadLimiter = new ConcurrencyLimitingExecutor(32);\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger,\n /** Pl storages available locally */\n localProjections: LocalStorageProjection[],\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new DownloadClient(transport));\n this.remoteFileDownloader = new RemoteFileDownloader(httpClient);\n this.localStorageIdsToRoot = newLocalStorageIdsToRoot(localProjections);\n }\n\n close() {}\n\n /**\n * Gets a presign URL and downloads the file.\n * An optional range with 2 numbers from what byte and to what byte to download can be provided.\n * @param fromBytes - from byte including this byte\n * @param toBytes - to byte excluding this byte\n */\n async withBlobContent<T>(\n info: ResourceInfo,\n options: RpcOptions | undefined,\n ops: DownloadOps,\n handler: ContentHandler<T>,\n ): Promise<T> {\n const { downloadUrl, headers } = await this.grpcGetDownloadUrl(info, options, ops.signal);\n\n const remoteHeaders = Object.fromEntries(headers.map(({ name, value }) => [name, value]));\n this.logger.info(`download blob ${stringifyWithResourceId(info)} from url ${downloadUrl}, ops: ${JSON.stringify(ops)}`);\n\n return isLocal(downloadUrl)\n ? await this.withLocalFileContent(downloadUrl, ops, handler)\n : await this.remoteFileDownloader.withContent(downloadUrl, remoteHeaders, ops, handler);\n }\n\n async withLocalFileContent<T>(\n url: string,\n ops: DownloadOps,\n handler: ContentHandler<T>,\n ): Promise<T> {\n const { storageId, relativePath } = parseLocalUrl(url);\n const fullPath = getFullPath(storageId, this.localStorageIdsToRoot, relativePath);\n\n return await this.localFileReadLimiter.run(async () => {\n const readOps = {\n start: ops.range?.from,\n end: ops.range?.to !== undefined ? ops.range.to - 1 : undefined,\n };\n let stream: fs.ReadStream | undefined;\n let handlerSuccess = false;\n\n try {\n const stat = await fsp.stat(fullPath);\n stream = fs.createReadStream(fullPath, readOps);\n const webStream = Readable.toWeb(stream);\n\n const result = await handler(webStream, stat.size);\n handlerSuccess = true;\n return result;\n } catch (error) {\n // Cleanup on error (including handler errors)\n if (!handlerSuccess && stream && !stream.destroyed) {\n stream.destroy();\n }\n throw error;\n }\n });\n }\n\n private async grpcGetDownloadUrl(\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.get().getDownloadURL(\n { resourceId: id, isInternalUse: false },\n addRTypeToMetadata(type, withAbort),\n ).response;\n }\n}\n\nexport function parseLocalUrl(url: 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 return {\n storageId: parsed.host,\n relativePath: decodeURIComponent(parsed.pathname.slice(1)),\n };\n}\n\nexport function getFullPath(\n storageId: string,\n localStorageIdsToRoot: Map<string, string>,\n relativePath: string,\n) {\n const root = localStorageIdsToRoot.get(storageId);\n if (root === undefined) throw new UnknownStorageError(`Unknown storage location: ${storageId}`);\n\n if (root === '') return relativePath;\n\n return path.join(root, relativePath);\n}\n\nconst storageProtocol = 'storage://';\nfunction isLocal(url: string) {\n return url.startsWith(storageProtocol);\n}\n\n/** Throws when a local URL have invalid scheme. */\nexport class WrongLocalFileUrl extends Error {\n name = 'WrongLocalFileUrl';\n}\n\n/** Happens when a storage for a local file can't be found. */\nexport class UnknownStorageError extends Error {\n name = 'UnknownStorageError';\n}\n\nexport function newLocalStorageIdsToRoot(projections: LocalStorageProjection[]) {\n const idToRoot: Map<string, string> = new Map();\n for (const lp of projections) {\n // Empty string means no prefix, i.e. any file on this machine can be got from the storage.\n if (lp.localPath !== '') {\n validateAbsolute(lp.localPath);\n }\n idToRoot.set(lp.storageId, lp.localPath);\n }\n\n return idToRoot;\n}\n","// @generated by protobuf-ts 2.11.0 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 * 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 * 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://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()\n * ) to obtain a formatter capable of generating timestamps in this format.\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 { no: 1, name: \"seconds\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\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(PbLong.from(message.seconds).toNumber() * 1000 + Math.ceil(message.nanos / 1000000));\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) + (ms < 0 && ms % 1000 !== 0 ? 1000 : 0)) * 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 (ms < Date.parse(\"0001-01-01T00:00:00Z\") || ms > Date.parse(\"9999-12-31T23:59:59Z\"))\n throw new Error(\"Unable to encode Timestamp to JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.\");\n if (message.nanos < 0)\n throw new Error(\"Unable to encode invalid Timestamp to JSON. Nanos must not be negative.\");\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\n 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(json: JsonValue, options: JsonReadOptions, target?: Timestamp): Timestamp {\n if (typeof json !== \"string\")\n throw new Error(\"Unable to parse Timestamp from JSON \" + typeofJsonValue(json) + \".\");\n let matches = json.match(/^([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 if (!matches)\n throw new Error(\"Unable to parse Timestamp from JSON. Invalid format.\");\n let ms = Date.parse(matches[1] + \"-\" + matches[2] + \"-\" + matches[3] + \"T\" + matches[4] + \":\" + matches[5] + \":\" + matches[6] + (matches[8] ? matches[8] : \"Z\"));\n if (Number.isNaN(ms))\n throw new Error(\"Unable to parse Timestamp from JSON. Invalid value.\");\n if (ms < Date.parse(\"0001-01-01T00:00:00Z\") || ms > Date.parse(\"9999-12-31T23:59:59Z\"))\n throw new globalThis.Error(\"Unable to parse Timestamp from JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.\");\n if (!target)\n target = this.create();\n target.seconds = PbLong.from(ms / 1000).toBigInt();\n target.nanos = 0;\n if (matches[7])\n target.nanos = (parseInt(\"1\" + matches[7] + \"0\".repeat(9 - matches[7].length)) - 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Timestamp): Timestamp {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: Timestamp, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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.11.0 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 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 { 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/**\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/**\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI): LsAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 2, name: \"size\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_ListItem): LsAPI_ListItem {\n let message = target ?? this.create(), 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(reader, reader.uint32(), options, message.lastModified);\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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_ListItem, writer: IBinaryWriter, options: BinaryWriteOptions): 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(message.lastModified, writer.tag(12, WireType.LengthDelimited).fork(), options).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)(this.typeName, message, writer);\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_List): LsAPI_List {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_List, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_List_Request): LsAPI_List_Request {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_List_Request, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"items\", kind: \"message\", repeat: 2 /*RepeatType.UNPACKED*/, T: () => LsAPI_ListItem },\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: LsAPI_List_Response): LsAPI_List_Response {\n let message = target ?? this.create(), 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(LsAPI_ListItem.internalBinaryRead(reader, reader.uint32(), options));\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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: LsAPI_List_Response, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n /* repeated MiLaboratories.Controller.Shared.LsAPI.ListItem items = 1; */\n for (let i = 0; i < message.items.length; i++)\n LsAPI_ListItem.internalBinaryWrite(message.items[i], writer.tag(1, WireType.LengthDelimited).fork(), options).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)(this.typeName, message, writer);\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.11.0 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\n */\n list(input: LsAPI_List_Request, options?: RpcOptions): 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 /**\n * @generated from protobuf rpc: List\n */\n list(input: LsAPI_List_Request, options?: RpcOptions): UnaryCall<LsAPI_List_Request, LsAPI_List_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<LsAPI_List_Request, LsAPI_List_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","import type { 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 type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport type { GrpcClientProvider, GrpcClientProviderFactory } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLs {\n private readonly grpcClient: GrpcClientProvider<LSClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n private readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new LSClient(transport));\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.get().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.11.0 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 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 { MessageType } from \"@protobuf-ts/runtime\";\n/**\n * @generated from protobuf message MiLaboratories.Controller.Shared.StreamingAPI\n */\nexport interface StreamingAPI {\n}\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI): StreamingAPI {\n let message = target ?? this.create(), end = reader.pos + length;\n while (reader.pos < end) {\n let [fieldNo, wireType] = reader.tag();\n switch (fieldNo) {\n default:\n let u = options.readUnknownField;\n if (u === \"throw\")\n throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {\n let u = options.writeUnknownFields;\n if (u !== false)\n (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 11, name: \"chunk_size\", kind: \"scalar\", opt: true, T: 13 /*ScalarType.UINT32*/ },\n { no: 20, name: \"read_limit\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_StreamBinary>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_StreamBinary): StreamingAPI_StreamBinary {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_StreamBinary, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 11, name: \"chunk_size\", kind: \"scalar\", opt: true, T: 13 /*ScalarType.UINT32*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_ReadBinary>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_ReadBinary): StreamingAPI_ReadBinary {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_ReadBinary, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 20, name: \"read_limit\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 21, name: \"search\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ },\n { no: 22, name: \"search_re\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_StreamText>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_StreamText): StreamingAPI_StreamText {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_StreamText, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 20, name: \"read_limit\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 21, name: \"search\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ },\n { no: 22, name: \"search_re\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ }\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_ReadText): StreamingAPI_ReadText {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_ReadText, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 1, name: \"resource_id\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 2, name: \"offset\", kind: \"scalar\", opt: true, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"line_count\", kind: \"scalar\", opt: true, T: 5 /*ScalarType.INT32*/ },\n { no: 21, name: \"search\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ },\n { no: 22, name: \"search_re\", kind: \"scalar\", opt: true, T: 9 /*ScalarType.STRING*/ }\n ]);\n }\n create(value?: PartialMessage<StreamingAPI_LastLines>): 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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_LastLines): StreamingAPI_LastLines {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_LastLines, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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 { no: 2, name: \"size\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ },\n { no: 3, name: \"new_offset\", kind: \"scalar\", T: 4 /*ScalarType.UINT64*/, L: 0 /*LongType.BIGINT*/ }\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(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: StreamingAPI_Response): StreamingAPI_Response {\n let message = target ?? this.create(), 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(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);\n let d = reader.skip(wireType);\n if (u !== false)\n (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);\n }\n }\n return message;\n }\n internalBinaryWrite(message: StreamingAPI_Response, writer: IBinaryWriter, options: BinaryWriteOptions): 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)(this.typeName, message, writer);\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(\"MiLaboratories.Controller.Shared.Streaming\", [\n { name: \"StreamBinary\", serverStreaming: true, options: {}, I: StreamingAPI_StreamBinary, O: StreamingAPI_Response },\n { name: \"ReadBinary\", options: {}, I: StreamingAPI_ReadBinary, O: StreamingAPI_Response },\n { name: \"StreamText\", serverStreaming: true, options: {}, I: StreamingAPI_StreamText, O: StreamingAPI_Response },\n { name: \"ReadText\", options: {}, I: StreamingAPI_ReadText, O: StreamingAPI_Response },\n { name: \"LastLines\", options: {}, I: StreamingAPI_LastLines, O: StreamingAPI_Response }\n]);\n","// @generated by protobuf-ts 2.11.0 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\n */\n streamBinary(input: StreamingAPI_StreamBinary, options?: RpcOptions): 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\n */\n readBinary(input: StreamingAPI_ReadBinary, options?: RpcOptions): 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\n */\n streamText(input: StreamingAPI_StreamText, options?: RpcOptions): 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\n */\n readText(input: StreamingAPI_ReadText, options?: RpcOptions): 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\n */\n lastLines(input: StreamingAPI_LastLines, options?: RpcOptions): 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 /**\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\n */\n streamBinary(input: StreamingAPI_StreamBinary, options?: RpcOptions): ServerStreamingCall<StreamingAPI_StreamBinary, StreamingAPI_Response> {\n const method = this.methods[0], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamBinary, StreamingAPI_Response>(\"serverStreaming\", this._transport, method, opt, input);\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\n */\n readBinary(input: StreamingAPI_ReadBinary, options?: RpcOptions): UnaryCall<StreamingAPI_ReadBinary, StreamingAPI_Response> {\n const method = this.methods[1], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadBinary, StreamingAPI_Response>(\"unary\", this._transport, method, opt, input);\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\n */\n streamText(input: StreamingAPI_StreamText, options?: RpcOptions): ServerStreamingCall<StreamingAPI_StreamText, StreamingAPI_Response> {\n const method = this.methods[2], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_StreamText, StreamingAPI_Response>(\"serverStreaming\", this._transport, method, opt, input);\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\n */\n readText(input: StreamingAPI_ReadText, options?: RpcOptions): UnaryCall<StreamingAPI_ReadText, StreamingAPI_Response> {\n const method = this.methods[3], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_ReadText, StreamingAPI_Response>(\"unary\", this._transport, method, opt, input);\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\n */\n lastLines(input: StreamingAPI_LastLines, options?: RpcOptions): UnaryCall<StreamingAPI_LastLines, StreamingAPI_Response> {\n const method = this.methods[4], opt = this._transport.mergeOptions(options);\n return stackIntercept<StreamingAPI_LastLines, StreamingAPI_Response>(\"unary\", this._transport, method, opt, input);\n }\n}\n","import { StreamingClient } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client';\nimport type { RpcOptions } from '@protobuf-ts/runtime-rpc';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport type { Dispatcher } from 'undici';\nimport type { GrpcClientProvider, GrpcClientProviderFactory } from '@milaboratories/pl-client';\nimport { addRTypeToMetadata } from '@milaboratories/pl-client';\nimport type { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\n\nexport class ClientLogs {\n public readonly grpcClient: GrpcClientProvider<StreamingClient>;\n\n constructor(\n grpcClientProviderFactory: GrpcClientProviderFactory,\n public readonly httpClient: Dispatcher,\n public readonly logger: MiLogger,\n ) {\n this.grpcClient = grpcClientProviderFactory.createGrpcClientProvider((transport) => new StreamingClient(transport));\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.get().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.get().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 type { GrpcClientProviderFactory, PlClient } from '@milaboratories/pl-client';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport type { 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 type { 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, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientDownload(grpcClientProviderFactory, httpDispatcher, logger, localProjections),\n });\n}\n\nexport function createLogsClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'StreamLogs',\n init: (_: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientLogs(grpcClientProviderFactory, httpDispatcher, logger),\n });\n}\n\nexport function createUploadProgressClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadProgress',\n init: (_: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientProgress(grpcClientProviderFactory, httpDispatcher, client, logger),\n });\n}\n\nexport function createUploadBlobClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'UploadBlob',\n init: (_: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, httpDispatcher: Dispatcher) =>\n new ClientUpload(grpcClientProviderFactory, httpDispatcher, client, logger),\n });\n}\n\nexport function createLsFilesClient(client: PlClient, logger: MiLogger) {\n return client.getDriver({\n name: 'LsFiles',\n init: (_client: PlClient, grpcClientProviderFactory: GrpcClientProviderFactory, _httpDispatcher: Dispatcher) =>\n new ClientLs(grpcClientProviderFactory, logger),\n });\n}\n","import { ConcurrencyLimitingExecutor } from '@milaboratories/ts-helpers';\nimport type { RangeBytes } from '@milaboratories/pl-model-common';\nimport * as fs from 'node:fs';\nimport { buffer } from 'node:stream/consumers';\n\n// Global concurrency limiter for file reads - limit to 32 parallel reads\nconst fileReadLimiter = new ConcurrencyLimitingExecutor(32);\n\n/**\n * Reads file content with concurrency limiting and proper error handling.\n * Ensures file descriptors are properly cleaned up even in error cases.\n */\nexport async function readFileContent(path: string, range?: RangeBytes): Promise<Uint8Array> {\n return await fileReadLimiter.run(async () => {\n const ops: { start?: number; end?: number } = {};\n if (range) {\n ops.start = range.from;\n ops.end = range.to - 1;\n }\n\n let stream: fs.ReadStream | undefined;\n try {\n stream = fs.createReadStream(path, ops);\n return await buffer(stream);\n } catch (error) {\n if (stream && !stream.destroyed) {\n stream.destroy();\n }\n throw error;\n }\n });\n}\n","/** Handle of locally downloaded blob. This handle is issued only after the\n * blob's content is downloaded locally, and ready for quick access. */\n\nimport type { LocalBlobHandle } from '@milaboratories/pl-model-common';\nimport type { Signer } from '@milaboratories/ts-helpers';\n\n// https://regex101.com/r/kfnBVX/1\nconst localHandleRegex = /^blob\\+local:\\/\\/download\\/(?<path>.*)#(?<signature>.*)$/;\n\nexport function newLocalHandle(path: string, signer: Signer): LocalBlobHandle {\n return `blob+local://download/${path}#${signer.sign(path)}` as LocalBlobHandle;\n}\n\nexport function isLocalBlobHandle(handle: string): handle is LocalBlobHandle {\n return Boolean(handle.match(localHandleRegex));\n}\n\nexport function parseLocalHandle(handle: LocalBlobHandle, signer: Signer) {\n const parsed = handle.match(localHandleRegex);\n\n if (parsed === null) {\n throw new Error(`Local handle is malformed: ${handle}, matches: ${parsed}`);\n }\n\n const { path, signature } = parsed.groups!;\n signer.verify(path, signature, `Signature verification failed for: ${handle}`);\n\n return { path, signature };\n}\n","import { z } from 'zod';\nimport type { InferSnapshot } from '@milaboratories/pl-tree';\nimport { rsSchema } from '@milaboratories/pl-tree';\nimport { RangeBytes } from '@milaboratories/pl-model-common';\n\n//\n// 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 function getSize(bs: OnDemandBlobResourceSnapshot, range?: RangeBytes): number {\n const size = bs.kv['ctl/file/blobInfo'].sizeBytes;\n if (range) {\n const newSize = range.to - range.from;\n if (newSize > size) {\n throw new Error(`getSize: range (${JSON.stringify(range)}, newSize: ${newSize}) is greater than size (${size})`);\n }\n\n return newSize;\n }\n\n return size;\n}\n\n//\n// upload\n//\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/** 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\n//\n// ls\n//\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","/** Handle of remote blob. This handle is issued as soon as the data becomes\n * available on the remote server. */\n\nimport type { Signer } from '@milaboratories/ts-helpers';\nimport type { OnDemandBlobResourceSnapshot } from '../types';\nimport type { RemoteBlobHandle } from '@milaboratories/pl-model-common';\nimport { bigintToResourceId } from '@milaboratories/pl-client';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\nimport { getSize } from '../types';\n\n// https://regex101.com/r/Q4YdTa/5\nconst remoteHandleRegex\n = /^blob\\+remote:\\/\\/download\\/(?<content>(?<resourceType>.+)\\/(?<resourceVersion>.+?)\\/(?<resourceId>\\d+?)\\/(?<size>\\d+?))#(?<signature>.*)$/;\n\nexport function newRemoteHandle(\n rInfo: OnDemandBlobResourceSnapshot,\n signer: Signer,\n): RemoteBlobHandle {\n let content = `${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}/${getSize(rInfo)}`;\n\n return `blob+remote://download/${content}#${signer.sign(content)}` as RemoteBlobHandle;\n}\n\nexport function isRemoteBlobHandle(handle: string): handle is RemoteBlobHandle {\n return Boolean(handle.match(remoteHandleRegex));\n}\n\nexport function parseRemoteHandle(handle: RemoteBlobHandle, signer: Signer): {\n info: ResourceInfo;\n size: number;\n } {\n const parsed = handle.match(remoteHandleRegex);\n if (parsed === null) {\n throw new Error(`Remote handle is malformed: ${handle}, matches: ${parsed}`);\n }\n\n const { content, resourceType, resourceVersion, resourceId, size, signature } = parsed.groups!;\n\n signer.verify(content, signature, `Signature verification failed for ${handle}`);\n\n return {\n info:{\n id: bigintToResourceId(BigInt(resourceId)),\n type: { name: resourceType, version: resourceVersion },\n },\n size: Number(size),\n };\n}\n","import {\n BasicResourceData,\n getField,\n isNullResourceId,\n PlClient,\n ResourceId,\n valErr,\n} from '@milaboratories/pl-client';\n\n/** Throws when a driver gets a resource with a wrong resource type. */\nexport class WrongResourceTypeError extends Error {\n name = 'WrongResourceTypeError';\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","/** Handle of logs. This handle should be passed\n * to the driver for retrieving logs. */\n\nimport type { ResourceInfo } from '@milaboratories/pl-tree';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport { bigintToResourceId } from '@milaboratories/pl-client';\n\nexport function newLogHandle(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\n/** Handle of the live logs of a program.\n * The resource that represents a log can be deleted,\n * in this case the handle should be refreshed. */\n\nexport const 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\n/** Handle of the ready logs of a program. */\n\nexport const 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\nexport function getResourceInfoFromLogHandle(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","import { bigintToResourceId, ResourceId } from \"@milaboratories/pl-client\";\nimport * as path from 'node:path';\n\nexport function blobKey(rId: ResourceId): string {\n return `${BigInt(rId)}`;\n}\n\nexport function pathToKey(fPath: string): string {\n return path.basename(fPath);\n}\n\nexport function pathToBlobInfo(fPath: string): ResourceId | undefined {\n const base = path.basename(fPath);\n return bigintToResourceId(BigInt(base));\n}\n","import type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport type { LocalBlobHandle, LocalBlobHandleAndSize } from '@milaboratories/pl-model-common';\nimport type { ResourceSnapshot } from '@milaboratories/pl-tree';\nimport type {\n ValueOrError,\n MiLogger,\n} from '@milaboratories/ts-helpers';\nimport {\n ensureDirExists,\n fileExists,\n createPathAtomically,\n CallersCounter,\n} from '@milaboratories/ts-helpers';\nimport fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Writable } from 'node:stream';\nimport type { ClientDownload } from '../../clients/download';\nimport { UnknownStorageError, WrongLocalFileUrl } from '../../clients/download';\nimport { NetworkError400 } from '../../helpers/download';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\n\n/** Downloads a blob and holds callers and watchers for the blob. */\nexport class DownloadBlobTask {\n readonly change = new ChangeSource();\n private readonly signalCtl = new AbortController();\n public readonly counter = new CallersCounter();\n private error: unknown | undefined;\n private done = false;\n public size = 0;\n private state: DownloadState = {};\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientDownload: ClientDownload,\n readonly rInfo: ResourceSnapshot,\n private readonly handle: LocalBlobHandle,\n readonly path: string,\n ) {}\n\n /** Returns a simple object that describes this task for debugging purposes. */\n public info() {\n return {\n rInfo: this.rInfo,\n fPath: this.path,\n done: this.done,\n error: this.error,\n state: this.state,\n };\n }\n\n public attach(w: Watcher, callerId: string) {\n this.counter.inc(callerId);\n if (!this.done) this.change.attachWatcher(w);\n }\n\n public async download() {\n try {\n const size = await this.ensureDownloaded();\n this.setDone(size);\n this.change.markChanged(`blob download for ${resourceIdToString(this.rInfo.id)} finished`);\n } catch (e: any) {\n this.logger.error(`download blob ${stringifyWithResourceId(this.rInfo)} failed: ${e}, state: ${JSON.stringify(this.state)}`);\n if (nonRecoverableError(e)) {\n this.setError(e);\n this.change.markChanged(`blob download for ${resourceIdToString(this.rInfo.id)} failed`);\n // Just in case we were half-way extracting an archive.\n await fsp.rm(this.path, { force: true });\n }\n\n throw e;\n }\n }\n\n private async ensureDownloaded() {\n this.signalCtl.signal.throwIfAborted();\n\n this.state = {};\n this.state.filePath = this.path;\n await ensureDirExists(path.dirname(this.state.filePath));\n this.signalCtl.signal.throwIfAborted();\n this.state.dirExists = true;\n\n const alreadyExists = await fileExists(this.state.filePath);\n this.signalCtl.signal.throwIfAborted();\n if (alreadyExists) {\n this.state.fileExists = true;\n this.logger.info(`a blob was already downloaded: ${this.state.filePath}`);\n const stat = await fsp.stat(this.state.filePath);\n this.signalCtl.signal.throwIfAborted();\n this.state.fileSize = stat.size;\n\n return this.state.fileSize;\n }\n\n const fileSize = await this.clientDownload.withBlobContent(\n this.rInfo,\n {},\n { signal: this.signalCtl.signal },\n async (content, size) => {\n this.state.fileSize = size;\n this.state.downloaded = true;\n\n await createPathAtomically(this.logger, this.state.filePath!, async (fPath: string) => {\n const f = Writable.toWeb(fs.createWriteStream(fPath, { flags: 'wx' }));\n await content.pipeTo(f, { signal: this.signalCtl.signal });\n this.state.tempWritten = true;\n });\n\n this.state.done = true;\n return size;\n }\n );\n\n return fileSize;\n }\n\n public abort(reason: string) {\n this.signalCtl.abort(new DownloadAborted(reason));\n }\n\n public getBlob():\n | { done: false }\n | {\n done: true;\n result: ValueOrError<LocalBlobHandleAndSize>;\n } {\n if (!this.done) return { done: false };\n\n return {\n done: this.done,\n result: getDownloadedBlobResponse(this.handle, this.size, this.error),\n };\n }\n\n private setDone(sizeBytes: number) {\n this.done = true;\n this.size = sizeBytes;\n }\n\n private setError(e: unknown) {\n this.done = true;\n this.error = e;\n }\n}\n\nexport function nonRecoverableError(e: any) {\n return (\n e instanceof DownloadAborted\n || e instanceof NetworkError400\n || e instanceof UnknownStorageError\n || e instanceof WrongLocalFileUrl\n // file that we downloads from was moved or deleted.\n || e?.code == 'ENOENT'\n // A resource was deleted.\n || (e.name == 'RpcError' && (e.code == 'NOT_FOUND' || e.code == 'ABORTED'))\n );\n}\n\n/** The downloading task was aborted by a signal.\n * It may happen when the computable is done, for example. */\nclass DownloadAborted extends Error {\n name = 'DownloadAborted';\n}\n\nexport function getDownloadedBlobResponse(\n handle: LocalBlobHandle | undefined,\n size: number,\n error?: unknown,\n): ValueOrError<LocalBlobHandleAndSize> {\n if (error) {\n return { ok: false, error };\n }\n\n if (!handle) {\n return { ok: false, error: new Error('No file or handle provided') };\n }\n\n return {\n ok: true,\n value: {\n handle,\n size,\n },\n };\n}\n\ntype DownloadState = {\n filePath?: string;\n dirExists?: boolean;\n fileExists?: boolean;\n fileSize?: number;\n downloaded?: boolean;\n tempWritten?: boolean;\n done?: boolean;\n}\n","import type { CallersCounter } from '@milaboratories/ts-helpers';\nimport { mapEntries, mapGet } from '@milaboratories/ts-helpers';\n\ntype PathLike = string;\n\nexport interface CachedFile {\n /** Size in bytes. */\n size: 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) {\n return;\n }\n\n const file = mapGet(this.cache, path);\n freedBytes += file.size;\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.size < 0) {\n throw new Error(`empty sizeBytes: ${file}`);\n }\n\n if (created) {\n this.totalSizeBytes += file.size;\n }\n }\n\n removeCache(file: T) {\n this.cache.delete(file.path);\n this.totalSizeBytes -= file.size;\n }\n}\n","import { z } from \"zod\";\nimport * as fs from 'node:fs/promises';\nimport { RangeBytes } from \"@milaboratories/pl-model-common\";\nimport { createPathAtomically, MiLogger } from \"@milaboratories/ts-helpers\";\nimport { CorruptedRangesError } from \"./cache\";\n\n/** The content of the ranges file: ranges of bytes.\n * The ranges should be normalized: sorted and no overlaps.\n * For that, use `normalizeRanges` function. */\nconst Ranges = z.object({\n ranges: z.array(RangeBytes),\n});\n\nexport type Ranges = z.infer<typeof Ranges>;\n\nexport const rangesFilePostfix = '.ranges.json';\n\nexport function rangesFileName(fPath: string): string {\n return fPath + rangesFilePostfix;\n}\n\nexport async function readRangesFile(logger: MiLogger, path: string): Promise<Ranges> {\n let ranges: Ranges = { ranges: [] };\n try {\n const file = await fs.readFile(path, 'utf8');\n ranges = Ranges.parse(JSON.parse(file));\n } catch (e: unknown) {\n\n if (e instanceof SyntaxError || e instanceof z.ZodError) {\n const msg = `readRangesFile: the file ${path} was corrupted: ${e}`;\n logger.error(msg);\n throw new CorruptedRangesError(msg);\n }\n\n if (!(e instanceof Error && 'code' in e && e.code === 'ENOENT')) {\n throw e;\n }\n\n // If the file does not exist, assume the ranges are empty.\n }\n\n normalizeRanges(ranges);\n\n return ranges;\n}\n\n/** Writes to a temporal file and then renames it atomically. */\nexport async function writeRangesFile(logger: MiLogger, path: string, ranges: Ranges) {\n await createPathAtomically(logger, path, async (tempPath: string) => {\n await fs.writeFile(tempPath, JSON.stringify(ranges, null, 2), { flag: 'wx' });\n });\n}\n\n/** Sorts and merges overlapping ranges. */\nexport function normalizeRanges(s: Ranges) {\n s.ranges.sort((a, b) => a.from - b.from);\n\n for (let i = 0; i < s.ranges.length - 1; i++) {\n if (s.ranges[i].to >= s.ranges[i + 1].from) {\n mergeRanges(s, i);\n i--;\n }\n }\n}\n\nfunction mergeRanges(s: Ranges, i: number) {\n const from = Math.min(s.ranges[i].from, s.ranges[i + 1].from);\n const to = Math.max(s.ranges[i].to, s.ranges[i + 1].to);\n\n s.ranges.splice(i, 2, { from, to });\n}\n\nexport function rangesSize(s: Ranges) {\n return s.ranges.reduce((acc, range) => acc + range.to - range.from, 0);\n}\n\nexport function doesRangeExist(allRanges: Ranges, range: RangeBytes): boolean {\n for (const r of allRanges.ranges) {\n if (r.from <= range.from && range.to <= r.to) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function addRange(s: Ranges, range: RangeBytes) {\n s.ranges.push(range);\n normalizeRanges(s);\n\n return s;\n}\n\n","import { fileExists, MiLogger, spawnAsync } from \"@milaboratories/ts-helpers\";\nimport * as fs from 'node:fs/promises';\n\n/** Creates a sparse file for all systems\n * Table of what supports sparse files:\n * https://en.wikipedia.org/wiki/Comparison_of_file_systems#Allocation_and_layout_policies */\nexport async function createSparseFile(\n logger: MiLogger,\n path: string,\n platform: NodeJS.Platform,\n) {\n try {\n const ensureCreated = await fs.open(path, 'w');\n await ensureCreated.close();\n\n await ensureSparseOnWindows(path, platform);\n } catch (error: unknown) {\n logger.error(`Error creating file ${path} on platform ${platform}: ${error}`);\n }\n}\n\n/** Sets a sparse flag on Windows.\n * We could check the file is sparse by running:\n * `fsutil sparse queryflag <path>`\n * and\n * `fsutil sparse queryrange <path>`\n */\nasync function ensureSparseOnWindows(path: string, platform: NodeJS.Platform) {\n if (platform === 'win32') {\n await spawnAsync('fsutil', ['sparse', 'setflag', `\"${path}\"`], { stdio: 'pipe' });\n }\n}\n\n/** Ensures the file is created and writes to it. */\nexport async function writeToSparseFile(\n logger: MiLogger,\n platform: NodeJS.Platform,\n path: string,\n data: Uint8Array,\n from: number\n) {\n if (!(await fileExists(path))) {\n await createSparseFile(logger, path, platform);\n }\n\n const fileHandle = await fs.open(path, 'r+');\n await fileHandle.write(data, 0, data.length, from);\n await fileHandle.close();\n}\n","import { RangeBytes } from '@milaboratories/pl-model-common';\nimport { ensureDirExists, fileExists, mapEntries, MiLogger } from '@milaboratories/ts-helpers';\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { addRange, doesRangeExist, Ranges, rangesFileName, rangesFilePostfix, rangesSize, readRangesFile, writeRangesFile } from './ranges';\nimport { writeToSparseFile } from './file';\nimport { functions } from '@milaboratories/helpers';\n\n/** The implementer of SparseCacheRanges could throw it if ranges were corrupted. */\nexport class CorruptedRangesError extends Error {\n name = 'CorruptedRangesError';\n}\n\n/** Extracted ranges methods to be able to store ranges somewhere else (e.g. in memory for tests). */\nexport interface SparseCacheRanges {\n get(key: string): Promise<Ranges>;\n set(key: string, ranges: Ranges): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Stores ranges in a directory as JSON files (the default implementation). */\nexport class SparseCacheFsRanges implements SparseCacheRanges {\n constructor(\n private readonly logger: MiLogger,\n private readonly cacheDir: string,\n ) {}\n\n private fPath(key: string): string {\n return path.join(this.cacheDir, rangesFileName(key));\n }\n\n async get(key: string): Promise<Ranges> {\n return await readRangesFile(this.logger, this.fPath(key));\n }\n\n async set(key: string, ranges: Ranges) {\n return await writeRangesFile(this.logger, this.fPath(key), ranges);\n }\n\n async delete(key: string) {\n await fs.rm(this.fPath(key));\n }\n}\n\n/** Extracted interface for storing sparse files. */\nexport interface SparseFileStorage {\n all(): Promise<string[]>;\n exists(key: string): Promise<boolean>;\n path(key: string): string;\n write(key: string, data: Uint8Array, from: number): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/** Stores sparse files in a directory (the default implementation). */\nexport class SparseCacheFsFile implements SparseFileStorage {\n private readonly suffix = '.sparse.bin';\n\n constructor(\n private readonly logger: MiLogger,\n private readonly cacheDir: string,\n ) {}\n\n async all(): Promise<string[]> {\n await ensureDirExists(this.cacheDir);\n const files = await fs.readdir(this.cacheDir);\n return files.filter((f) => f.endsWith(this.suffix));\n }\n\n async exists(key: string): Promise<boolean> {\n return await fileExists(this.path(key));\n }\n\n path(key: string): string {\n return path.join(this.cacheDir, key + this.suffix);\n }\n\n async write(key: string, data: Uint8Array, from: number): Promise<void> {\n await ensureDirExists(this.cacheDir);\n await writeToSparseFile(this.logger, process.platform, this.path(key), data, from);\n }\n\n async delete(key: string): Promise<void> {\n await fs.rm(this.path(key));\n }\n}\n\n/** LRU cache for ranges of sparse files. */\nexport class SparseCache {\n /** Fields are public for tests. */\n\n /** The lock to make sure cache requests are done one by one. */\n private lock = new functions.AwaitLock()\n\n public keyToLastAccessTime = new Map<string, Date>();\n public size = 0;\n\n constructor(\n public readonly logger: MiLogger,\n /** The hard limit in bytes. */\n public readonly maxSize: number,\n public readonly ranges: SparseCacheRanges,\n public readonly storage: SparseFileStorage,\n ) {}\n\n /** Resets a cache's size by rereading everything we already store.\n * Safe for concurrent use. */\n async reset() {\n await withLock(this.lock, async () => {\n await this.resetUnsafe();\n })\n }\n\n /** Returns a path to the key if the range exists in a cache, otherwise returns undefined.\n * Safe for concurrent use. */\n async get(key: string, range: RangeBytes): Promise<string | undefined> {\n return await withLock(this.lock, async () => {\n return await this.getUnsafe(key, range);\n });\n }\n\n /** Sets data to the cache's file and clear the cache if it's needed.\n * Safe for concurrent use. */\n async set(key: string, range: RangeBytes, data: Uint8Array): Promise<void> {\n await withLock(this.lock, async () => {\n await this.setUnsafe(key, range, data);\n })\n }\n\n private async resetUnsafe() {\n this.size = 0;\n this.keyToLastAccessTime = new Map<string, Date>();\n\n const now = new Date();\n // In rmKey method we first deletes the key from a storage and only then from ranges,\n // so if something goes wrong between 2 operations,\n // on reset the logic will be correct.\n for (const key of await this.storage.all()) {\n const ranges = await this.ranges.get(key);\n this.size += rangesSize(ranges);\n this.keyToLastAccessTime.set(key, now);\n }\n }\n\n private async getUnsafe(key: string, range: RangeBytes): Promise<string | undefined> {\n // It first checks the storage, and then the ranges.\n // In another method, when we remove a key, it first deletes a key from a storage and then from ranges,\n // so if we don't have a key in storage but have it in ranges, the logic here is correct.\n // We probably could reverse the operations here and there, and everywhere we work with both storage and ranges.\n if (await this.storage.exists(key)) {\n this.keyToLastAccessTime.set(key, new Date());\n\n const ranges = await this.getRanges(key);\n if (doesRangeExist(ranges, range)) {\n return this.storage.path(key);\n }\n\n return undefined;\n }\n\n return undefined;\n }\n\n private async setUnsafe(key: string, range: { from: number; to: number; }, data: Uint8Array) {\n await this.setWithoutEviction(key, range, data);\n await this.ensureEvicted();\n }\n\n /** Sets a key and recalculates a size, but doesn't ensures that the size is less than the hard limit. */\n async setWithoutEviction(key: string, range: RangeBytes, data: Uint8Array): Promise<void> {\n if (range.to - range.from !== data.length) {\n throw new Error(\n `SparseCache.set: trying to set ${key} with wrong range length: `\n + `range: ${JSON.stringify(range)}, data: ${data.length}`\n );\n }\n\n this.keyToLastAccessTime.set(key, new Date());\n\n const ranges = await this.getRanges(key);\n this.size -= rangesSize(ranges);\n\n await this.storage.write(key, data, range.from);\n\n const newRanges = addRange(ranges, range);\n this.size += rangesSize(newRanges);\n\n await this.ranges.set(key, newRanges);\n }\n\n /** Ensures the size is less than hard limit by deleting the oldest keys. */\n async ensureEvicted(): Promise<void> {\n const byTime = mapEntries(this.keyToLastAccessTime);\n byTime.sort(([_, aDate], [__, bDate]) => bDate.getTime() - aDate.getTime());\n\n while (this.size > this.maxSize) {\n const keyAndDate = byTime.pop(); // removes the oldest\n if (!keyAndDate) {\n break;\n }\n const [key, _] = keyAndDate;\n\n const ranges = await this.getRanges(key);\n this.size -= rangesSize(ranges);\n this.rmKey(key);\n }\n }\n\n /** Gets ranges and if they were corrupted, then remove the file from the cache and reset the cache's size. */\n private async getRanges(key: string) {\n try {\n return await this.ranges.get(key);\n } catch (e: unknown) {\n if (e instanceof CorruptedRangesError) {\n // We need to reset a state of the cache and update current size,\n // it's the only way to calculate the real size when one of the ranges were corrupted.\n await this.rmKey(key);\n await this.resetUnsafe();\n\n return await this.ranges.get(key);\n }\n\n throw e;\n }\n }\n\n /** Removes a key the state of the cache. The size should be updated. */\n private async rmKey(key: string) {\n await this.storage.delete(key);\n await this.ranges.delete(key);\n this.keyToLastAccessTime.delete(key);\n }\n}\n\n/** Acquires the lock and executes a callback. */\nasync function withLock<T>(lock: functions.AwaitLock, cb: () => Promise<T>): Promise<T> {\n try {\n await lock.acquireAsync();\n return await cb();\n } finally {\n lock.release();\n }\n}\n","import type {\n ComputableCtx,\n ComputableStableDefined,\n Watcher,\n} from '@milaboratories/computable';\nimport {\n ChangeSource,\n Computable,\n} from '@milaboratories/computable';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type {\n AnyLogHandle,\n BlobDriver,\n LocalBlobHandle,\n LocalBlobHandleAndSize,\n ReadyLogHandle,\n RemoteBlobHandle,\n RemoteBlobHandleAndSize,\n StreamingApiResponse,\n} from '@milaboratories/pl-model-common';\nimport { type RangeBytes, validateRangeBytes } from '@milaboratories/pl-model-common';\nimport type {\n PlTreeEntry,\n ResourceInfo,\n ResourceSnapshot\n} from '@milaboratories/pl-tree';\nimport {\n isPlTreeEntry,\n makeResourceSnapshot,\n treeEntryToResourceInfo,\n} from '@milaboratories/pl-tree';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { CallersCounter, mapGet, TaskProcessor } from '@milaboratories/ts-helpers';\nimport Denque from 'denque';\nimport * as fs from 'fs';\nimport { randomUUID } from 'node:crypto';\nimport * as fsp from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport * as readline from 'node:readline/promises';\nimport { Writable } from 'node:stream';\nimport { buffer } from 'node:stream/consumers';\nimport type { ClientDownload } from '../../clients/download';\nimport type { ClientLogs } from '../../clients/logs';\nimport { readFileContent } from '../helpers/read_file';\nimport {\n isLocalBlobHandle,\n newLocalHandle,\n parseLocalHandle,\n} from '../helpers/download_local_handle';\nimport {\n isRemoteBlobHandle,\n newRemoteHandle,\n parseRemoteHandle,\n} from '../helpers/download_remote_handle';\nimport { Updater, WrongResourceTypeError } from '../helpers/helpers';\nimport { getResourceInfoFromLogHandle, newLogHandle } from '../helpers/logs_handle';\nimport { getSize, OnDemandBlobResourceSnapshot } from '../types';\nimport { blobKey, pathToKey } from './blob_key';\nimport { DownloadBlobTask, nonRecoverableError } from './download_blob_task';\nimport { FilesCache } from '../helpers/files_cache';\nimport { SparseCache, SparseCacheFsFile, SparseCacheFsRanges } from './sparse_cache/cache';\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 /**\n * A hard limit of the amount of sparse cache, in bytes.\n * Once exceeded, the download driver will start deleting blobs one by one.\n *\n * The sparse cache is used to store ranges of blobs.\n * */\n rangesCacheMaxSizeBytes: number;\n\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 unique key to the path of a blob as a map. */\n private keyToDownload: Map<string, DownloadBlobTask> = 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<DownloadBlobTask>;\n private rangesCache: SparseCache;\n\n /** Downloads files and writes them to the local dir. */\n private downloadQueue: TaskProcessor;\n\n private keyToOnDemand: Map<string, OnDemandBlobHolder> = new Map();\n\n private idToLastLines: Map<string, LastLinesGetter> = new Map();\n private idToProgressLog: Map<string, 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 rangesCacheDir: string,\n private readonly signer: Signer,\n private readonly ops: DownloadDriverOps,\n ) {\n this.cache = new FilesCache(this.ops.cacheSoftSizeBytes);\n\n const fsRanges = new SparseCacheFsRanges(this.logger, this.rangesCacheDir);\n const fsStorage = new SparseCacheFsFile(this.logger, this.rangesCacheDir);\n this.rangesCache = new SparseCache(this.logger, this.ops.rangesCacheMaxSizeBytes, fsRanges, fsStorage);\n\n this.downloadQueue = new TaskProcessor(this.logger, ops.nConcurrentDownloads);\n\n this.saveDir = path.resolve(saveDir);\n }\n\n static async init(\n logger: MiLogger,\n clientDownload: ClientDownload,\n clientLogs: ClientLogs,\n saveDir: string,\n rangesCacheDir: string,\n signer: Signer,\n ops: DownloadDriverOps,\n ): Promise<DownloadDriver> {\n const driver = new DownloadDriver(logger, clientDownload, clientLogs, saveDir, rangesCacheDir, signer, ops);\n await driver.rangesCache.reset();\n\n return driver;\n }\n\n /** Gets a blob or part of the blob by its resource id or downloads a blob and sets it in a cache. */\n public getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx: ComputableCtx,\n ): LocalBlobHandleAndSize | undefined;\n public getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ): ComputableStableDefined<LocalBlobHandleAndSize>;\n public getDownloadedBlob(\n res: ResourceInfo | PlTreeEntry,\n ctx?: ComputableCtx,\n ): Computable<LocalBlobHandleAndSize | undefined> | LocalBlobHandleAndSize | undefined {\n if (ctx === undefined) {\n return Computable.make((ctx) => this.getDownloadedBlob(res, ctx));\n }\n\n const rInfo = treeEntryToResourceInfo(res, ctx);\n\n const callerId = randomUUID();\n ctx.addOnDestroy(() => this.releaseBlob(rInfo, callerId));\n\n const result = this.getDownloadedBlobNoCtx(ctx.watcher, rInfo as ResourceSnapshot, callerId);\n if (result == undefined) {\n ctx.markUnstable('download blob is still undefined');\n }\n\n return result;\n }\n\n private getDownloadedBlobNoCtx(\n w: Watcher,\n rInfo: ResourceSnapshot,\n callerId: string,\n ): LocalBlobHandleAndSize | undefined {\n validateDownloadableResourceType('getDownloadedBlob', rInfo.type);\n\n // We don't need to request files with wider limits,\n // PFrame's engine does it disk-optimally by itself.\n\n const task = this.getOrSetNewTask(rInfo, callerId);\n task.attach(w, callerId);\n\n const result = task.getBlob();\n if (!result.done) {\n return undefined;\n }\n if (result.result.ok) {\n return result.result.value;\n }\n throw result.result.error;\n }\n\n private getOrSetNewTask(\n rInfo: ResourceSnapshot,\n callerId: string,\n ): DownloadBlobTask {\n const key = blobKey(rInfo.id);\n\n const inMemoryTask = this.keyToDownload.get(key);\n if (inMemoryTask) {\n return inMemoryTask;\n }\n\n // schedule the blob downloading, then it'll be added to the cache.\n const fPath = path.resolve(this.saveDir, key);\n\n const newTask = new DownloadBlobTask(\n this.logger,\n this.clientDownload,\n rInfo,\n newLocalHandle(fPath, this.signer),\n fPath,\n );\n this.keyToDownload.set(key, newTask);\n\n this.downloadQueue.push({\n fn: () => this.downloadBlob(newTask, callerId),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e),\n });\n\n return newTask;\n }\n\n private async downloadBlob(task: DownloadBlobTask, callerId: string) {\n await task.download();\n const blob = task.getBlob();\n if (blob.done && blob.result.ok) {\n this.cache.addCache(task, callerId);\n }\n }\n\n /** Gets on demand blob. */\n public getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ): Computable<RemoteBlobHandleAndSize>;\n public getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx?: undefined,\n fromBytes?: number,\n toBytes?: number,\n ): Computable<RemoteBlobHandleAndSize>;\n public getOnDemandBlob(\n res: OnDemandBlobResourceSnapshot | PlTreeEntry,\n ctx: ComputableCtx,\n fromBytes?: number,\n toBytes?: number,\n ): RemoteBlobHandleAndSize;\n public 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 // note that the watcher is not needed,\n // the handler never changes.\n const result = this.getOnDemandBlobNoCtx(rInfo, callerId);\n\n return result;\n }\n\n private getOnDemandBlobNoCtx(\n info: OnDemandBlobResourceSnapshot,\n callerId: string,\n ): RemoteBlobHandleAndSize {\n validateDownloadableResourceType('getOnDemandBlob', info.type);\n\n let blob = this.keyToOnDemand.get(blobKey(info.id));\n\n if (blob === undefined) {\n blob = new OnDemandBlobHolder(getSize(info), newRemoteHandle(info, this.signer));\n this.keyToOnDemand.set(blobKey(info.id), blob);\n }\n\n blob.attach(callerId);\n\n return blob.getHandle();\n }\n\n /** Gets a path from a handle. */\n public getLocalPath(handle: LocalBlobHandle): string {\n const { path } = parseLocalHandle(handle, this.signer);\n return path;\n }\n\n /** Gets a content of a blob by a handle. */\n public async getContent(handle: LocalBlobHandle | RemoteBlobHandle, range?: RangeBytes): Promise<Uint8Array> {\n if (range) {\n validateRangeBytes(range, `getContent`);\n }\n\n if (isLocalBlobHandle(handle)) {\n return await readFileContent(this.getLocalPath(handle), range);\n }\n\n if (isRemoteBlobHandle(handle)) {\n const result = parseRemoteHandle(handle, this.signer);\n\n const key = blobKey(result.info.id);\n const filePath = await this.rangesCache.get(key, range ?? { from: 0, to: result.size });\n if (filePath) {\n return await readFileContent(filePath, range);\n }\n\n const data = await this.clientDownload.withBlobContent(\n { id: result.info.id, type: result.info.type },\n undefined,\n { range },\n async (content) => await buffer(content)\n );\n await this.rangesCache.set(key, range ?? { from: 0, to: result.size }, data);\n\n return data;\n }\n\n throw new Error('Malformed remote handle');\n }\n\n /**\n * Creates computable that will return blob content once it is downloaded.\n * Uses downloaded blob handle under the hood, so stores corresponding blob in file system.\n */\n public getComputableContent(\n res: ResourceInfo | PlTreeEntry,\n range?: RangeBytes,\n ): ComputableStableDefined<Uint8Array> {\n if (range) {\n validateRangeBytes(range, `getComputableContent`);\n }\n\n return Computable.make((ctx) =>\n this.getDownloadedBlob(res, ctx), {\n postprocessValue: (v) => v ? this.getContent(v.handle, range) : undefined\n }\n ).withStableType()\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 public getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number\n ): Computable<string | undefined>;\n public getLastLogs(\n res: ResourceInfo | PlTreeEntry,\n lines: number,\n ctx: ComputableCtx\n ): Computable<string | undefined>;\n public 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, 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 validateDownloadableResourceType('getLastLogs', rInfo.type);\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n\n const { path } = parseLocalHandle(blob.handle, this.signer);\n\n let logGetter = this.idToLastLines.get(blobKey(rInfo.id));\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, lines);\n this.idToLastLines.set(blobKey(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 public getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string\n ): Computable<string | undefined>;\n public getProgressLog(\n res: ResourceInfo | PlTreeEntry,\n patternToSearch: string,\n ctx: ComputableCtx\n ): string | undefined;\n public 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, 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 validateDownloadableResourceType('getProgressLog', rInfo.type);\n\n const blob = this.getDownloadedBlobNoCtx(w, rInfo, callerId);\n if (blob == undefined) return undefined;\n const { path } = parseLocalHandle(blob.handle, this.signer);\n\n let logGetter = this.idToProgressLog.get(blobKey(rInfo.id));\n\n if (logGetter == undefined) {\n const newLogGetter = new LastLinesGetter(path, 1, patternToSearch);\n this.idToProgressLog.set(blobKey(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 public getLogHandle(res: ResourceInfo | PlTreeEntry): Computable<AnyLogHandle>;\n public getLogHandle(res: ResourceInfo | PlTreeEntry, ctx: ComputableCtx): AnyLogHandle;\n public 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 validateDownloadableResourceType('getLogHandle', rInfo.type);\n return newLogHandle(false, rInfo);\n }\n\n public 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 getResourceInfoFromLogHandle(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 public 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 getResourceInfoFromLogHandle(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(rInfo: ResourceInfo, callerId: string) {\n const task = this.keyToDownload.get(blobKey(rInfo.id));\n if (task == undefined) {\n return;\n }\n\n if (this.cache.existsFile(blobKey(rInfo.id))) {\n const toDelete = this.cache.removeFile(blobKey(rInfo.id), callerId);\n\n await Promise.all(\n toDelete.map(async (cachedFile) => {\n await fsp.rm(cachedFile.path);\n\n this.cache.removeCache(cachedFile);\n\n this.removeTask(\n mapGet(this.keyToDownload, pathToKey(cachedFile.path)),\n `the task ${stringifyWithResourceId(cachedFile)} was removed`\n + `from cache along with ${stringifyWithResourceId(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) {\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed from cache`,\n );\n }\n }\n }\n\n private removeTask(task: DownloadBlobTask, reason: string) {\n task.abort(reason);\n task.change.markChanged(`download task for ${task.path} removed: ${reason}`);\n this.keyToDownload.delete(pathToKey(task.path));\n this.idToLastLines.delete(blobKey(task.rInfo.id));\n this.idToProgressLog.delete(blobKey(task.rInfo.id));\n }\n\n private async releaseOnDemandBlob(blobId: ResourceId, callerId: string) {\n const deleted = this.keyToOnDemand.get(blobKey(blobId))?.release(callerId) ?? false;\n if (deleted) this.keyToOnDemand.delete(blobKey(blobId));\n }\n\n /** Removes all files from a hard drive. */\n async releaseAll() {\n this.downloadQueue.stop();\n\n this.keyToDownload.forEach((task, key) => {\n this.keyToDownload.delete(key);\n task.change.markChanged(`task ${resourceIdToString(task.rInfo.id)} released`);\n });\n }\n}\n\n/** Keeps a counter to the on demand handle. */\nclass OnDemandBlobHolder {\n private readonly counter = new CallersCounter();\n\n constructor(\n private readonly size: number,\n private readonly handle: RemoteBlobHandle,\n ) {}\n\n public getHandle(): RemoteBlobHandleAndSize {\n return { handle: this.handle, size: this.size };\n }\n\n public attach(callerId: string) {\n this.counter.inc(callerId);\n }\n\n public release(callerId: string): boolean {\n return this.counter.dec(callerId);\n }\n}\n\nclass LastLinesGetter {\n private updater: 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 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(`logs for ${this.path} updated`);\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(`log update for ${this.path} failed, resource not found`);\n return;\n }\n\n throw e;\n }\n }\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. */\nasync function getLastLines(fPath: string, nLines: number, patternToSearch?: string): Promise<string> {\n let inStream: fs.ReadStream | undefined;\n let rl: readline.Interface | undefined;\n\n try {\n inStream = fs.createReadStream(fPath);\n rl = readline.createInterface({ input: inStream, crlfDelay: Infinity });\n\n const lines = new Denque();\n\n for await (const line of rl) {\n if (patternToSearch != undefined && !line.includes(patternToSearch)) continue;\n\n lines.push(line);\n if (lines.length > nLines) {\n lines.shift();\n }\n }\n\n // last EOL is for keeping backward compat with platforma implementation.\n return lines.toArray().join(os.EOL) + os.EOL;\n } finally {\n // Cleanup resources in finally block to ensure they're always cleaned up\n try {\n if (rl) {\n rl.close();\n }\n } catch (cleanupError) {\n console.error('Error closing readline interface:', cleanupError);\n }\n\n try {\n if (inStream && !inStream.destroyed) {\n inStream.destroy();\n }\n } catch (cleanupError) {\n console.error('Error destroying read stream:', cleanupError);\n }\n }\n}\n\nfunction validateDownloadableResourceType(methodName: string, rType: ResourceType) {\n if (!rType.name.startsWith('Blob/')) {\n let message = `${methodName}: wrong resource type: ${rType.name}, expected: a resource of type that starts with 'Blob/'.`;\n if (rType.name == 'Blob')\n message += ` If it's called from workflow, should a file be exported with 'file.exportFile' function?`;\n\n throw new WrongResourceTypeError(message);\n }\n}\n","import type { ComputableCtx } from '@milaboratories/computable';\nimport type { InferSnapshot, PlTreeEntry, PlTreeEntryAccessor, PlTreeNodeAccessor } from '@milaboratories/pl-tree';\nimport { isPlTreeEntry, isPlTreeEntryAccessor, makeResourceSnapshot, rsSchema } from '@milaboratories/pl-tree';\n\n/** We need only resource type for this driver. */\nexport const DownloadableBlobSnapshot = rsSchema({});\nexport type DownloadableBlobSnapshot = InferSnapshot<typeof DownloadableBlobSnapshot>;\n\nexport function makeDownloadableBlobSnapshot(\n entryOrAccessor: PlTreeEntry | PlTreeNodeAccessor | PlTreeEntryAccessor,\n ctx: ComputableCtx,\n): DownloadableBlobSnapshot {\n const node = isPlTreeEntry(entryOrAccessor)\n ? ctx.accessor(entryOrAccessor).node()\n : isPlTreeEntryAccessor(entryOrAccessor)\n ? entryOrAccessor.node()\n : entryOrAccessor;\n\n return makeResourceSnapshot(node, DownloadableBlobSnapshot);\n}\n","import type { FolderURL, BlockUIURL } from '@milaboratories/pl-model-common';\nimport type { Signer } from '@milaboratories/ts-helpers';\nimport path from 'path';\n\n/** Creates a new plblob+folder URL. */\nexport function newFolderURL(signer: Signer, saveDir: string, fPath: string): FolderURL {\n const p = path.relative(saveDir, fPath);\n const sign = signer.sign(p);\n\n return `plblob+folder://${sign}.${p}.blob`;\n}\n\n/** Creates a new block-ui URL. */\nexport function newBlockUIURL(signer: Signer, saveDir: string, fPath: string): BlockUIURL {\n const p = path.relative(saveDir, fPath);\n const sign = signer.sign(p);\n\n return `block-ui://${sign}.${p}.uidir`;\n}\n\n/** Checks the signature and path injections.\n * @returns the path to the file inside the root directory. */\nexport function getPathForFolderURL(signer: Signer, url: FolderURL, rootDir: string): string {\n return getPath(signer, url, rootDir);\n}\n\n/** Checks the signature and path injections.\n * @returns the path to the file inside the root directory. */\nexport function getPathForBlockUIURL(signer: Signer, url: BlockUIURL, rootDir: string): string {\n return getPath(signer, url, rootDir);\n}\n\n/** Parses URL,\n * checks the signature,\n * gets the absolute path by the given root directory.\n * If the path is empty, it returns the index.html file.\n * @returns an absolute path for the user. */\nfunction getPath(signer: Signer, url: string, rootDir: string): string {\n const parsed = new URL(url);\n const [sign, subfolder, _] = parsed.host.split('.');\n\n signer.verify(subfolder, sign, `signature verification failed for url: ${url}, subfolder: ${subfolder}`);\n\n // Decoding changes '%20' to ' ' for example.\n const pathname = decodeURIComponent(parsed.pathname.slice(1));\n\n let fPath = parseNestedPathNoEscape(path.join(rootDir, `${subfolder}`), pathname);\n\n if (parsed.pathname == '' || parsed.pathname == '/') {\n fPath = path.join(fPath, 'index.html');\n }\n\n return path.resolve(fPath);\n}\n\n/** Checks that the userInputPath is in baseDir.\n * @returns an absolute path for the user. */\nfunction parseNestedPathNoEscape(baseDir: string, userInputPath: string): string {\n const absolutePath = path.resolve(baseDir, userInputPath);\n\n const normalizedBase = path.resolve(baseDir);\n\n if (!absolutePath.startsWith(normalizedBase)) {\n throw new Error('Path validation failed.');\n }\n\n return absolutePath;\n}\n","import { Transform, Writable } from 'node:stream';\nimport * as zlib from 'node:zlib';\nimport * as tar from 'tar-fs';\nimport path from 'path';\nimport fs from 'fs';\nimport * as fsp from 'fs/promises';\nimport { NetworkError400 } from '../../helpers/download';\nimport type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { CallersCounter, createPathAtomically, ensureDirExists, fileExists, notEmpty } from '@milaboratories/ts-helpers';\nimport type { DownloadableBlobSnapshot } from './snapshot';\nimport { UnknownStorageError, WrongLocalFileUrl, type ClientDownload } from '../../clients/download';\nimport type { ArchiveFormat, FolderURL } from '@milaboratories/pl-model-common';\nimport { newFolderURL } from '../urls/url';\nimport decompress from 'decompress';\nimport { assertNever } from '@protobuf-ts/runtime';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\n\nexport type URLResult = {\n url?: FolderURL;\n error?: string;\n};\n\n/** Downloads and extracts an archive to a directory. */\nexport class DownloadAndUnarchiveTask {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n private readonly signalCtl = new AbortController();\n error: string | undefined;\n done = false;\n size = 0;\n private url: FolderURL | undefined;\n private state: DownloadCtx | undefined;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly signer: Signer,\n readonly saveDir: string,\n readonly path: string,\n readonly rInfo: DownloadableBlobSnapshot,\n readonly format: ArchiveFormat,\n private readonly clientDownload: ClientDownload,\n ) {}\n\n /** A debug info of the task. */\n public info() {\n return {\n rInfo: this.rInfo,\n format: this.format,\n path: this.path,\n done: this.done,\n size: this.size,\n error: this.error,\n taskHistory: this.state,\n };\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 const size = await this.downloadAndDecompress(this.signalCtl.signal);\n this.setDone(size);\n this.change.markChanged(`download and decompress for ${resourceIdToString(this.rInfo.id)} finished`);\n\n this.logger.info(`blob to URL task is done: ${stringifyWithResourceId(this.info())}`);\n } catch (e: any) {\n this.logger.warn(`a error was produced: ${e} for blob to URL task: ${stringifyWithResourceId(this.info())}`);\n\n if (nonRecoverableError(e)) {\n this.setError(e);\n this.change.markChanged(`download and decompress for ${resourceIdToString(this.rInfo.id)} failed`);\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 /** Does the download part and keeps a state of the process. */\n private async downloadAndDecompress(signal: AbortSignal): Promise<number> {\n this.state = {};\n\n this.state.parentDir = path.dirname(this.path);\n await ensureDirExists(this.state.parentDir);\n\n this.state.fileExisted = await fileExists(this.path);\n if (this.state.fileExisted) {\n return await dirSize(this.path);\n }\n\n const size = await this.clientDownload.withBlobContent(\n this.rInfo, \n {}, \n { signal },\n async (content, size) => {\n this.state!.downloaded = true;\n\n await createPathAtomically(this.logger, this.path, async (fPath: string) => {\n this.state!.tempPath = fPath;\n this.state!.archiveFormat = this.format;\n\n switch (this.format) {\n case 'tar':\n await fsp.mkdir(fPath); // throws if a directory already exists.\n const simpleUntar = Writable.toWeb(tar.extract(fPath));\n await content.pipeTo(simpleUntar, { signal });\n return;\n\n case 'tgz':\n await fsp.mkdir(fPath); // throws if a directory already exists.\n const gunzip = Transform.toWeb(zlib.createGunzip());\n const untar = Writable.toWeb(tar.extract(fPath));\n\n await content\n .pipeThrough(gunzip, { signal })\n .pipeTo(untar, { signal });\n return;\n\n case 'zip':\n this.state!.zipPath = this.path + '.zip';\n\n const f = Writable.toWeb(fs.createWriteStream(this.state!.zipPath));\n await content.pipeTo(f, { signal });\n this.state!.zipPathCreated = true;\n\n // Without this filter it fails with\n // \"EISDIR: illegal operation on a directory\".\n // The workaround is from\n // https://github.com/kevva/decompress/issues/46#issuecomment-525048104\n await decompress(this.state!.zipPath, fPath, {\n filter: file => !file.path.endsWith('/'),\n });\n this.state!.zipDecompressed = true;\n\n await fs.promises.rm(this.state!.zipPath);\n this.state!.zipPathDeleted = true;\n\n return;\n\n default:\n assertNever(this.format);\n }\n });\n\n this.state!.pathCreated = true;\n return size;\n }\n );\n\n return size;\n }\n\n getURL(): URLResult | undefined {\n if (this.done) return { url: notEmpty(this.url) };\n\n if (this.error) return { error: this.error };\n\n return undefined;\n }\n\n private setDone(size: number) {\n this.done = true;\n this.size = size;\n this.url = newFolderURL(this.signer, this.saveDir, this.path);\n }\n\n private setError(e: any) {\n this.error = String(e);\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new URLAborted(reason));\n }\n}\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: any) => {\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: any, size: any) => sum + size, 0);\n}\n\n/** Do rm -rf on dir. */\nexport async function rmRFDir(path: string) {\n await fsp.rm(path, { recursive: true, force: true });\n}\n\n/** Just a type that adds lots of context when the error happens. */\ntype DownloadCtx = {\n parentDir?: string;\n fileExisted?: boolean;\n downloaded?: boolean;\n archiveFormat?: ArchiveFormat;\n tempPath?: string;\n zipPath?: string;\n zipPathCreated?: boolean;\n zipDecompressed?: boolean;\n zipPathDeleted?: boolean;\n pathCreated?: boolean;\n};\n\n/** Throws when a downloading aborts. */\nclass URLAborted extends Error {\n name = 'URLAborted';\n}\n\nexport function nonRecoverableError(e: any) {\n return (\n e instanceof URLAborted\n || e instanceof NetworkError400\n || e instanceof UnknownStorageError\n || e instanceof WrongLocalFileUrl\n // file that we downloads from was moved or deleted.\n || e?.code == 'ENOENT'\n // A resource was deleted.\n || (e.name == 'RpcError' && (e.code == 'NOT_FOUND' || e.code == 'ABORTED'))\n // wrong archive format\n || (String(e).includes('incorrect header check'))\n );\n}\n","import type { ResourceId } from '@milaboratories/pl-client';\nimport type { ArchiveFormat } from '@milaboratories/pl-model-common';\n\n/** A key in the driver task queue. */\nexport type Id = string;\n\nexport function newId(id: ResourceId, format: ArchiveFormat): Id {\n return `id:${String(BigInt(id))}-${format}`;\n}\n\n// export function\n","import type { ComputableCtx, Watcher } from '@milaboratories/computable';\nimport { Computable } from '@milaboratories/computable';\nimport type {\n MiLogger,\n Signer } from '@milaboratories/ts-helpers';\nimport {\n TaskProcessor,\n} from '@milaboratories/ts-helpers';\nimport { randomUUID } from 'node:crypto';\nimport * as path from 'node:path';\nimport { FilesCache } from '../helpers/files_cache';\nimport type { ResourceId } from '@milaboratories/pl-client';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport { type ArchiveFormat, type BlobToURLDriver, type FolderURL, isFolderURL } from '@milaboratories/pl-model-common';\nimport type { DownloadableBlobSnapshot } from './snapshot';\nimport { makeDownloadableBlobSnapshot } from './snapshot';\nimport type { PlTreeEntry } from '@milaboratories/pl-tree';\nimport { isPlTreeEntry } from '@milaboratories/pl-tree';\nimport { DownloadAndUnarchiveTask, rmRFDir } from './task';\nimport type { ClientDownload } from '../../clients/download';\nimport { getPathForFolderURL } from '../urls/url';\nimport type { Id } from './driver_id';\nimport { newId } from './driver_id';\nimport { nonRecoverableError } from '../download_blob/download_blob_task';\n\nexport type DownloadBlobToURLDriverOps = {\n cacheSoftSizeBytes: number;\n nConcurrentDownloads: number;\n};\n\n/** Downloads .tar, .tar.gz or zip archives,\n * extracts them into saveDir and gets a url for it. */\nexport class DownloadBlobToURLDriver implements BlobToURLDriver {\n private idToDownload: Map<Id, DownloadAndUnarchiveTask> = 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<DownloadAndUnarchiveTask>;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly signer: Signer,\n private readonly clientDownload: ClientDownload,\n private readonly saveDir: string,\n private readonly opts: DownloadBlobToURLDriverOps = {\n cacheSoftSizeBytes: 50 * 1024 * 1024,\n nConcurrentDownloads: 50,\n },\n ) {\n this.downloadQueue = new TaskProcessor(this.logger, this.opts.nConcurrentDownloads, {\n type: 'exponentialWithMaxDelayBackoff',\n initialDelay: 10000,\n maxDelay: 30000,\n backoffMultiplier: 1.5,\n jitter: 0.5,\n });\n this.cache = new FilesCache(this.opts.cacheSoftSizeBytes);\n }\n\n public info(): any {\n return {\n saveDir: this.saveDir,\n opts: this.opts,\n idToDownloadSize: this.idToDownload.size,\n idToDownloadKeys: this.idToDownload.keys(),\n idToDownload: Array.from(this.idToDownload.entries()).map(([id, task]) => [id, task.info()]),\n };\n }\n\n /**\n * @returns full path to the referenced file\n */\n getPathForCustomProtocol(url: FolderURL): string {\n if (isFolderURL(url)) {\n return getPathForFolderURL(this.signer, url, this.saveDir);\n }\n\n throw new Error(`getPathForCustomProtocol: ${url} is invalid`);\n }\n\n extractArchiveAndGetURL(\n res: DownloadableBlobSnapshot | PlTreeEntry,\n format: ArchiveFormat,\n ctx: ComputableCtx,\n ): FolderURL | undefined;\n\n extractArchiveAndGetURL(\n res: DownloadableBlobSnapshot | PlTreeEntry,\n format: ArchiveFormat,\n ): Computable<FolderURL | undefined>;\n\n extractArchiveAndGetURL(\n res: DownloadableBlobSnapshot | PlTreeEntry,\n format: ArchiveFormat,\n ctx?: ComputableCtx,\n ): Computable<FolderURL | undefined> | FolderURL | undefined {\n // wrap result as computable, if we were not given an existing computable context\n if (ctx === undefined)\n return Computable.make((c) => this.extractArchiveAndGetURL(res, format, c));\n\n const rInfo: DownloadableBlobSnapshot = isPlTreeEntry(res)\n ? makeDownloadableBlobSnapshot(res, ctx)\n : res;\n\n const callerId = randomUUID();\n\n ctx.addOnDestroy(() => this.releasePath(rInfo.id, format, callerId));\n\n const result = this.extractArchiveAndGetURLNoCtx(rInfo, format, ctx.watcher, callerId);\n if (result?.url === undefined)\n ctx.markUnstable(\n `a path to the downloaded archive might be undefined. The current result: ${result}`,\n );\n\n if (result?.error !== undefined)\n throw result?.error;\n\n return result?.url;\n }\n\n private extractArchiveAndGetURLNoCtx(\n rInfo: DownloadableBlobSnapshot,\n format: ArchiveFormat,\n w: Watcher,\n callerId: string,\n ) {\n const task = this.idToDownload.get(newId(rInfo.id, format));\n\n if (task != undefined) {\n task.attach(w, callerId);\n return task.getURL();\n }\n\n const newTask = this.setNewTask(w, rInfo, format, callerId);\n this.downloadQueue.push({\n fn: async () => this.downloadUrl(newTask, callerId),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e),\n });\n\n return newTask.getURL();\n }\n\n /** Downloads and extracts a tar archive if it wasn't downloaded yet. */\n async downloadUrl(task: DownloadAndUnarchiveTask, callerId: string) {\n await task.download();\n // Might be undefined if a error happened\n if (task.getURL()?.url != 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(id: ResourceId, format: ArchiveFormat, callerId: string): Promise<void> {\n const task = this.idToDownload.get(newId(id, format));\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: DownloadAndUnarchiveTask) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed`\n + `from cache along with ${stringifyWithResourceId(toDelete.map((t) => t.info()))}`,\n );\n }),\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted)\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed from cache`,\n );\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.idToDownload.entries()).map(async ([_, task]) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was released when the driver was closed`,\n );\n }),\n );\n }\n\n private setNewTask(w: Watcher, rInfo: DownloadableBlobSnapshot, format: ArchiveFormat, callerId: string) {\n const result = new DownloadAndUnarchiveTask(\n this.logger,\n this.signer,\n this.saveDir,\n this.getFilePath(rInfo.id, format),\n rInfo,\n format,\n this.clientDownload,\n );\n result.attach(w, callerId);\n this.idToDownload.set(newId(rInfo.id, format), result);\n\n return result;\n }\n\n private removeTask(task: DownloadAndUnarchiveTask, reason: string) {\n task.abort(reason);\n task.change.markChanged(`task for ${resourceIdToString(task.rInfo.id)} removed: ${reason}`);\n this.idToDownload.delete(newId(task.rInfo.id, task.format));\n }\n\n private getFilePath(id: ResourceId, format: ArchiveFormat): string {\n return path.join(this.saveDir, `${String(BigInt(id))}_${format}`);\n }\n}\n","import type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport { resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { AsyncPoolController, MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { asyncPool, CallersCounter } from '@milaboratories/ts-helpers';\nimport type { ClientProgress, ProgressStatus } from '../clients/progress';\nimport type { ClientUpload } from '../clients/upload';\nimport { MTimeError, NoFileForUploading, UnexpectedEOF } from '../clients/upload';\nimport type { ImportResourceSnapshot } from './types';\nimport { ImportFileHandleUploadData } from './types';\nimport assert from 'node:assert';\nimport { ResourceInfo } from '@milaboratories/pl-tree';\n\n/** Holds all info needed to upload a file and a status of uploading\n * and indexing. Also, has a method to update a status of the progress.\n * And holds a change source. */\nexport class UploadTask {\n private readonly change: ChangeSource = new ChangeSource();\n private readonly counter: CallersCounter = new CallersCounter();\n private nMaxUploads: number;\n private nPartsWithThisUploadSpeed = 0;\n private nPartsToIncreaseUpload = 10; // how many parts we have to wait to increase concurrency, 50 mb, 10 parts by 5 mb each.\n\n /** If this is upload progress this field will be defined */\n private uploadData?: ImportFileHandleUploadData;\n public progress: sdk.ImportProgress;\n\n /** If failed, then getting a progress is terminally failed. */\n public failed?: boolean;\n\n /** True if the blob was existed.\n * At this case, the task will show progress == 1.0. */\n private alreadyExisted = false;\n\n constructor(\n private readonly logger: MiLogger,\n private readonly clientBlob: ClientUpload,\n private readonly clientProgress: ClientProgress,\n private readonly maxNConcurrentPartsUpload: number,\n signer: Signer,\n public readonly res: ImportResourceSnapshot,\n ) {\n this.nMaxUploads = this.maxNConcurrentPartsUpload;\n const { uploadData, progress } = newProgress(res, signer);\n this.uploadData = uploadData;\n this.progress = progress;\n }\n\n public getProgress(w: Watcher, callerId: string) {\n this.incCounter(w, callerId);\n\n if (this.failed) {\n this.logger.error(`Uploading terminally failed: ${this.progress.lastError}`);\n throw new Error(this.progress.lastError);\n }\n\n return cloneProgress(this.progress);\n }\n\n public shouldScheduleUpload(): boolean {\n return isMyUpload(this.progress);\n }\n\n /** Uploads a blob if it's not BlobIndex. */\n public async uploadBlobTask() {\n try {\n await uploadBlob(\n this.logger,\n this.clientBlob,\n this.res,\n this.uploadData!,\n this.isComputableDone.bind(this),\n {\n nPartsWithThisUploadSpeed: this.nPartsWithThisUploadSpeed,\n nPartsToIncreaseUpload: this.nPartsToIncreaseUpload,\n currentSpeed: this.nMaxUploads,\n maxSpeed: this.maxNConcurrentPartsUpload,\n },\n );\n this.change.markChanged(`blob upload for ${resourceIdToString(this.res.id)} finished`);\n } catch (e: any) {\n this.setRetriableError(e);\n\n if (isResourceWasDeletedError(e)) {\n this.logger.warn(`resource was deleted while uploading a blob: ${e}`);\n this.change.markChanged(`blob upload for ${resourceIdToString(this.res.id)} aborted, resource was deleted`);\n this.setDone(true);\n\n return;\n }\n\n this.logger.error(`error while uploading a blob: ${e}`);\n this.change.markChanged(`blob upload for ${resourceIdToString(this.res.id)} failed`);\n\n if (nonRecoverableError(e)) {\n this.setTerminalError(e);\n return;\n }\n\n if (isHeadersTimeoutError(e)) {\n // we probably have a slow internet, we need to slow things a bit.\n this.nMaxUploads = decreaseConcurrency(this.logger, this.nMaxUploads, 1);\n }\n\n throw e;\n }\n }\n\n public async updateStatus() {\n try {\n // we do it with timeout in case we have slow internet.\n const status = await this.clientProgress.getStatus(this.res, { timeout: 10000 });\n\n const oldStatus = this.progress.status;\n const newStatus = doneProgressIfExisted(this.alreadyExisted, protoToStatus(status));\n this.progress.status = newStatus;\n this.setDone(status.done);\n\n if (status.done || this.progress.status.progress != oldStatus?.progress) {\n this.change.markChanged(`upload status for ${resourceIdToString(this.res.id)} changed`);\n }\n } catch (e: any) {\n this.setRetriableError(e);\n\n if ((e.name == 'RpcError' && e.code == 'DEADLINE_EXCEEDED') || e?.message?.includes('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(`upload status for ${resourceIdToString(this.res.id)} changed, resource not found`);\n this.setDone(true);\n return;\n }\n\n this.logger.error(`retryable error while updating a status of BlobImport: ${e}`);\n // It was a terminal error, but when a connection drops,\n // this will stop the whole task, so we make it retryable.\n // It was like that:\n // this.change.markChanged();\n // this.setTerminalError(e);\n }\n }\n\n /** Set non-terminal error, that task can be retried. */\n private setRetriableError(e: unknown) {\n this.progress.lastError = String(e);\n }\n\n /** Set a terminal error, the task will throw a error instead of a progress. */\n private setTerminalError(e: unknown) {\n this.progress.lastError = String(e);\n this.progress.done = false;\n this.failed = true;\n }\n\n public setDoneIfOutputSet(res: ImportResourceSnapshot) {\n if (isImportResourceOutputSet(res)) {\n this.setDone(true);\n this.alreadyExisted = true;\n }\n }\n\n private setDone(done: boolean) {\n this.progress.done = done;\n if (done) this.progress.lastError = undefined;\n }\n\n public incCounter(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 private isComputableDone() {\n return this.counter.isZero();\n }\n}\n\n/** Uploads a blob if it's not BlobIndex. */\nexport async function uploadBlob(\n logger: MiLogger,\n clientBlob: ClientUpload,\n res: ResourceInfo,\n uploadData: ImportFileHandleUploadData,\n isDoneFn: () => boolean,\n speed: {\n nPartsWithThisUploadSpeed: number,\n nPartsToIncreaseUpload: number,\n currentSpeed: number,\n maxSpeed: number,\n },\n) {\n assert(isUpload(res), 'the upload operation can be done only for BlobUploads');\n const timeout = 10000; // 10 sec instead of standard 5 sec, things might be slow with a slow connection.\n\n if (isDoneFn()) return;\n const parts = await clientBlob.initUpload(res, { timeout });\n logger.info(\n `started to upload blob ${res.id},`\n + ` parts overall: ${parts.overall}, parts remained: ${parts.toUpload.length},`\n + ` number of concurrent uploads: ${speed.currentSpeed}`,\n );\n\n const partUploadFn = (part: bigint) => async (controller: AsyncPoolController) => {\n if (isDoneFn()) return;\n await clientBlob.partUpload(\n res,\n uploadData.localPath,\n BigInt(uploadData.modificationTime),\n part,\n { timeout }\n );\n logger.info(`uploaded chunk ${part}/${parts.overall} of resource: ${res.id}`);\n\n // if we had a network freeze, it will be increased slowly.\n speed.nPartsWithThisUploadSpeed++;\n if (speed.nPartsWithThisUploadSpeed >= speed.nPartsToIncreaseUpload) {\n speed.nPartsWithThisUploadSpeed = 0;\n speed.currentSpeed = increaseConcurrency(logger, speed.currentSpeed, speed.maxSpeed);\n controller.setConcurrency(speed.currentSpeed);\n }\n };\n\n await asyncPool(speed.currentSpeed, parts.toUpload.map(partUploadFn));\n\n if (isDoneFn()) return;\n await clientBlob.finalize(res, { timeout });\n\n logger.info(`uploading of resource ${res.id} finished.`);\n}\n\nfunction newProgress(res: ImportResourceSnapshot, signer: Signer) {\n let isUploadSignMatch: boolean | undefined;\n let uploadData: ImportFileHandleUploadData | undefined;\n if (isUpload(res)) {\n uploadData = ImportFileHandleUploadData.parse(res.data);\n isUploadSignMatch = isSignMatch(signer, uploadData.localPath, uploadData.pathSignature);\n }\n\n return {\n uploadData: uploadData,\n progress: {\n done: false,\n status: undefined,\n isUpload: isUpload(res),\n isUploadSignMatch: isUploadSignMatch,\n lastError: undefined,\n } satisfies sdk.ImportProgress,\n };\n}\n\n/** Returns true if we need to upload the blob that got from this progress. */\nexport function isMyUpload(p: sdk.ImportProgress): boolean {\n return p.isUpload && (p.isUploadSignMatch ?? false);\n}\n\n/** Creates 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 * We do not use '...' cloning syntax\n * for the compiler to fail here if we change API. */\nfunction cloneProgress(progress: sdk.ImportProgress): sdk.ImportProgress {\n const cloned: sdk.ImportProgress = {\n done: progress.done,\n isUpload: progress.isUpload,\n isUploadSignMatch: progress.isUploadSignMatch,\n lastError: progress.lastError,\n };\n\n if (progress.status)\n cloned.status = {\n progress: progress.status.progress,\n bytesProcessed: progress.status.bytesProcessed,\n bytesTotal: progress.status.bytesTotal,\n };\n\n return progress;\n}\n\nfunction isImportResourceOutputSet(res: ImportResourceSnapshot) {\n return 'blob' in res.fields\n ? res.fields.blob !== undefined\n : res.fields.incarnation !== undefined;\n}\n\nexport function isUpload(res: ResourceInfo) {\n return res.type.name.startsWith('BlobUpload');\n}\n\nexport function 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 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\n/** Special hack: if we didn't even start to upload the blob\n * to backend because the result was already there,\n * the backend does show us a status that nothing were uploaded,\n * but we need to show the client that everything is OK.\n * Thus, here we set progress to be 1.0 and all bytes are become processed. */\nfunction doneProgressIfExisted(alreadyExisted: boolean, status: sdk.ImportStatus) {\n if (alreadyExisted && status.bytesTotal != 0 && status.bytesProcessed == 0) {\n return {\n progress: 1.0,\n bytesProcessed: Number(status.bytesTotal),\n bytesTotal: Number(status.bytesTotal),\n };\n }\n\n return status;\n}\n\nexport function isResourceWasDeletedError(e: any) {\n return (\n e.name == 'RpcError'\n && (e.code == 'NOT_FOUND' || e.code == 'ABORTED' || e.code == 'ALREADY_EXISTS')\n );\n}\n\nexport function nonRecoverableError(e: any) {\n return e instanceof MTimeError || e instanceof UnexpectedEOF || e instanceof NoFileForUploading;\n}\n\nfunction isHeadersTimeoutError(e: any) {\n return (e as Error)?.message.includes(`UND_ERR_HEADERS_TIMEOUT`);\n}\n\n/** It's called for every upload success so if everyone is succeeded, we'll double the concurrency. */\nfunction increaseConcurrency(logger: MiLogger, current: number, max: number): number {\n const newConcurrency = Math.min(current + 2, max);\n if (newConcurrency != current)\n logger.info(`uploadTask.increaseConcurrency: increased from ${current} to ${newConcurrency}`)\n\n return newConcurrency;\n}\n\n/** When a error happens, this will half the concurrency level, so the next time\n * we'll try to upload blobs slower. */\nfunction decreaseConcurrency(logger: MiLogger, current: number, min: number): number {\n const newConcurrency = Math.max(Math.round(current / 2), min);\n if (newConcurrency != current)\n logger.info(`uploadTask.decreaseConcurrency: decreased from ${current} to ${newConcurrency}`)\n\n return newConcurrency;\n}\n","import { randomUUID } from 'node:crypto';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport type {\n Watcher,\n ComputableCtx } from '@milaboratories/computable';\nimport {\n Computable,\n PollingComputableHooks,\n} from '@milaboratories/computable';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport { asyncPool, TaskProcessor } from '@milaboratories/ts-helpers';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { ClientProgress } from '../clients/progress';\nimport type { ClientUpload } from '../clients/upload';\nimport type {\n PlTreeEntry,\n PlTreeEntryAccessor,\n PlTreeNodeAccessor,\n} from '@milaboratories/pl-tree';\nimport {\n isPlTreeEntry,\n isPlTreeEntryAccessor,\n makeResourceSnapshot,\n} from '@milaboratories/pl-tree';\nimport { scheduler } from 'node:timers/promises';\nimport type { PollingOps } from './helpers/polling_ops';\nimport type { ImportResourceSnapshot } from './types';\nimport { IndexResourceSnapshot, UploadResourceSnapshot } from './types';\nimport { isMyUpload, nonRecoverableError, UploadTask } from './upload_task';\nimport { WrongResourceTypeError } from './helpers/helpers';\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\n if (node.resourceType.name.startsWith('BlobUpload'))\n return makeResourceSnapshot(node, UploadResourceSnapshot);\n 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, UploadTask> = 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\n return result;\n }\n\n private getProgressIdNoCtx(\n w: Watcher,\n res: ImportResourceSnapshot,\n callerId: string,\n ): sdk.ImportProgress {\n validateResourceType('getProgressId', res.type);\n\n const task = this.idToProgress.get(res.id);\n\n if (task != undefined) {\n task.setDoneIfOutputSet(res);\n return task.getProgress(w, callerId);\n }\n\n const newTask = new UploadTask(\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, newTask);\n\n if (newTask.shouldScheduleUpload()) {\n this.uploadQueue.push({\n fn: () => newTask.uploadBlobTask(),\n recoverableErrorPredicate: (e) => !nonRecoverableError(e),\n });\n }\n\n newTask.setDoneIfOutputSet(res);\n return newTask.getProgress(w, callerId);\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 task = this.idToProgress.get(id);\n if (task === undefined) return;\n\n const deleted = task.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<UploadTask> {\n return Array.from(this.idToProgress.entries())\n .filter(([_, p]) => !isProgressDone(p.progress))\n .map(([_, p]) => p);\n }\n}\n\nfunction isProgressDone(p: sdk.ImportProgress) {\n return p.done && (p.status?.progress ?? 0.0) >= 1.0;\n}\n\ntype ScheduledRefresh = {\n resolve: () => void;\n reject: (err: any) => void;\n};\n\nfunction validateResourceType(methodName: string, rType: ResourceType) {\n if (!rType.name.startsWith('BlobUpload') && !rType.name.startsWith('BlobIndex')) {\n throw new WrongResourceTypeError(\n `${methodName}: wrong resource type: ${rType.name}, `\n + `expected: a resource of either type 'BlobUpload' or 'BlobIndex'.`,\n );\n }\n}\n","import type {\n ComputableCtx,\n Watcher,\n} from '@milaboratories/computable';\nimport {\n ChangeSource,\n Computable,\n PollingComputableHooks,\n} from '@milaboratories/computable';\nimport type {\n ResourceId,\n ResourceType } from '@milaboratories/pl-client';\nimport {\n resourceIdToString,\n stringifyWithResourceId,\n} from '@milaboratories/pl-client';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { asyncPool, CallersCounter } from '@milaboratories/ts-helpers';\nimport type { ClientLogs } from '../clients/logs';\nimport { randomUUID } from 'node:crypto';\nimport type { PlTreeEntry, ResourceInfo } from '@milaboratories/pl-tree';\nimport { treeEntryToResourceInfo } from '@milaboratories/pl-tree';\nimport { scheduler } from 'node:timers/promises';\nimport type { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { PollingOps } from './helpers/polling_ops';\nimport type { RpcError } from '@protobuf-ts/runtime-rpc';\nimport { getResourceInfoFromLogHandle, isLiveLogHandle, newLogHandle } from './helpers/logs_handle';\nimport { WrongResourceTypeError } from './helpers/helpers';\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 validateResourceType('getLastLogs', rInfo.type);\n\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 validateResourceType('getProgressLog', rInfo.type);\n\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 validateResourceType('getLogHandle', rInfo.type);\n\n return newLogHandle(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 getResourceInfoFromLogHandle(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(\n getResourceInfoFromLogHandle(handle),\n lineCount,\n BigInt(offsetBytes ?? 0),\n searchStr,\n ),\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 = new TextDecoder().decode(resp.data);\n if (this.logs != newLogs) this.change.markChanged(`logs for ${resourceIdToString(this.rInfo.id)} updated`);\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\nfunction validateResourceType(methodName: string, rType: ResourceType) {\n if (!rType.name.startsWith('StreamWorkdir')) {\n throw new WrongResourceTypeError(\n `${methodName}: wrong resource type: ${rType.name}, `\n + `expected: a resource of type 'StreamWorkdir'.`,\n );\n }\n}\n","import type { ComputableCtx } from '@milaboratories/computable';\nimport { Computable } from '@milaboratories/computable';\nimport type { PlTreeEntry, ResourceInfo } from '@milaboratories/pl-tree';\nimport type { LogsStreamDriver } from './logs_stream';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport type { DownloadDriver } from './download_blob/download_blob';\nimport { isLiveLogHandle } from './helpers/logs_handle';\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 /** Same as getProgressLog but also returns a liveliness of the log.\n * The previous getProgressLog couldn't be extended.\n * Returns a last line that has patternToSearch.\n * Notifies when a new line appeared or EOF reached. */\n getProgressLogWithInfo(res: PlTreeEntry, patternToSearch: string): Computable<sdk.ProgressLogWithInfo | undefined>;\n getProgressLogWithInfo(res: PlTreeEntry, patternToSearch: string, ctx: ComputableCtx): sdk.ProgressLogWithInfo | undefined;\n getProgressLogWithInfo(\n res: PlTreeEntry,\n patternToSearch: string,\n ctx?: ComputableCtx,\n ): Computable<sdk.ProgressLogWithInfo | undefined> | sdk.ProgressLogWithInfo | undefined {\n if (ctx === undefined)\n return Computable.make((ctx) => this.getProgressLogWithInfo(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)) {\n const log = this.downloadDriver.getProgressLog(stream, patternToSearch, ctx);\n return {\n progressLine: log,\n live: false,\n }\n }\n\n try {\n const log = this.logsStreamDriver.getProgressLog(stream, patternToSearch, ctx);\n return {\n progressLine: log,\n live: true,\n }\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 with info: ${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","import type { Watcher } from '@milaboratories/computable';\nimport { ChangeSource } from '@milaboratories/computable';\nimport type {\n MiLogger,\n Signer,\n} from '@milaboratories/ts-helpers';\nimport {\n CallersCounter,\n createPathAtomically,\n ensureDirExists,\n fileExists,\n notEmpty,\n} from '@milaboratories/ts-helpers';\nimport * as fsp from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { Transform, Writable } from 'node:stream';\nimport * as zlib from 'node:zlib';\nimport * as tar from 'tar-fs';\nimport type { RemoteFileDownloader } from '../../helpers/download';\nimport { NetworkError400 } from '../../helpers/download';\nimport type { UrlResult } from './driver';\nimport { newBlockUIURL } from '../urls/url';\n\n/** Downloads and extracts an archive to a directory. */\nexport class DownloadByUrlTask {\n readonly counter = new CallersCounter();\n readonly change = new ChangeSource();\n private readonly signalCtl = new AbortController();\n error: string | undefined;\n done = false;\n size = 0;\n\n constructor(\n private readonly logger: MiLogger,\n readonly path: string,\n readonly url: URL,\n readonly signer: Signer,\n readonly saveDir: string,\n ) { }\n\n public info() {\n return {\n url: this.url.toString(),\n path: this.path,\n done: this.done,\n size: this.size,\n error: this.error,\n };\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: RemoteFileDownloader, withGunzip: boolean) {\n try {\n const size = await this.downloadAndUntar(clientDownload, withGunzip, this.signalCtl.signal);\n this.setDone(size);\n this.change.markChanged(`download of ${this.url} finished`);\n } catch (e: unknown) {\n if (e instanceof URLAborted || e instanceof NetworkError400) {\n this.setError(e);\n this.change.markChanged(`download of ${this.url} failed`);\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: RemoteFileDownloader,\n withGunzip: boolean,\n signal: AbortSignal,\n ): Promise<number> {\n await ensureDirExists(path.dirname(this.path));\n\n if (await fileExists(this.path)) {\n return await dirSize(this.path);\n }\n\n const size = await clientDownload.withContent(\n this.url.toString(), \n {}, \n { signal },\n async (content, size) => {\n let processedContent = content;\n if (withGunzip) {\n const gunzip = Transform.toWeb(zlib.createGunzip());\n processedContent = content.pipeThrough(gunzip, { signal });\n }\n\n await createPathAtomically(this.logger, this.path, async (fPath: string) => {\n await fsp.mkdir(fPath); // throws if a directory already exists.\n const untar = Writable.toWeb(tar.extract(fPath));\n await processedContent.pipeTo(untar, { signal });\n });\n\n return size;\n }\n );\n\n return size;\n }\n\n getUrl(): UrlResult | undefined {\n if (this.done) return {\n url: newBlockUIURL(this.signer, this.saveDir, notEmpty(this.path))\n };\n\n if (this.error) return { error: this.error };\n\n return undefined;\n }\n\n private setDone(size: number) {\n this.done = true;\n this.size = size;\n }\n\n private setError(e: any) {\n this.error = String(e);\n }\n\n abort(reason: string) {\n this.signalCtl.abort(new URLAborted(reason));\n }\n}\n\n/** Throws when a downloading aborts. */\nexport class URLAborted extends Error {\n name = 'URLAborted';\n}\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: any) => {\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: any, size: any) => sum + size, 0);\n}\n\n/** Do rm -rf on dir. */\nexport async function rmRFDir(path: string) {\n await fsp.rm(path, { recursive: true, force: true });\n}\n","import type { ComputableCtx, Watcher } from '@milaboratories/computable';\nimport { Computable } from '@milaboratories/computable';\nimport type {\n MiLogger,\n Signer,\n} from '@milaboratories/ts-helpers';\nimport {\n TaskProcessor,\n} from '@milaboratories/ts-helpers';\nimport { createHash, randomUUID } from 'node:crypto';\nimport * as path from 'node:path';\nimport type { Dispatcher } from 'undici';\nimport { RemoteFileDownloader } from '../../helpers/download';\nimport { FilesCache } from '../helpers/files_cache';\nimport { stringifyWithResourceId } from '@milaboratories/pl-client';\nimport type { BlockUIURL, FrontendDriver } from '@milaboratories/pl-model-common';\nimport { isBlockUIURL } from '@milaboratories/pl-model-common';\nimport { getPathForBlockUIURL } from '../urls/url';\nimport { DownloadByUrlTask, rmRFDir } from './task';\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 getUrl(url: URL): Computable<UrlResult | undefined>;\n}\n\nexport interface UrlResult {\n /** Path to the downloadable blob along with the signature and a custom protocol,\n * might be undefined when the error happened. */\n url?: BlockUIURL;\n /** Error that happened when the archive were downloaded. */\n error?: string;\n}\n\nexport type DownloadUrlDriverOps = {\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 /** Whether to gunzip the downloaded archive (it will be untared automatically). */\n withGunzip: boolean;\n\n /** Max number of concurrent downloads while calculating computable states\n * derived from this driver.\n * */\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, FrontendDriver {\n private readonly downloadHelper: RemoteFileDownloader;\n\n private urlToDownload: Map<string, DownloadByUrlTask> = 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<DownloadByUrlTask>;\n\n constructor(\n private readonly logger: MiLogger,\n httpClient: Dispatcher,\n private readonly saveDir: string,\n private readonly signer: Signer,\n private readonly opts: DownloadUrlDriverOps = {\n cacheSoftSizeBytes: 1 * 1024 * 1024 * 1024, // 1 GB\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 RemoteFileDownloader(httpClient);\n }\n\n /** Use to get a path result inside a computable context */\n getUrl(url: URL, ctx: ComputableCtx): UrlResult | undefined;\n\n /** Returns a Computable that do the work */\n getUrl(url: URL): Computable<UrlResult | undefined>;\n\n /** Returns a computable that returns a custom protocol URL to the downloaded and unarchived path. */\n getUrl(\n url: URL,\n ctx?: ComputableCtx,\n ): Computable<UrlResult | undefined> | UrlResult | undefined {\n // wrap result as computable, if we were not given an existing computable context\n if (ctx === undefined) return Computable.make((c) => this.getUrl(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.getUrlNoCtx(url, ctx.watcher, callerId);\n if (result?.url === 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 getUrlNoCtx(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.getUrl();\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.getUrl();\n }\n\n getPathForBlockUI(url: string): string {\n if (!isBlockUIURL(url)) {\n throw new Error(`getPathForBlockUI: ${url} is invalid`);\n }\n\n return getPathForBlockUIURL(this.signer, url, this.saveDir);\n }\n\n /** Downloads and extracts a tar archive if it wasn't downloaded yet. */\n async downloadUrl(task: DownloadByUrlTask, callerId: string) {\n await task.download(this.downloadHelper, this.opts.withGunzip);\n // Might be undefined if a error happened\n if (task.getUrl()?.url !== 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: DownloadByUrlTask) => {\n await rmRFDir(task.path);\n this.cache.removeCache(task);\n\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed`\n + `from cache along with ${stringifyWithResourceId(toDelete.map((t) => t.info()))}`,\n );\n }),\n );\n } else {\n // The task is still in a downloading queue.\n const deleted = task.counter.dec(callerId);\n if (deleted)\n this.removeTask(\n task,\n `the task ${stringifyWithResourceId(task.info())} was removed from cache`,\n );\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(\n task,\n `the task ${stringifyWithResourceId(task.info())} was released when the driver was closed`,\n );\n }),\n );\n }\n\n private setNewTask(w: Watcher, url: URL, callerId: string) {\n const result = new DownloadByUrlTask(\n this.logger,\n this.getFilePath(url),\n url,\n this.signer,\n this.saveDir,\n );\n result.attach(w, callerId);\n this.urlToDownload.set(url.toString(), result);\n\n return result;\n }\n\n private removeTask(task: DownloadByUrlTask, reason: string) {\n task.abort(reason);\n task.change.markChanged(`task for url ${task.url} removed: ${reason}`);\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","import type * as sdk from '@milaboratories/pl-model-common';\nimport type { Signer } from '@milaboratories/ts-helpers';\nimport { ImportFileHandleIndexData, ImportFileHandleUploadData } from '../types';\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","import type * as sdk from '@milaboratories/pl-model-common';\nimport type { ResourceId, ResourceType } from '@milaboratories/pl-client';\nimport { bigintToResourceId } 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 type { 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 type { PlClient, ResourceData, ResourceId } from '@milaboratories/pl-client';\nimport { isNotNullResourceId } from '@milaboratories/pl-client';\nimport type { MiLogger, Signer } from '@milaboratories/ts-helpers';\nimport type * as sdk from '@milaboratories/pl-model-common';\nimport type {\n LocalImportFileHandle,\n LsEntry,\n OpenDialogOps,\n OpenMultipleFilesResponse,\n OpenSingleFileResponse,\n TableRange,\n} from '@milaboratories/pl-model-common';\nimport {\n isImportFileHandleIndex,\n} from '@milaboratories/pl-model-common';\nimport type { 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_remote_import_handle';\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle,\n} from './helpers/ls_storage_entry';\nimport type { LocalStorageProjection, VirtualLocalStorageSpec } from './types';\nimport { validateAbsolute } from '../helpers/validate';\nimport { DefaultVirtualLocalStorages } from './virtual_storages';\nimport { createLsFilesClient } from '../clients/constructors';\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 listRemoteFilesWithAdditionalInfo(storage: sdk.StorageHandle, fullPath: string): Promise<ListRemoteFilesResultWithAdditionalInfo>;\n}\n\nexport type ListRemoteFilesResultWithAdditionalInfo = {\n parent?: string;\n entries: LsEntryWithAdditionalInfo[];\n};\n\nexport type LsEntryWithAdditionalInfo = LsEntry & {\n size: number;\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 }\n\n if (path.sep === '/' && fullPath === '') fullPath = '/';\n\n if (storageData.rootPath === '') {\n validateAbsolute(fullPath);\n }\n const lsRoot = path.isAbsolute(fullPath) ? fullPath : 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 public async listRemoteFilesWithAdditionalInfo(\n storageHandle: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithAdditionalInfo> {\n const storageData = parseStorageHandle(storageHandle);\n if (!storageData.isRemote) {\n throw new Error(`Storage ${storageData.name} is not remote`);\n }\n\n const response = await this.lsClient.list(storageData, fullPath);\n\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 size: Number(e.size),\n })),\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","end","fieldNo","wireType","u","UnknownFieldHandler","writer","uploadapi_Init$Type","uploadapi_Init_Request$Type","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","grpcClientProviderFactory","httpClient","_","logger","transport","id","type","init","path","expectedMTimeUnix","partNumber","info","chunk","readFileChunk","checkExpectedMTime","contentLength","headers","name","contentLengthKey","key","existingContentLength","rawBody","statusCode","responseHeaders","request","body","checkStatusCodeOk","partsCount","uploadedParts","toUpload","uploaded","addRTypeToMetadata","uploadedPartSize","bytesProcessed","chunkStart","chunkEnd","f","fs","len","pos","b","bytesRead","readBytesFromPosition","position","bytesReadTotal","mTime","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","NetworkError400","RemoteFileDownloader","url","reqHeaders","ops","handler","webBody","Readable","handlerSuccess","size","result","error","beginning","validateAbsolute","p","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","ClientDownload","localProjections","ConcurrencyLimitingExecutor","newLocalStorageIdsToRoot","downloadUrl","remoteHeaders","stringifyWithResourceId","isLocal","storageId","relativePath","parseLocalUrl","fullPath","getFullPath","readOps","_a","_b","stream","stat","fsp","webStream","signal","withAbort","parsed","WrongLocalFileUrl","localStorageIdsToRoot","root","UnknownStorageError","storageProtocol","projections","idToRoot","lp","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","fileReadLimiter","readFileContent","range","buffer","localHandleRegex","newLocalHandle","signer","isLocalBlobHandle","handle","parseLocalHandle","signature","OnDemandBlobResourceSnapshot","rsSchema","getSize","bs","newSize","ImportFileHandleUploadData","ImportFileHandleIndexData","ImportFileHandleData","UploadResourceSnapshot","IndexResourceSnapshot","remoteHandleRegex","newRemoteHandle","content","isRemoteBlobHandle","parseRemoteHandle","resourceType","resourceVersion","resourceId","bigintToResourceId","WrongResourceTypeError","Updater","onUpdate","newLogHandle","live","liveHandleRegex","isLiveLogHandle","readyHandleRegex","isReadyLogHandle","getResourceInfoFromLogHandle","blobKey","pathToKey","fPath","DownloadBlobTask","clientDownload","ChangeSource","CallersCounter","w","callerId","resourceIdToString","nonRecoverableError","ensureDirExists","alreadyExists","fileExists","createPathAtomically","Writable","reason","DownloadAborted","getDownloadedBlobResponse","sizeBytes","FilesCache","softSizeBytes","file","mapGet","freedBytes","mapEntries","created","Ranges","RangeBytes","rangesFilePostfix","rangesFileName","readRangesFile","ranges","CorruptedRangesError","normalizeRanges","writeRangesFile","tempPath","a","mergeRanges","from","to","rangesSize","acc","doesRangeExist","allRanges","r","addRange","createSparseFile","platform","ensureSparseOnWindows","spawnAsync","writeToSparseFile","data","fileHandle","SparseCacheFsRanges","cacheDir","SparseCacheFsFile","SparseCache","maxSize","storage","functions","withLock","now","newRanges","byTime","aDate","__","bDate","keyAndDate","lock","cb","DownloadDriver","clientLogs","saveDir","rangesCacheDir","fsRanges","fsStorage","TaskProcessor","driver","res","ctx","Computable","treeEntryToResourceInfo","randomUUID","validateDownloadableResourceType","task","inMemoryTask","newTask","blob","isPlTreeEntry","makeResourceSnapshot","OnDemandBlobHolder","validateRangeBytes","filePath","v","lines","logGetter","newLogGetter","LastLinesGetter","patternToSearch","resp","toDelete","cachedFile","d","blobId","newLogs","getLastLines","nLines","inStream","rl","readline","Denque","line","os","cleanupError","methodName","DownloadableBlobSnapshot","makeDownloadableBlobSnapshot","entryOrAccessor","node","isPlTreeEntryAccessor","newFolderURL","newBlockUIURL","getPathForFolderURL","rootDir","getPath","getPathForBlockUIURL","subfolder","pathname","parseNestedPathNoEscape","baseDir","userInputPath","absolutePath","normalizedBase","DownloadAndUnarchiveTask","format","rmRFDir","dirSize","simpleUntar","tar","gunzip","Transform","zlib","untar","decompress","assertNever","URLAborted","dir","files","sum","newId","DownloadBlobToURLDriver","opts","isFolderURL","c","t","UploadTask","clientBlob","clientProgress","maxNConcurrentPartsUpload","uploadData","progress","newProgress","cloneProgress","isMyUpload","uploadBlob","isResourceWasDeletedError","isHeadersTimeoutError","decreaseConcurrency","oldStatus","newStatus","doneProgressIfExisted","protoToStatus","isImportResourceOutputSet","done","isDoneFn","speed","assert","isUpload","timeout","parts","partUploadFn","part","controller","increaseConcurrency","asyncPool","isUploadSignMatch","isSignMatch","proto","alreadyExisted","current","max","newConcurrency","min","makeBlobImportSnapshot","UploadDriver","PollingComputableHooks","resolve","reject","handleResource","validateResourceType","toNotify","n","scheduler","isProgressDone","LogsStreamDriver","LogGetter","logs","getter","LogsDriver","logsStreamDriver","downloadDriver","streamManagerGetStream","isBlob","manager","DownloadByUrlTask","withGunzip","processedContent","DownloadUrlDriver","isBlockUIURL","sha256","createHash","createIndexImportHandle","storageName","createUploadImportHandle","localPath","modificationTimeSeconds","parseUploadHandle","parseIndexHandle","parseStorageHandle","isRemoteStorageHandle","parseRemoteStorageHandle","isLocalStorageHandle","parseLocalStorageHandle","createLocalStorageHandle","createRemoteStorageHandle","storageType","DefaultVirtualLocalStorages","home","homeDrive","util","exec","drive","isHomeDrive","LsDriver","lsClient","storageIdToResourceId","virtualStoragesMap","localProjectionsMap","openFileDialogCallback","isImportFileHandleIndex","handleData","localProjection","pathWithinStorage","virtualStorages","noRoot","it","storageHandle","storageData","lsRoot","entries","dirent","vp","doGetAvailableStorageIds","tx","lsProviderId","provider","providerToStorageIds","isNotNullResourceId"],"mappings":"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"}