@milaboratories/pl-drivers 1.14.16 → 1.15.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.
Files changed (36) hide show
  1. package/dist/clients/ls_api.cjs +1 -0
  2. package/dist/clients/ls_api.cjs.map +1 -1
  3. package/dist/clients/ls_api.js +1 -0
  4. package/dist/clients/ls_api.js.map +1 -1
  5. package/dist/drivers/helpers/ls_remote_import_handle.cjs +5 -3
  6. package/dist/drivers/helpers/ls_remote_import_handle.cjs.map +1 -1
  7. package/dist/drivers/helpers/ls_remote_import_handle.js +5 -3
  8. package/dist/drivers/helpers/ls_remote_import_handle.js.map +1 -1
  9. package/dist/drivers/ls.cjs +3 -3
  10. package/dist/drivers/ls.cjs.map +1 -1
  11. package/dist/drivers/ls.d.ts +6 -6
  12. package/dist/drivers/ls.d.ts.map +1 -1
  13. package/dist/drivers/ls.js +3 -3
  14. package/dist/drivers/ls.js.map +1 -1
  15. package/dist/drivers/types.cjs +2 -1
  16. package/dist/drivers/types.cjs.map +1 -1
  17. package/dist/drivers/types.d.ts +14 -0
  18. package/dist/drivers/types.d.ts.map +1 -1
  19. package/dist/drivers/types.js +2 -1
  20. package/dist/drivers/types.js.map +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.cjs +31 -0
  23. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.cjs.map +1 -1
  24. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.d.ts +11 -0
  25. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.d.ts.map +1 -1
  26. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.js +31 -0
  27. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.js.map +1 -1
  28. package/package.json +5 -5
  29. package/src/clients/ls_api.ts +1 -0
  30. package/src/drivers/helpers/ls_remote_import_handle.test.ts +46 -0
  31. package/src/drivers/helpers/ls_remote_import_handle.ts +6 -0
  32. package/src/drivers/ls.test.ts +138 -2
  33. package/src/drivers/ls.ts +9 -9
  34. package/src/drivers/types.ts +5 -0
  35. package/src/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.ts +34 -0
  36. package/src/proto-rest/lsapi.ts +8 -0
@@ -39,6 +39,7 @@ var ClientLs = class {
39
39
  name: item.name,
40
40
  size: BigInt(item.size),
41
41
  isDir: item.isDir,
42
+ additionalInfo: item.additionalInfo ?? {},
42
43
  fullName: item.fullName,
43
44
  directory: item.directory,
44
45
  lastModified: parseTimestamp(item.lastModified),
@@ -1 +1 @@
1
- {"version":3,"file":"ls_api.cjs","names":["LSClient","RestAPI"],"sources":["../../src/clients/ls_api.ts"],"sourcesContent":["import type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { RpcOptions } from \"@protobuf-ts/runtime-rpc\";\nimport type { WireClientProvider, WireClientProviderFactory } from \"@milaboratories/pl-client\";\nimport { RestAPI, parseSignedResourceId, signatureToBase64Url } from \"@milaboratories/pl-client\";\nimport { addRTypeToMetadata, createRTypeRoutingHeader } from \"@milaboratories/pl-client\";\nimport type {\n LsAPI_List_Response,\n LsAPI_ListItem,\n} from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol\";\nimport { LSClient } from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client\";\nimport type { LsApiPaths, LsRestClientType } from \"../proto-rest\";\n\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\n\nexport class ClientLs {\n private readonly wire: WireClientProvider<LsRestClientType | LSClient>;\n\n constructor(\n wireClientProviderFactory: WireClientProviderFactory,\n private readonly logger: MiLogger,\n ) {\n this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {\n if (wire.type === \"grpc\") {\n return new LSClient(wire.Transport);\n }\n\n return RestAPI.createClient<LsApiPaths>({\n hostAndPort: wire.Config.hostAndPort,\n ssl: wire.Config.ssl,\n dispatcher: wire.Dispatcher,\n middlewares: wire.Middlewares,\n });\n });\n }\n\n close() {}\n\n public async list(\n rInfo: ResourceInfo,\n path: string,\n options?: RpcOptions,\n ): Promise<LsAPI_List_Response> {\n const client = this.wire.get();\n\n const { globalId, signature } = parseSignedResourceId(rInfo.id);\n if (client instanceof LSClient) {\n return await client.list(\n {\n resourceId: globalId,\n resourceSignature: signature,\n location: path,\n },\n addRTypeToMetadata(rInfo.type, options),\n ).response;\n } else {\n const resp = (\n await client.POST(\"/v1/list\", {\n body: {\n resourceId: globalId.toString(),\n resourceSignature: signatureToBase64Url(signature),\n location: path,\n },\n headers: { ...createRTypeRoutingHeader(rInfo.type) },\n })\n ).data!;\n\n const items: LsAPI_ListItem[] = resp.items.map((item) => ({\n name: item.name,\n size: BigInt(item.size),\n isDir: item.isDir,\n fullName: item.fullName,\n directory: item.directory,\n lastModified: parseTimestamp(item.lastModified),\n version: item.version,\n }));\n\n return {\n items,\n delimiter: resp.delimiter,\n };\n }\n }\n}\n\nfunction parseTimestamp(timestamp: string): { seconds: bigint; nanos: number } {\n // Parse ISO 8601 format: 2025-08-08T11:12:44.145635532Z\n const date = new Date(timestamp);\n const seconds = BigInt(Math.floor(date.getTime() / 1000));\n\n // Extract fractional seconds from the original string\n const fractionalMatch = timestamp.match(/\\.(\\d+)Z?$/);\n let nanos = 0;\n if (fractionalMatch) {\n const fractionalPart = fractionalMatch[1];\n // Pad or truncate to 9 digits (nanoseconds)\n const padded = fractionalPart.padEnd(9, \"0\").slice(0, 9);\n nanos = parseInt(padded, 10);\n }\n\n return { seconds, nanos };\n}\n"],"mappings":";;;;AAcA,IAAa,WAAb,MAAsB;CACpB;CAEA,YACE,2BACA,QACA;AADiB,OAAA,SAAA;AAEjB,OAAK,OAAO,0BAA0B,0BAA0B,SAAS;AACvE,OAAI,KAAK,SAAS,OAChB,QAAO,IAAIA,wBAAAA,SAAS,KAAK,UAAU;AAGrC,UAAOC,0BAAAA,QAAQ,aAAyB;IACtC,aAAa,KAAK,OAAO;IACzB,KAAK,KAAK,OAAO;IACjB,YAAY,KAAK;IACjB,aAAa,KAAK;IACnB,CAAC;IACF;;CAGJ,QAAQ;CAER,MAAa,KACX,OACA,MACA,SAC8B;EAC9B,MAAM,SAAS,KAAK,KAAK,KAAK;EAE9B,MAAM,EAAE,UAAU,eAAA,GAAA,0BAAA,uBAAoC,MAAM,GAAG;AAC/D,MAAI,kBAAkBD,wBAAAA,SACpB,QAAO,MAAM,OAAO,KAClB;GACE,YAAY;GACZ,mBAAmB;GACnB,UAAU;GACX,GAAA,GAAA,0BAAA,oBACkB,MAAM,MAAM,QAAQ,CACxC,CAAC;OACG;GACL,MAAM,QACJ,MAAM,OAAO,KAAK,YAAY;IAC5B,MAAM;KACJ,YAAY,SAAS,UAAU;KAC/B,oBAAA,GAAA,0BAAA,sBAAwC,UAAU;KAClD,UAAU;KACX;IACD,SAAS,EAAE,IAAA,GAAA,0BAAA,0BAA4B,MAAM,KAAK,EAAE;IACrD,CAAC,EACF;AAYF,UAAO;IACL,OAX8B,KAAK,MAAM,KAAK,UAAU;KACxD,MAAM,KAAK;KACX,MAAM,OAAO,KAAK,KAAK;KACvB,OAAO,KAAK;KACZ,UAAU,KAAK;KACf,WAAW,KAAK;KAChB,cAAc,eAAe,KAAK,aAAa;KAC/C,SAAS,KAAK;KACf,EAAE;IAID,WAAW,KAAK;IACjB;;;;AAKP,SAAS,eAAe,WAAuD;CAE7E,MAAM,OAAO,IAAI,KAAK,UAAU;CAChC,MAAM,UAAU,OAAO,KAAK,MAAM,KAAK,SAAS,GAAG,IAAK,CAAC;CAGzD,MAAM,kBAAkB,UAAU,MAAM,aAAa;CACrD,IAAI,QAAQ;AACZ,KAAI,iBAAiB;EAGnB,MAAM,SAFiB,gBAAgB,GAET,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE;AACxD,UAAQ,SAAS,QAAQ,GAAG;;AAG9B,QAAO;EAAE;EAAS;EAAO"}
1
+ {"version":3,"file":"ls_api.cjs","names":["LSClient","RestAPI"],"sources":["../../src/clients/ls_api.ts"],"sourcesContent":["import type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { RpcOptions } from \"@protobuf-ts/runtime-rpc\";\nimport type { WireClientProvider, WireClientProviderFactory } from \"@milaboratories/pl-client\";\nimport { RestAPI, parseSignedResourceId, signatureToBase64Url } from \"@milaboratories/pl-client\";\nimport { addRTypeToMetadata, createRTypeRoutingHeader } from \"@milaboratories/pl-client\";\nimport type {\n LsAPI_List_Response,\n LsAPI_ListItem,\n} from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol\";\nimport { LSClient } from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client\";\nimport type { LsApiPaths, LsRestClientType } from \"../proto-rest\";\n\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\n\nexport class ClientLs {\n private readonly wire: WireClientProvider<LsRestClientType | LSClient>;\n\n constructor(\n wireClientProviderFactory: WireClientProviderFactory,\n private readonly logger: MiLogger,\n ) {\n this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {\n if (wire.type === \"grpc\") {\n return new LSClient(wire.Transport);\n }\n\n return RestAPI.createClient<LsApiPaths>({\n hostAndPort: wire.Config.hostAndPort,\n ssl: wire.Config.ssl,\n dispatcher: wire.Dispatcher,\n middlewares: wire.Middlewares,\n });\n });\n }\n\n close() {}\n\n public async list(\n rInfo: ResourceInfo,\n path: string,\n options?: RpcOptions,\n ): Promise<LsAPI_List_Response> {\n const client = this.wire.get();\n\n const { globalId, signature } = parseSignedResourceId(rInfo.id);\n if (client instanceof LSClient) {\n return await client.list(\n {\n resourceId: globalId,\n resourceSignature: signature,\n location: path,\n },\n addRTypeToMetadata(rInfo.type, options),\n ).response;\n } else {\n const resp = (\n await client.POST(\"/v1/list\", {\n body: {\n resourceId: globalId.toString(),\n resourceSignature: signatureToBase64Url(signature),\n location: path,\n },\n headers: { ...createRTypeRoutingHeader(rInfo.type) },\n })\n ).data!;\n\n const items: LsAPI_ListItem[] = resp.items.map((item) => ({\n name: item.name,\n size: BigInt(item.size),\n isDir: item.isDir,\n additionalInfo: item.additionalInfo ?? {},\n fullName: item.fullName,\n directory: item.directory,\n lastModified: parseTimestamp(item.lastModified),\n version: item.version,\n }));\n\n return {\n items,\n delimiter: resp.delimiter,\n };\n }\n }\n}\n\nfunction parseTimestamp(timestamp: string): { seconds: bigint; nanos: number } {\n // Parse ISO 8601 format: 2025-08-08T11:12:44.145635532Z\n const date = new Date(timestamp);\n const seconds = BigInt(Math.floor(date.getTime() / 1000));\n\n // Extract fractional seconds from the original string\n const fractionalMatch = timestamp.match(/\\.(\\d+)Z?$/);\n let nanos = 0;\n if (fractionalMatch) {\n const fractionalPart = fractionalMatch[1];\n // Pad or truncate to 9 digits (nanoseconds)\n const padded = fractionalPart.padEnd(9, \"0\").slice(0, 9);\n nanos = parseInt(padded, 10);\n }\n\n return { seconds, nanos };\n}\n"],"mappings":";;;;AAcA,IAAa,WAAb,MAAsB;CACpB;CAEA,YACE,2BACA,QACA;AADiB,OAAA,SAAA;AAEjB,OAAK,OAAO,0BAA0B,0BAA0B,SAAS;AACvE,OAAI,KAAK,SAAS,OAChB,QAAO,IAAIA,wBAAAA,SAAS,KAAK,UAAU;AAGrC,UAAOC,0BAAAA,QAAQ,aAAyB;IACtC,aAAa,KAAK,OAAO;IACzB,KAAK,KAAK,OAAO;IACjB,YAAY,KAAK;IACjB,aAAa,KAAK;IACnB,CAAC;IACF;;CAGJ,QAAQ;CAER,MAAa,KACX,OACA,MACA,SAC8B;EAC9B,MAAM,SAAS,KAAK,KAAK,KAAK;EAE9B,MAAM,EAAE,UAAU,eAAA,GAAA,0BAAA,uBAAoC,MAAM,GAAG;AAC/D,MAAI,kBAAkBD,wBAAAA,SACpB,QAAO,MAAM,OAAO,KAClB;GACE,YAAY;GACZ,mBAAmB;GACnB,UAAU;GACX,GAAA,GAAA,0BAAA,oBACkB,MAAM,MAAM,QAAQ,CACxC,CAAC;OACG;GACL,MAAM,QACJ,MAAM,OAAO,KAAK,YAAY;IAC5B,MAAM;KACJ,YAAY,SAAS,UAAU;KAC/B,oBAAA,GAAA,0BAAA,sBAAwC,UAAU;KAClD,UAAU;KACX;IACD,SAAS,EAAE,IAAA,GAAA,0BAAA,0BAA4B,MAAM,KAAK,EAAE;IACrD,CAAC,EACF;AAaF,UAAO;IACL,OAZ8B,KAAK,MAAM,KAAK,UAAU;KACxD,MAAM,KAAK;KACX,MAAM,OAAO,KAAK,KAAK;KACvB,OAAO,KAAK;KACZ,gBAAgB,KAAK,kBAAkB,EAAE;KACzC,UAAU,KAAK;KACf,WAAW,KAAK;KAChB,cAAc,eAAe,KAAK,aAAa;KAC/C,SAAS,KAAK;KACf,EAAE;IAID,WAAW,KAAK;IACjB;;;;AAKP,SAAS,eAAe,WAAuD;CAE7E,MAAM,OAAO,IAAI,KAAK,UAAU;CAChC,MAAM,UAAU,OAAO,KAAK,MAAM,KAAK,SAAS,GAAG,IAAK,CAAC;CAGzD,MAAM,kBAAkB,UAAU,MAAM,aAAa;CACrD,IAAI,QAAQ;AACZ,KAAI,iBAAiB;EAGnB,MAAM,SAFiB,gBAAgB,GAET,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE;AACxD,UAAQ,SAAS,QAAQ,GAAG;;AAG9B,QAAO;EAAE;EAAS;EAAO"}
@@ -38,6 +38,7 @@ var ClientLs = class {
38
38
  name: item.name,
39
39
  size: BigInt(item.size),
40
40
  isDir: item.isDir,
41
+ additionalInfo: item.additionalInfo ?? {},
41
42
  fullName: item.fullName,
42
43
  directory: item.directory,
43
44
  lastModified: parseTimestamp(item.lastModified),
@@ -1 +1 @@
1
- {"version":3,"file":"ls_api.js","names":[],"sources":["../../src/clients/ls_api.ts"],"sourcesContent":["import type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { RpcOptions } from \"@protobuf-ts/runtime-rpc\";\nimport type { WireClientProvider, WireClientProviderFactory } from \"@milaboratories/pl-client\";\nimport { RestAPI, parseSignedResourceId, signatureToBase64Url } from \"@milaboratories/pl-client\";\nimport { addRTypeToMetadata, createRTypeRoutingHeader } from \"@milaboratories/pl-client\";\nimport type {\n LsAPI_List_Response,\n LsAPI_ListItem,\n} from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol\";\nimport { LSClient } from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client\";\nimport type { LsApiPaths, LsRestClientType } from \"../proto-rest\";\n\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\n\nexport class ClientLs {\n private readonly wire: WireClientProvider<LsRestClientType | LSClient>;\n\n constructor(\n wireClientProviderFactory: WireClientProviderFactory,\n private readonly logger: MiLogger,\n ) {\n this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {\n if (wire.type === \"grpc\") {\n return new LSClient(wire.Transport);\n }\n\n return RestAPI.createClient<LsApiPaths>({\n hostAndPort: wire.Config.hostAndPort,\n ssl: wire.Config.ssl,\n dispatcher: wire.Dispatcher,\n middlewares: wire.Middlewares,\n });\n });\n }\n\n close() {}\n\n public async list(\n rInfo: ResourceInfo,\n path: string,\n options?: RpcOptions,\n ): Promise<LsAPI_List_Response> {\n const client = this.wire.get();\n\n const { globalId, signature } = parseSignedResourceId(rInfo.id);\n if (client instanceof LSClient) {\n return await client.list(\n {\n resourceId: globalId,\n resourceSignature: signature,\n location: path,\n },\n addRTypeToMetadata(rInfo.type, options),\n ).response;\n } else {\n const resp = (\n await client.POST(\"/v1/list\", {\n body: {\n resourceId: globalId.toString(),\n resourceSignature: signatureToBase64Url(signature),\n location: path,\n },\n headers: { ...createRTypeRoutingHeader(rInfo.type) },\n })\n ).data!;\n\n const items: LsAPI_ListItem[] = resp.items.map((item) => ({\n name: item.name,\n size: BigInt(item.size),\n isDir: item.isDir,\n fullName: item.fullName,\n directory: item.directory,\n lastModified: parseTimestamp(item.lastModified),\n version: item.version,\n }));\n\n return {\n items,\n delimiter: resp.delimiter,\n };\n }\n }\n}\n\nfunction parseTimestamp(timestamp: string): { seconds: bigint; nanos: number } {\n // Parse ISO 8601 format: 2025-08-08T11:12:44.145635532Z\n const date = new Date(timestamp);\n const seconds = BigInt(Math.floor(date.getTime() / 1000));\n\n // Extract fractional seconds from the original string\n const fractionalMatch = timestamp.match(/\\.(\\d+)Z?$/);\n let nanos = 0;\n if (fractionalMatch) {\n const fractionalPart = fractionalMatch[1];\n // Pad or truncate to 9 digits (nanoseconds)\n const padded = fractionalPart.padEnd(9, \"0\").slice(0, 9);\n nanos = parseInt(padded, 10);\n }\n\n return { seconds, nanos };\n}\n"],"mappings":";;;AAcA,IAAa,WAAb,MAAsB;CACpB;CAEA,YACE,2BACA,QACA;AADiB,OAAA,SAAA;AAEjB,OAAK,OAAO,0BAA0B,0BAA0B,SAAS;AACvE,OAAI,KAAK,SAAS,OAChB,QAAO,IAAI,SAAS,KAAK,UAAU;AAGrC,UAAO,QAAQ,aAAyB;IACtC,aAAa,KAAK,OAAO;IACzB,KAAK,KAAK,OAAO;IACjB,YAAY,KAAK;IACjB,aAAa,KAAK;IACnB,CAAC;IACF;;CAGJ,QAAQ;CAER,MAAa,KACX,OACA,MACA,SAC8B;EAC9B,MAAM,SAAS,KAAK,KAAK,KAAK;EAE9B,MAAM,EAAE,UAAU,cAAc,sBAAsB,MAAM,GAAG;AAC/D,MAAI,kBAAkB,SACpB,QAAO,MAAM,OAAO,KAClB;GACE,YAAY;GACZ,mBAAmB;GACnB,UAAU;GACX,EACD,mBAAmB,MAAM,MAAM,QAAQ,CACxC,CAAC;OACG;GACL,MAAM,QACJ,MAAM,OAAO,KAAK,YAAY;IAC5B,MAAM;KACJ,YAAY,SAAS,UAAU;KAC/B,mBAAmB,qBAAqB,UAAU;KAClD,UAAU;KACX;IACD,SAAS,EAAE,GAAG,yBAAyB,MAAM,KAAK,EAAE;IACrD,CAAC,EACF;AAYF,UAAO;IACL,OAX8B,KAAK,MAAM,KAAK,UAAU;KACxD,MAAM,KAAK;KACX,MAAM,OAAO,KAAK,KAAK;KACvB,OAAO,KAAK;KACZ,UAAU,KAAK;KACf,WAAW,KAAK;KAChB,cAAc,eAAe,KAAK,aAAa;KAC/C,SAAS,KAAK;KACf,EAAE;IAID,WAAW,KAAK;IACjB;;;;AAKP,SAAS,eAAe,WAAuD;CAE7E,MAAM,OAAO,IAAI,KAAK,UAAU;CAChC,MAAM,UAAU,OAAO,KAAK,MAAM,KAAK,SAAS,GAAG,IAAK,CAAC;CAGzD,MAAM,kBAAkB,UAAU,MAAM,aAAa;CACrD,IAAI,QAAQ;AACZ,KAAI,iBAAiB;EAGnB,MAAM,SAFiB,gBAAgB,GAET,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE;AACxD,UAAQ,SAAS,QAAQ,GAAG;;AAG9B,QAAO;EAAE;EAAS;EAAO"}
1
+ {"version":3,"file":"ls_api.js","names":[],"sources":["../../src/clients/ls_api.ts"],"sourcesContent":["import type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { RpcOptions } from \"@protobuf-ts/runtime-rpc\";\nimport type { WireClientProvider, WireClientProviderFactory } from \"@milaboratories/pl-client\";\nimport { RestAPI, parseSignedResourceId, signatureToBase64Url } from \"@milaboratories/pl-client\";\nimport { addRTypeToMetadata, createRTypeRoutingHeader } from \"@milaboratories/pl-client\";\nimport type {\n LsAPI_List_Response,\n LsAPI_ListItem,\n} from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol\";\nimport { LSClient } from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client\";\nimport type { LsApiPaths, LsRestClientType } from \"../proto-rest\";\n\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\n\nexport class ClientLs {\n private readonly wire: WireClientProvider<LsRestClientType | LSClient>;\n\n constructor(\n wireClientProviderFactory: WireClientProviderFactory,\n private readonly logger: MiLogger,\n ) {\n this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {\n if (wire.type === \"grpc\") {\n return new LSClient(wire.Transport);\n }\n\n return RestAPI.createClient<LsApiPaths>({\n hostAndPort: wire.Config.hostAndPort,\n ssl: wire.Config.ssl,\n dispatcher: wire.Dispatcher,\n middlewares: wire.Middlewares,\n });\n });\n }\n\n close() {}\n\n public async list(\n rInfo: ResourceInfo,\n path: string,\n options?: RpcOptions,\n ): Promise<LsAPI_List_Response> {\n const client = this.wire.get();\n\n const { globalId, signature } = parseSignedResourceId(rInfo.id);\n if (client instanceof LSClient) {\n return await client.list(\n {\n resourceId: globalId,\n resourceSignature: signature,\n location: path,\n },\n addRTypeToMetadata(rInfo.type, options),\n ).response;\n } else {\n const resp = (\n await client.POST(\"/v1/list\", {\n body: {\n resourceId: globalId.toString(),\n resourceSignature: signatureToBase64Url(signature),\n location: path,\n },\n headers: { ...createRTypeRoutingHeader(rInfo.type) },\n })\n ).data!;\n\n const items: LsAPI_ListItem[] = resp.items.map((item) => ({\n name: item.name,\n size: BigInt(item.size),\n isDir: item.isDir,\n additionalInfo: item.additionalInfo ?? {},\n fullName: item.fullName,\n directory: item.directory,\n lastModified: parseTimestamp(item.lastModified),\n version: item.version,\n }));\n\n return {\n items,\n delimiter: resp.delimiter,\n };\n }\n }\n}\n\nfunction parseTimestamp(timestamp: string): { seconds: bigint; nanos: number } {\n // Parse ISO 8601 format: 2025-08-08T11:12:44.145635532Z\n const date = new Date(timestamp);\n const seconds = BigInt(Math.floor(date.getTime() / 1000));\n\n // Extract fractional seconds from the original string\n const fractionalMatch = timestamp.match(/\\.(\\d+)Z?$/);\n let nanos = 0;\n if (fractionalMatch) {\n const fractionalPart = fractionalMatch[1];\n // Pad or truncate to 9 digits (nanoseconds)\n const padded = fractionalPart.padEnd(9, \"0\").slice(0, 9);\n nanos = parseInt(padded, 10);\n }\n\n return { seconds, nanos };\n}\n"],"mappings":";;;AAcA,IAAa,WAAb,MAAsB;CACpB;CAEA,YACE,2BACA,QACA;AADiB,OAAA,SAAA;AAEjB,OAAK,OAAO,0BAA0B,0BAA0B,SAAS;AACvE,OAAI,KAAK,SAAS,OAChB,QAAO,IAAI,SAAS,KAAK,UAAU;AAGrC,UAAO,QAAQ,aAAyB;IACtC,aAAa,KAAK,OAAO;IACzB,KAAK,KAAK,OAAO;IACjB,YAAY,KAAK;IACjB,aAAa,KAAK;IACnB,CAAC;IACF;;CAGJ,QAAQ;CAER,MAAa,KACX,OACA,MACA,SAC8B;EAC9B,MAAM,SAAS,KAAK,KAAK,KAAK;EAE9B,MAAM,EAAE,UAAU,cAAc,sBAAsB,MAAM,GAAG;AAC/D,MAAI,kBAAkB,SACpB,QAAO,MAAM,OAAO,KAClB;GACE,YAAY;GACZ,mBAAmB;GACnB,UAAU;GACX,EACD,mBAAmB,MAAM,MAAM,QAAQ,CACxC,CAAC;OACG;GACL,MAAM,QACJ,MAAM,OAAO,KAAK,YAAY;IAC5B,MAAM;KACJ,YAAY,SAAS,UAAU;KAC/B,mBAAmB,qBAAqB,UAAU;KAClD,UAAU;KACX;IACD,SAAS,EAAE,GAAG,yBAAyB,MAAM,KAAK,EAAE;IACrD,CAAC,EACF;AAaF,UAAO;IACL,OAZ8B,KAAK,MAAM,KAAK,UAAU;KACxD,MAAM,KAAK;KACX,MAAM,OAAO,KAAK,KAAK;KACvB,OAAO,KAAK;KACZ,gBAAgB,KAAK,kBAAkB,EAAE;KACzC,UAAU,KAAK;KACf,WAAW,KAAK;KAChB,cAAc,eAAe,KAAK,aAAa;KAC/C,SAAS,KAAK;KACf,EAAE;IAID,WAAW,KAAK;IACjB;;;;AAKP,SAAS,eAAe,WAAuD;CAE7E,MAAM,OAAO,IAAI,KAAK,UAAU;CAChC,MAAM,UAAU,OAAO,KAAK,MAAM,KAAK,SAAS,GAAG,IAAK,CAAC;CAGzD,MAAM,kBAAkB,UAAU,MAAM,aAAa;CACrD,IAAI,QAAQ;AACZ,KAAI,iBAAiB;EAGnB,MAAM,SAFiB,gBAAgB,GAET,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE;AACxD,UAAQ,SAAS,QAAQ,GAAG;;AAG9B,QAAO;EAAE;EAAS;EAAO"}
@@ -1,10 +1,12 @@
1
1
  const require_types = require("../types.cjs");
2
2
  //#region src/drivers/helpers/ls_remote_import_handle.ts
3
- function createIndexImportHandle(storageId, path) {
4
- return `index://index/${encodeURIComponent(JSON.stringify({
3
+ function createIndexImportHandle(storageId, path, additionalInfo) {
4
+ const data = {
5
5
  storageId,
6
6
  path
7
- }))}`;
7
+ };
8
+ if (additionalInfo && Object.keys(additionalInfo).length > 0) data.additionalInfo = additionalInfo;
9
+ return `index://index/${encodeURIComponent(JSON.stringify(data))}`;
8
10
  }
9
11
  function createUploadImportHandle(localPath, signer, sizeBytes, modificationTimeSeconds) {
10
12
  const data = {
@@ -1 +1 @@
1
- {"version":3,"file":"ls_remote_import_handle.cjs","names":["ImportFileHandleUploadData","ImportFileHandleIndexData"],"sources":["../../../src/drivers/helpers/ls_remote_import_handle.ts"],"sourcesContent":["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 storageId: string,\n path: string,\n): sdk.ImportFileHandleIndex {\n const data: ImportFileHandleIndexData = {\n storageId: storageId,\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"],"mappings":";;AAIA,SAAgB,wBACd,WACA,MAC2B;AAM3B,QAAO,iBAAiB,mBAAmB,KAAK,UALR;EAC3B;EACL;EACP,CAE8D,CAAC;;AAGlE,SAAgB,yBACd,WACA,QACA,WACA,yBAC4B;CAC5B,MAAM,OAAmC;EACvC;EACA,eAAe,OAAO,KAAK,UAAU;EACrC,WAAW,OAAO,UAAU;EAC5B,kBAAkB,OAAO,wBAAwB;EAClD;AAED,QAAO,mBAAmB,mBAAmB,KAAK,UAAU,KAAK,CAAC;;AAGpE,SAAgB,kBAAkB,QAAgE;CAChG,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAOA,cAAAA,2BAA2B,MAChC,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAC1D;;AAGH,SAAgB,iBAAiB,QAA8D;CAC7F,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAOC,cAAAA,0BAA0B,MAAM,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"ls_remote_import_handle.cjs","names":["ImportFileHandleUploadData","ImportFileHandleIndexData"],"sources":["../../../src/drivers/helpers/ls_remote_import_handle.ts"],"sourcesContent":["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 storageId: string,\n path: string,\n additionalInfo?: Record<string, string>,\n): sdk.ImportFileHandleIndex {\n const data: ImportFileHandleIndexData = {\n storageId: storageId,\n path: path,\n };\n\n // Only embed the envelope when non-empty; preserves byte-identical URL for non-federative storages.\n if (additionalInfo && Object.keys(additionalInfo).length > 0) {\n data.additionalInfo = additionalInfo;\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"],"mappings":";;AAIA,SAAgB,wBACd,WACA,MACA,gBAC2B;CAC3B,MAAM,OAAkC;EAC3B;EACL;EACP;AAGD,KAAI,kBAAkB,OAAO,KAAK,eAAe,CAAC,SAAS,EACzD,MAAK,iBAAiB;AAGxB,QAAO,iBAAiB,mBAAmB,KAAK,UAAU,KAAK,CAAC;;AAGlE,SAAgB,yBACd,WACA,QACA,WACA,yBAC4B;CAC5B,MAAM,OAAmC;EACvC;EACA,eAAe,OAAO,KAAK,UAAU;EACrC,WAAW,OAAO,UAAU;EAC5B,kBAAkB,OAAO,wBAAwB;EAClD;AAED,QAAO,mBAAmB,mBAAmB,KAAK,UAAU,KAAK,CAAC;;AAGpE,SAAgB,kBAAkB,QAAgE;CAChG,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAOA,cAAAA,2BAA2B,MAChC,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAC1D;;AAGH,SAAgB,iBAAiB,QAA8D;CAC7F,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAOC,cAAAA,0BAA0B,MAAM,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAAC"}
@@ -1,10 +1,12 @@
1
1
  import { ImportFileHandleIndexData, ImportFileHandleUploadData } from "../types.js";
2
2
  //#region src/drivers/helpers/ls_remote_import_handle.ts
3
- function createIndexImportHandle(storageId, path) {
4
- return `index://index/${encodeURIComponent(JSON.stringify({
3
+ function createIndexImportHandle(storageId, path, additionalInfo) {
4
+ const data = {
5
5
  storageId,
6
6
  path
7
- }))}`;
7
+ };
8
+ if (additionalInfo && Object.keys(additionalInfo).length > 0) data.additionalInfo = additionalInfo;
9
+ return `index://index/${encodeURIComponent(JSON.stringify(data))}`;
8
10
  }
9
11
  function createUploadImportHandle(localPath, signer, sizeBytes, modificationTimeSeconds) {
10
12
  const data = {
@@ -1 +1 @@
1
- {"version":3,"file":"ls_remote_import_handle.js","names":[],"sources":["../../../src/drivers/helpers/ls_remote_import_handle.ts"],"sourcesContent":["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 storageId: string,\n path: string,\n): sdk.ImportFileHandleIndex {\n const data: ImportFileHandleIndexData = {\n storageId: storageId,\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"],"mappings":";;AAIA,SAAgB,wBACd,WACA,MAC2B;AAM3B,QAAO,iBAAiB,mBAAmB,KAAK,UALR;EAC3B;EACL;EACP,CAE8D,CAAC;;AAGlE,SAAgB,yBACd,WACA,QACA,WACA,yBAC4B;CAC5B,MAAM,OAAmC;EACvC;EACA,eAAe,OAAO,KAAK,UAAU;EACrC,WAAW,OAAO,UAAU;EAC5B,kBAAkB,OAAO,wBAAwB;EAClD;AAED,QAAO,mBAAmB,mBAAmB,KAAK,UAAU,KAAK,CAAC;;AAGpE,SAAgB,kBAAkB,QAAgE;CAChG,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAO,2BAA2B,MAChC,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAC1D;;AAGH,SAAgB,iBAAiB,QAA8D;CAC7F,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAO,0BAA0B,MAAM,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"ls_remote_import_handle.js","names":[],"sources":["../../../src/drivers/helpers/ls_remote_import_handle.ts"],"sourcesContent":["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 storageId: string,\n path: string,\n additionalInfo?: Record<string, string>,\n): sdk.ImportFileHandleIndex {\n const data: ImportFileHandleIndexData = {\n storageId: storageId,\n path: path,\n };\n\n // Only embed the envelope when non-empty; preserves byte-identical URL for non-federative storages.\n if (additionalInfo && Object.keys(additionalInfo).length > 0) {\n data.additionalInfo = additionalInfo;\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"],"mappings":";;AAIA,SAAgB,wBACd,WACA,MACA,gBAC2B;CAC3B,MAAM,OAAkC;EAC3B;EACL;EACP;AAGD,KAAI,kBAAkB,OAAO,KAAK,eAAe,CAAC,SAAS,EACzD,MAAK,iBAAiB;AAGxB,QAAO,iBAAiB,mBAAmB,KAAK,UAAU,KAAK,CAAC;;AAGlE,SAAgB,yBACd,WACA,QACA,WACA,yBAC4B;CAC5B,MAAM,OAAmC;EACvC;EACA,eAAe,OAAO,KAAK,UAAU;EACrC,WAAW,OAAO,UAAU;EAC5B,kBAAkB,OAAO,wBAAwB;EAClD;AAED,QAAO,mBAAmB,mBAAmB,KAAK,UAAU,KAAK,CAAC;;AAGpE,SAAgB,kBAAkB,QAAgE;CAChG,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAO,2BAA2B,MAChC,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAC1D;;AAGH,SAAgB,iBAAiB,QAA8D;CAC7F,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAO,0BAA0B,MAAM,KAAK,MAAM,mBAAmB,IAAI,SAAS,UAAU,EAAE,CAAC,CAAC,CAAC"}
@@ -101,7 +101,7 @@ var LsDriver = class LsDriver {
101
101
  type: e.isDir ? "dir" : "file",
102
102
  name: e.name,
103
103
  fullPath: e.fullName,
104
- handle: require_ls_remote_import_handle.createIndexImportHandle(storageData.storageId, e.fullName)
104
+ handle: require_ls_remote_import_handle.createIndexImportHandle(storageData.storageId, e.fullName, e.additionalInfo)
105
105
  })) };
106
106
  }
107
107
  if (node_path.sep === "/" && fullPath === "") fullPath = "/";
@@ -120,7 +120,7 @@ var LsDriver = class LsDriver {
120
120
  }
121
121
  return { entries };
122
122
  }
123
- async listRemoteFilesWithAdditionalInfo(storageHandle, fullPath) {
123
+ async listRemoteFilesWithFileStats(storageHandle, fullPath) {
124
124
  const storageData = require_ls_storage_entry.parseStorageHandle(storageHandle);
125
125
  if (!storageData.isRemote) throw new Error(`Storage ${storageData.name} is not remote`);
126
126
  const rInfo = await this.resolveRemoteStorageResourceInfo(storageData);
@@ -128,7 +128,7 @@ var LsDriver = class LsDriver {
128
128
  type: e.isDir ? "dir" : "file",
129
129
  name: e.name,
130
130
  fullPath: e.fullName,
131
- handle: require_ls_remote_import_handle.createIndexImportHandle(storageData.storageId, e.fullName),
131
+ handle: require_ls_remote_import_handle.createIndexImportHandle(storageData.storageId, e.fullName, e.additionalInfo),
132
132
  size: Number(e.size)
133
133
  })) };
134
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ls.cjs","names":["fsp","parseIndexHandle","path","parseUploadHandle","createIndexImportHandle","createUploadImportHandle","createLocalStorageHandle","createRemoteStorageHandle","parseStorageHandle","createLsFilesClient","DefaultVirtualLocalStorages"],"sources":["../../src/drivers/ls.ts"],"sourcesContent":["import type { PlClient, UserResources } from \"@milaboratories/pl-client\";\nimport type * as sdk from \"@milaboratories/pl-model-common\";\nimport { isImportFileHandleIndex } from \"@milaboratories/pl-model-common\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport * as fsp from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { createLsFilesClient } from \"../clients/constructors\";\nimport type { ClientLs } from \"../clients/ls_api\";\nimport { validateAbsolute } from \"../helpers/validate\";\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\nimport {\n createIndexImportHandle,\n createUploadImportHandle,\n parseIndexHandle,\n parseUploadHandle,\n} from \"./helpers/ls_remote_import_handle\";\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle,\n RemoteStorageHandleData,\n} from \"./helpers/ls_storage_entry\";\nimport type { LocalStorageProjection, VirtualLocalStorageSpec } from \"./types\";\nimport { DefaultVirtualLocalStorages } from \"./virtual_storages\";\n\n/**\n * Extends public and safe SDK's driver API with methods used internally in the middle\n * layer and in tests.\n */\nexport interface InternalLsDriver extends sdk.LsDriver {\n /**\n * Given local path, generates well-structured and signed upload handle.\n * To be used in tests and in implementation of the native file selection UI API.\n * */\n getLocalFileHandle(localPath: string): Promise<sdk.LocalImportFileHandle>;\n\n listRemoteFilesWithAdditionalInfo(\n storage: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithAdditionalInfo>;\n}\n\nexport type ListRemoteFilesResultWithAdditionalInfo = {\n parent?: string;\n entries: LsEntryWithAdditionalInfo[];\n};\n\nexport type LsEntryWithAdditionalInfo = sdk.LsEntry & {\n size: number;\n};\n\nexport type OpenFileDialogCallback = (\n multipleFiles: boolean,\n ops?: sdk.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 private readonly userResources: UserResources,\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: sdk.LocalImportFileHandle,\n range?: sdk.TableRange,\n ): Promise<Uint8Array> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n\n if (range) {\n const fileHandle = await fsp.open(localPath, \"r\");\n try {\n const buffer = Buffer.alloc(range.length);\n const { bytesRead } = await fileHandle.read(buffer, 0, range.length, range.offset);\n return new Uint8Array(buffer.subarray(0, bytesRead));\n } finally {\n await fileHandle.close();\n }\n }\n\n return await fsp.readFile(localPath);\n }\n\n public async getLocalFileSize(file: sdk.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?: sdk.OpenDialogOps,\n ): Promise<sdk.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(\n ops?: sdk.OpenDialogOps,\n ): Promise<sdk.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: sdk.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 & sdk.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 & sdk.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 & sdk.LocalImportFileHandle;\n }\n\n public async getStorageList(): Promise<sdk.StorageEntry[]> {\n const virtualStorages = [...this.virtualStoragesMap.values()].map((s) => ({\n id: s.id,\n name: s.name,\n handle: createLocalStorageHandle(s.id, s.root),\n initialFullPath: s.initialPath,\n }));\n\n const dataLibraries = await this.userResources.getDataLibraries();\n const remoteStorages = [...dataLibraries.values()].map((info) => ({\n id: info.storageId,\n name: info.storageName,\n handle: createRemoteStorageHandle(info),\n initialFullPath: \"\",\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 = remoteStorages.filter((it) => it.id !== \"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 rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, 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: sdk.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 rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, e.fullName),\n size: Number(e.size),\n })),\n };\n }\n\n /** Looks up ResourceType for a remote storage from the data libraries index. */\n private async resolveRemoteStorageResourceInfo(\n storageData: RemoteStorageHandleData,\n ): Promise<ResourceInfo> {\n return { id: storageData.resourceId, type: storageData.resourceType };\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.id, 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 client.userResources,\n signer,\n virtualStoragesMap,\n localProjectionsMap,\n openFileDialogCallback,\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ls.cjs","names":["fsp","parseIndexHandle","path","parseUploadHandle","createIndexImportHandle","createUploadImportHandle","createLocalStorageHandle","createRemoteStorageHandle","parseStorageHandle","createLsFilesClient","DefaultVirtualLocalStorages"],"sources":["../../src/drivers/ls.ts"],"sourcesContent":["import type { PlClient, UserResources } from \"@milaboratories/pl-client\";\nimport type * as sdk from \"@milaboratories/pl-model-common\";\nimport { isImportFileHandleIndex } from \"@milaboratories/pl-model-common\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport * as fsp from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { createLsFilesClient } from \"../clients/constructors\";\nimport type { ClientLs } from \"../clients/ls_api\";\nimport { validateAbsolute } from \"../helpers/validate\";\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\nimport {\n createIndexImportHandle,\n createUploadImportHandle,\n parseIndexHandle,\n parseUploadHandle,\n} from \"./helpers/ls_remote_import_handle\";\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle,\n RemoteStorageHandleData,\n} from \"./helpers/ls_storage_entry\";\nimport type { LocalStorageProjection, VirtualLocalStorageSpec } from \"./types\";\nimport { DefaultVirtualLocalStorages } from \"./virtual_storages\";\n\n/**\n * Extends public and safe SDK's driver API with methods used internally in the middle\n * layer and in tests.\n */\nexport interface InternalLsDriver extends sdk.LsDriver {\n /**\n * Given local path, generates well-structured and signed upload handle.\n * To be used in tests and in implementation of the native file selection UI API.\n * */\n getLocalFileHandle(localPath: string): Promise<sdk.LocalImportFileHandle>;\n\n listRemoteFilesWithFileStats(\n storage: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithFileStats>;\n}\n\nexport type ListRemoteFilesResultWithFileStats = {\n parent?: string;\n entries: LsEntryWithFileStats[];\n};\n\nexport type LsEntryWithFileStats = sdk.LsEntry & {\n size: number;\n};\n\nexport type OpenFileDialogCallback = (\n multipleFiles: boolean,\n ops?: sdk.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 private readonly userResources: UserResources,\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: sdk.LocalImportFileHandle,\n range?: sdk.TableRange,\n ): Promise<Uint8Array> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n\n if (range) {\n const fileHandle = await fsp.open(localPath, \"r\");\n try {\n const buffer = Buffer.alloc(range.length);\n const { bytesRead } = await fileHandle.read(buffer, 0, range.length, range.offset);\n return new Uint8Array(buffer.subarray(0, bytesRead));\n } finally {\n await fileHandle.close();\n }\n }\n\n return await fsp.readFile(localPath);\n }\n\n public async getLocalFileSize(file: sdk.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?: sdk.OpenDialogOps,\n ): Promise<sdk.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(\n ops?: sdk.OpenDialogOps,\n ): Promise<sdk.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: sdk.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 & sdk.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 & sdk.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 & sdk.LocalImportFileHandle;\n }\n\n public async getStorageList(): Promise<sdk.StorageEntry[]> {\n const virtualStorages = [...this.virtualStoragesMap.values()].map((s) => ({\n id: s.id,\n name: s.name,\n handle: createLocalStorageHandle(s.id, s.root),\n initialFullPath: s.initialPath,\n }));\n\n const dataLibraries = await this.userResources.getDataLibraries();\n const remoteStorages = [...dataLibraries.values()].map((info) => ({\n id: info.storageId,\n name: info.storageName,\n handle: createRemoteStorageHandle(info),\n initialFullPath: \"\",\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 = remoteStorages.filter((it) => it.id !== \"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 rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, e.fullName, e.additionalInfo),\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: sdk.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 listRemoteFilesWithFileStats(\n storageHandle: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithFileStats> {\n const storageData = parseStorageHandle(storageHandle);\n if (!storageData.isRemote) {\n throw new Error(`Storage ${storageData.name} is not remote`);\n }\n\n const rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, e.fullName, e.additionalInfo),\n size: Number(e.size),\n })),\n };\n }\n\n /** Looks up ResourceType for a remote storage from the data libraries index. */\n private async resolveRemoteStorageResourceInfo(\n storageData: RemoteStorageHandleData,\n ): Promise<ResourceInfo> {\n return { id: storageData.resourceId, type: storageData.resourceType };\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.id, 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 client.userResources,\n signer,\n virtualStoragesMap,\n localProjectionsMap,\n openFileDialogCallback,\n );\n }\n}\n"],"mappings":"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"}
@@ -14,13 +14,13 @@ interface InternalLsDriver extends sdk.LsDriver {
14
14
  * To be used in tests and in implementation of the native file selection UI API.
15
15
  * */
16
16
  getLocalFileHandle(localPath: string): Promise<sdk.LocalImportFileHandle>;
17
- listRemoteFilesWithAdditionalInfo(storage: sdk.StorageHandle, fullPath: string): Promise<ListRemoteFilesResultWithAdditionalInfo>;
17
+ listRemoteFilesWithFileStats(storage: sdk.StorageHandle, fullPath: string): Promise<ListRemoteFilesResultWithFileStats>;
18
18
  }
19
- type ListRemoteFilesResultWithAdditionalInfo = {
19
+ type ListRemoteFilesResultWithFileStats = {
20
20
  parent?: string;
21
- entries: LsEntryWithAdditionalInfo[];
21
+ entries: LsEntryWithFileStats[];
22
22
  };
23
- type LsEntryWithAdditionalInfo = sdk.LsEntry & {
23
+ type LsEntryWithFileStats = sdk.LsEntry & {
24
24
  size: number;
25
25
  };
26
26
  type OpenFileDialogCallback = (multipleFiles: boolean, ops?: sdk.OpenDialogOps) => Promise<undefined | string[]>;
@@ -49,7 +49,7 @@ declare class LsDriver implements InternalLsDriver {
49
49
  getLocalFileHandle(localPath: string): Promise<sdk.ImportFileHandle & sdk.LocalImportFileHandle>;
50
50
  getStorageList(): Promise<sdk.StorageEntry[]>;
51
51
  listFiles(storageHandle: sdk.StorageHandle, fullPath: string): Promise<sdk.ListFilesResult>;
52
- listRemoteFilesWithAdditionalInfo(storageHandle: sdk.StorageHandle, fullPath: string): Promise<ListRemoteFilesResultWithAdditionalInfo>;
52
+ listRemoteFilesWithFileStats(storageHandle: sdk.StorageHandle, fullPath: string): Promise<ListRemoteFilesResultWithFileStats>;
53
53
  /** Looks up ResourceType for a remote storage from the data libraries index. */
54
54
  private resolveRemoteStorageResourceInfo;
55
55
  fileToImportHandle(_file: sdk.FileLike): Promise<sdk.ImportFileHandle>;
@@ -58,5 +58,5 @@ declare class LsDriver implements InternalLsDriver {
58
58
  localProjections: LocalStorageProjection[], openFileDialogCallback: OpenFileDialogCallback, virtualStorages?: VirtualLocalStorageSpec[]): Promise<LsDriver>;
59
59
  }
60
60
  //#endregion
61
- export { InternalLsDriver, ListRemoteFilesResultWithAdditionalInfo, LsDriver, LsEntryWithAdditionalInfo, OpenFileDialogCallback };
61
+ export { InternalLsDriver, ListRemoteFilesResultWithFileStats, LsDriver, LsEntryWithFileStats, OpenFileDialogCallback };
62
62
  //# sourceMappingURL=ls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ls.d.ts","names":[],"sources":["../../src/drivers/ls.ts"],"mappings":";;;;;;;;AA6BA;;UAAiB,gBAAA,SAAyB,GAAA,CAAI,QAAA;EAKG;;;;EAA/C,kBAAA,CAAmB,SAAA,WAAoB,OAAA,CAAQ,GAAA,CAAI,qBAAA;EAEnD,iCAAA,CACE,OAAA,EAAS,GAAA,CAAI,aAAA,EACb,QAAA,WACC,OAAA,CAAQ,uCAAA;AAAA;AAAA,KAGD,uCAAA;EACV,MAAA;EACA,OAAA,EAAS,yBAAA;AAAA;AAAA,KAGC,yBAAA,GAA4B,GAAA,CAAI,OAAA;EAC1C,IAAA;AAAA;AAAA,KAGU,sBAAA,IACV,aAAA,WACA,GAAA,GAAM,GAAA,CAAI,aAAA,KACP,OAAA;AAAA,cAEQ,QAAA,YAAoB,gBAAA;EAAA,iBAEZ,MAAA;EAAA,iBACA,QAAA;EAAA,iBACA,aAAA;EAAA,iBACA,MAAA;EAtBhB;EAAA,iBAwBgB,kBAAA;EAxB+B;EAAA,iBA0B/B,mBAAA;EAAA,iBACA,sBAAA;EAAA,QATZ,WAAA,CAAA;EAYM,mBAAA,CACX,IAAA,EAAM,GAAA,CAAI,qBAAA,EACV,KAAA,GAAQ,GAAA,CAAI,UAAA,GACX,OAAA,CAAQ,UAAA;EAiBE,gBAAA,CAAiB,IAAA,EAAM,GAAA,CAAI,qBAAA,GAAwB,OAAA;EAMnD,2BAAA,CACX,GAAA,GAAM,GAAA,CAAI,aAAA,GACT,OAAA,CAAQ,GAAA,CAAI,yBAAA;EAQF,wBAAA,CACX,GAAA,GAAM,GAAA,CAAI,aAAA,GACT,OAAA,CAAQ,GAAA,CAAI,sBAAA;EA/DN;;;AAGX;;;EAHW,QA6EK,yBAAA;EA0BD,kBAAA,CACX,SAAA,WACC,OAAA,CAAQ,GAAA,CAAI,gBAAA,GAAmB,GAAA,CAAI,qBAAA;EA+BzB,cAAA,CAAA,GAAkB,OAAA,CAAQ,GAAA,CAAI,YAAA;EAyB9B,SAAA,CACX,aAAA,EAAe,GAAA,CAAI,aAAA,EACnB,QAAA,WACC,OAAA,CAAQ,GAAA,CAAI,eAAA;EA2CF,iCAAA,CACX,aAAA,EAAe,GAAA,CAAI,aAAA,EACnB,QAAA,WACC,OAAA,CAAQ,uCAAA;EA9MP;EAAA,QAmOU,gCAAA;EAMD,kBAAA,CAAmB,KAAA,EAAO,GAAA,CAAI,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,gBAAA;EAAA,OAM9C,IAAA,CAClB,MAAA,EAAQ,QAAA,EACR,MAAA,EAAQ,QAAA,EACR,MAAA,EAAQ,MAAA,EA5OA;;EA8OR,gBAAA,EAAkB,sBAAA,IAClB,sBAAA,EAAwB,sBAAA,EACxB,eAAA,GAAkB,uBAAA,KACjB,OAAA,CAAQ,QAAA;AAAA"}
1
+ {"version":3,"file":"ls.d.ts","names":[],"sources":["../../src/drivers/ls.ts"],"mappings":";;;;;;;;AA6BA;;UAAiB,gBAAA,SAAyB,GAAA,CAAI,QAAA;EAKG;;;;EAA/C,kBAAA,CAAmB,SAAA,WAAoB,OAAA,CAAQ,GAAA,CAAI,qBAAA;EAEnD,4BAAA,CACE,OAAA,EAAS,GAAA,CAAI,aAAA,EACb,QAAA,WACC,OAAA,CAAQ,kCAAA;AAAA;AAAA,KAGD,kCAAA;EACV,MAAA;EACA,OAAA,EAAS,oBAAA;AAAA;AAAA,KAGC,oBAAA,GAAuB,GAAA,CAAI,OAAA;EACrC,IAAA;AAAA;AAAA,KAGU,sBAAA,IACV,aAAA,WACA,GAAA,GAAM,GAAA,CAAI,aAAA,KACP,OAAA;AAAA,cAEQ,QAAA,YAAoB,gBAAA;EAAA,iBAEZ,MAAA;EAAA,iBACA,QAAA;EAAA,iBACA,aAAA;EAAA,iBACA,MAAA;EAtBhB;EAAA,iBAwBgB,kBAAA;EAxB0B;EAAA,iBA0B1B,mBAAA;EAAA,iBACA,sBAAA;EAAA,QATZ,WAAA,CAAA;EAYM,mBAAA,CACX,IAAA,EAAM,GAAA,CAAI,qBAAA,EACV,KAAA,GAAQ,GAAA,CAAI,UAAA,GACX,OAAA,CAAQ,UAAA;EAiBE,gBAAA,CAAiB,IAAA,EAAM,GAAA,CAAI,qBAAA,GAAwB,OAAA;EAMnD,2BAAA,CACX,GAAA,GAAM,GAAA,CAAI,aAAA,GACT,OAAA,CAAQ,GAAA,CAAI,yBAAA;EAQF,wBAAA,CACX,GAAA,GAAM,GAAA,CAAI,aAAA,GACT,OAAA,CAAQ,GAAA,CAAI,sBAAA;EA/DN;;;AAGX;;;EAHW,QA6EK,yBAAA;EA0BD,kBAAA,CACX,SAAA,WACC,OAAA,CAAQ,GAAA,CAAI,gBAAA,GAAmB,GAAA,CAAI,qBAAA;EA+BzB,cAAA,CAAA,GAAkB,OAAA,CAAQ,GAAA,CAAI,YAAA;EAyB9B,SAAA,CACX,aAAA,EAAe,GAAA,CAAI,aAAA,EACnB,QAAA,WACC,OAAA,CAAQ,GAAA,CAAI,eAAA;EA2CF,4BAAA,CACX,aAAA,EAAe,GAAA,CAAI,aAAA,EACnB,QAAA,WACC,OAAA,CAAQ,kCAAA;EA9MP;EAAA,QAmOU,gCAAA;EAMD,kBAAA,CAAmB,KAAA,EAAO,GAAA,CAAI,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,gBAAA;EAAA,OAM9C,IAAA,CAClB,MAAA,EAAQ,QAAA,EACR,MAAA,EAAQ,QAAA,EACR,MAAA,EAAQ,MAAA,EA5OA;;EA8OR,gBAAA,EAAkB,sBAAA,IAClB,sBAAA,EAAwB,sBAAA,EACxB,eAAA,GAAkB,uBAAA,KACjB,OAAA,CAAQ,QAAA;AAAA"}
@@ -98,7 +98,7 @@ var LsDriver = class LsDriver {
98
98
  type: e.isDir ? "dir" : "file",
99
99
  name: e.name,
100
100
  fullPath: e.fullName,
101
- handle: createIndexImportHandle(storageData.storageId, e.fullName)
101
+ handle: createIndexImportHandle(storageData.storageId, e.fullName, e.additionalInfo)
102
102
  })) };
103
103
  }
104
104
  if (path$1.sep === "/" && fullPath === "") fullPath = "/";
@@ -117,7 +117,7 @@ var LsDriver = class LsDriver {
117
117
  }
118
118
  return { entries };
119
119
  }
120
- async listRemoteFilesWithAdditionalInfo(storageHandle, fullPath) {
120
+ async listRemoteFilesWithFileStats(storageHandle, fullPath) {
121
121
  const storageData = parseStorageHandle(storageHandle);
122
122
  if (!storageData.isRemote) throw new Error(`Storage ${storageData.name} is not remote`);
123
123
  const rInfo = await this.resolveRemoteStorageResourceInfo(storageData);
@@ -125,7 +125,7 @@ var LsDriver = class LsDriver {
125
125
  type: e.isDir ? "dir" : "file",
126
126
  name: e.name,
127
127
  fullPath: e.fullName,
128
- handle: createIndexImportHandle(storageData.storageId, e.fullName),
128
+ handle: createIndexImportHandle(storageData.storageId, e.fullName, e.additionalInfo),
129
129
  size: Number(e.size)
130
130
  })) };
131
131
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ls.js","names":["path"],"sources":["../../src/drivers/ls.ts"],"sourcesContent":["import type { PlClient, UserResources } from \"@milaboratories/pl-client\";\nimport type * as sdk from \"@milaboratories/pl-model-common\";\nimport { isImportFileHandleIndex } from \"@milaboratories/pl-model-common\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport * as fsp from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { createLsFilesClient } from \"../clients/constructors\";\nimport type { ClientLs } from \"../clients/ls_api\";\nimport { validateAbsolute } from \"../helpers/validate\";\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\nimport {\n createIndexImportHandle,\n createUploadImportHandle,\n parseIndexHandle,\n parseUploadHandle,\n} from \"./helpers/ls_remote_import_handle\";\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle,\n RemoteStorageHandleData,\n} from \"./helpers/ls_storage_entry\";\nimport type { LocalStorageProjection, VirtualLocalStorageSpec } from \"./types\";\nimport { DefaultVirtualLocalStorages } from \"./virtual_storages\";\n\n/**\n * Extends public and safe SDK's driver API with methods used internally in the middle\n * layer and in tests.\n */\nexport interface InternalLsDriver extends sdk.LsDriver {\n /**\n * Given local path, generates well-structured and signed upload handle.\n * To be used in tests and in implementation of the native file selection UI API.\n * */\n getLocalFileHandle(localPath: string): Promise<sdk.LocalImportFileHandle>;\n\n listRemoteFilesWithAdditionalInfo(\n storage: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithAdditionalInfo>;\n}\n\nexport type ListRemoteFilesResultWithAdditionalInfo = {\n parent?: string;\n entries: LsEntryWithAdditionalInfo[];\n};\n\nexport type LsEntryWithAdditionalInfo = sdk.LsEntry & {\n size: number;\n};\n\nexport type OpenFileDialogCallback = (\n multipleFiles: boolean,\n ops?: sdk.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 private readonly userResources: UserResources,\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: sdk.LocalImportFileHandle,\n range?: sdk.TableRange,\n ): Promise<Uint8Array> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n\n if (range) {\n const fileHandle = await fsp.open(localPath, \"r\");\n try {\n const buffer = Buffer.alloc(range.length);\n const { bytesRead } = await fileHandle.read(buffer, 0, range.length, range.offset);\n return new Uint8Array(buffer.subarray(0, bytesRead));\n } finally {\n await fileHandle.close();\n }\n }\n\n return await fsp.readFile(localPath);\n }\n\n public async getLocalFileSize(file: sdk.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?: sdk.OpenDialogOps,\n ): Promise<sdk.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(\n ops?: sdk.OpenDialogOps,\n ): Promise<sdk.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: sdk.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 & sdk.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 & sdk.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 & sdk.LocalImportFileHandle;\n }\n\n public async getStorageList(): Promise<sdk.StorageEntry[]> {\n const virtualStorages = [...this.virtualStoragesMap.values()].map((s) => ({\n id: s.id,\n name: s.name,\n handle: createLocalStorageHandle(s.id, s.root),\n initialFullPath: s.initialPath,\n }));\n\n const dataLibraries = await this.userResources.getDataLibraries();\n const remoteStorages = [...dataLibraries.values()].map((info) => ({\n id: info.storageId,\n name: info.storageName,\n handle: createRemoteStorageHandle(info),\n initialFullPath: \"\",\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 = remoteStorages.filter((it) => it.id !== \"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 rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, 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: sdk.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 rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, e.fullName),\n size: Number(e.size),\n })),\n };\n }\n\n /** Looks up ResourceType for a remote storage from the data libraries index. */\n private async resolveRemoteStorageResourceInfo(\n storageData: RemoteStorageHandleData,\n ): Promise<ResourceInfo> {\n return { id: storageData.resourceId, type: storageData.resourceType };\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.id, 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 client.userResources,\n signer,\n virtualStoragesMap,\n localProjectionsMap,\n openFileDialogCallback,\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ls.js","names":["path"],"sources":["../../src/drivers/ls.ts"],"sourcesContent":["import type { PlClient, UserResources } from \"@milaboratories/pl-client\";\nimport type * as sdk from \"@milaboratories/pl-model-common\";\nimport { isImportFileHandleIndex } from \"@milaboratories/pl-model-common\";\nimport type { MiLogger, Signer } from \"@milaboratories/ts-helpers\";\nimport * as fsp from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { createLsFilesClient } from \"../clients/constructors\";\nimport type { ClientLs } from \"../clients/ls_api\";\nimport { validateAbsolute } from \"../helpers/validate\";\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\nimport {\n createIndexImportHandle,\n createUploadImportHandle,\n parseIndexHandle,\n parseUploadHandle,\n} from \"./helpers/ls_remote_import_handle\";\nimport {\n createLocalStorageHandle,\n createRemoteStorageHandle,\n parseStorageHandle,\n RemoteStorageHandleData,\n} from \"./helpers/ls_storage_entry\";\nimport type { LocalStorageProjection, VirtualLocalStorageSpec } from \"./types\";\nimport { DefaultVirtualLocalStorages } from \"./virtual_storages\";\n\n/**\n * Extends public and safe SDK's driver API with methods used internally in the middle\n * layer and in tests.\n */\nexport interface InternalLsDriver extends sdk.LsDriver {\n /**\n * Given local path, generates well-structured and signed upload handle.\n * To be used in tests and in implementation of the native file selection UI API.\n * */\n getLocalFileHandle(localPath: string): Promise<sdk.LocalImportFileHandle>;\n\n listRemoteFilesWithFileStats(\n storage: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithFileStats>;\n}\n\nexport type ListRemoteFilesResultWithFileStats = {\n parent?: string;\n entries: LsEntryWithFileStats[];\n};\n\nexport type LsEntryWithFileStats = sdk.LsEntry & {\n size: number;\n};\n\nexport type OpenFileDialogCallback = (\n multipleFiles: boolean,\n ops?: sdk.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 private readonly userResources: UserResources,\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: sdk.LocalImportFileHandle,\n range?: sdk.TableRange,\n ): Promise<Uint8Array> {\n const localPath = await this.tryResolveLocalFileHandle(file);\n\n if (range) {\n const fileHandle = await fsp.open(localPath, \"r\");\n try {\n const buffer = Buffer.alloc(range.length);\n const { bytesRead } = await fileHandle.read(buffer, 0, range.length, range.offset);\n return new Uint8Array(buffer.subarray(0, bytesRead));\n } finally {\n await fileHandle.close();\n }\n }\n\n return await fsp.readFile(localPath);\n }\n\n public async getLocalFileSize(file: sdk.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?: sdk.OpenDialogOps,\n ): Promise<sdk.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(\n ops?: sdk.OpenDialogOps,\n ): Promise<sdk.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: sdk.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 & sdk.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 & sdk.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 & sdk.LocalImportFileHandle;\n }\n\n public async getStorageList(): Promise<sdk.StorageEntry[]> {\n const virtualStorages = [...this.virtualStoragesMap.values()].map((s) => ({\n id: s.id,\n name: s.name,\n handle: createLocalStorageHandle(s.id, s.root),\n initialFullPath: s.initialPath,\n }));\n\n const dataLibraries = await this.userResources.getDataLibraries();\n const remoteStorages = [...dataLibraries.values()].map((info) => ({\n id: info.storageId,\n name: info.storageName,\n handle: createRemoteStorageHandle(info),\n initialFullPath: \"\",\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 = remoteStorages.filter((it) => it.id !== \"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 rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, e.fullName, e.additionalInfo),\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: sdk.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 listRemoteFilesWithFileStats(\n storageHandle: sdk.StorageHandle,\n fullPath: string,\n ): Promise<ListRemoteFilesResultWithFileStats> {\n const storageData = parseStorageHandle(storageHandle);\n if (!storageData.isRemote) {\n throw new Error(`Storage ${storageData.name} is not remote`);\n }\n\n const rInfo = await this.resolveRemoteStorageResourceInfo(storageData);\n const response = await this.lsClient.list(rInfo, 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.storageId, e.fullName, e.additionalInfo),\n size: Number(e.size),\n })),\n };\n }\n\n /** Looks up ResourceType for a remote storage from the data libraries index. */\n private async resolveRemoteStorageResourceInfo(\n storageData: RemoteStorageHandleData,\n ): Promise<ResourceInfo> {\n return { id: storageData.resourceId, type: storageData.resourceType };\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.id, 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 client.userResources,\n signer,\n virtualStoragesMap,\n localProjectionsMap,\n openFileDialogCallback,\n );\n }\n}\n"],"mappings":";;;;;;;;;AAwDA,IAAa,WAAb,MAAa,SAAqC;CAChD,YACE,QACA,UACA,eACA,QAEA,oBAEA,qBACA,wBACA;AATiB,OAAA,SAAA;AACA,OAAA,WAAA;AACA,OAAA,gBAAA;AACA,OAAA,SAAA;AAEA,OAAA,qBAAA;AAEA,OAAA,sBAAA;AACA,OAAA,yBAAA;;CAGnB,MAAa,oBACX,MACA,OACqB;EACrB,MAAM,YAAY,MAAM,KAAK,0BAA0B,KAAK;AAE5D,MAAI,OAAO;GACT,MAAM,aAAa,MAAM,IAAI,KAAK,WAAW,IAAI;AACjD,OAAI;IACF,MAAM,SAAS,OAAO,MAAM,MAAM,OAAO;IACzC,MAAM,EAAE,cAAc,MAAM,WAAW,KAAK,QAAQ,GAAG,MAAM,QAAQ,MAAM,OAAO;AAClF,WAAO,IAAI,WAAW,OAAO,SAAS,GAAG,UAAU,CAAC;aAC5C;AACR,UAAM,WAAW,OAAO;;;AAI5B,SAAO,MAAM,IAAI,SAAS,UAAU;;CAGtC,MAAa,iBAAiB,MAAkD;EAC9E,MAAM,YAAY,MAAM,KAAK,0BAA0B,KAAK;AAE5D,UADa,MAAM,IAAI,KAAK,UAAU,EAC1B;;CAGd,MAAa,4BACX,KACwC;EACxC,MAAM,SAAS,MAAM,KAAK,uBAAuB,MAAM,IAAI;AAC3D,MAAI,WAAW,KAAA,EAAW,QAAO,EAAE;AACnC,SAAO,EACL,OAAO,MAAM,QAAQ,IAAI,OAAO,KAAK,cAAc,KAAK,mBAAmB,UAAU,CAAC,CAAC,EACxF;;CAGH,MAAa,yBACX,KACqC;EACrC,MAAM,SAAS,MAAM,KAAK,uBAAuB,OAAO,IAAI;AAC5D,MAAI,WAAW,KAAA,EAAW,QAAO,EAAE;AACnC,SAAO,EACL,MAAM,MAAM,KAAK,mBAAmB,OAAO,GAAG,EAC/C;;;;;;;;CASH,MAAc,0BAA0B,QAAoD;AAC1F,MAAI,wBAAwB,OAAO,EAAE;GACnC,MAAM,aAAa,iBAAiB,OAAO;GAC3C,MAAM,kBAAkB,KAAK,oBAAoB,IAAI,WAAW,UAAU;AAC1E,OAAI,CAAC,gBACH,OAAM,IAAI,MAAM,WAAW,WAAW,UAAU,0BAA0B;AAC5E,UAAOA,OAAK,KAAK,gBAAgB,WAAW,WAAW,KAAK;SACvD;GACL,MAAM,aAAa,kBAAkB,OAAO;AAE5C,QAAK,OAAO,OACV,WAAW,WACX,WAAW,eACX,kDACD;GAED,MAAM,YAAY,WAAW;GAE7B,MAAM,OAAO,MAAM,IAAI,KAAK,WAAW,EAAE,QAAQ,MAAM,CAAC;AACxD,OAAI,OAAO,KAAK,UAAU,MAAM,KAAK,WAAW,iBAC9C,OAAM,IAAI,MAAM,iDAAiD;AAEnE,UAAO;;;CAIX,MAAa,mBACX,WAC2D;AAC3D,mBAAiB,UAAU;AAI3B,OAAK,MAAM,MAAM,KAAK,oBAAoB,QAAQ,CAEhD,KAAI,UAAU,WAAW,GAAG,UAAU,EAAE;GAItC,MAAM,oBACJ,GAAG,cAAc,KAAK,YAAYA,OAAK,SAAS,GAAG,WAAW,UAAU;AAC1E,UAAO,wBACL,GAAG,WACH,kBACD;;EAML,MAAM,OAAO,MAAM,IAAI,KAAK,WAAW,EAAE,QAAQ,MAAM,CAAC;AACxD,SAAO,yBACL,WACA,KAAK,QACL,KAAK,MACL,KAAK,UAAU,MAChB;;CAGH,MAAa,iBAA8C;EACzD,MAAM,kBAAkB,CAAC,GAAG,KAAK,mBAAmB,QAAQ,CAAC,CAAC,KAAK,OAAO;GACxE,IAAI,EAAE;GACN,MAAM,EAAE;GACR,QAAQ,yBAAyB,EAAE,IAAI,EAAE,KAAK;GAC9C,iBAAiB,EAAE;GACpB,EAAE;EAcH,MAAM,SAXiB,CAAC,IADF,MAAM,KAAK,cAAc,kBAAkB,EACxB,QAAQ,CAAC,CAAC,KAAK,UAAU;GAChE,IAAI,KAAK;GACT,MAAM,KAAK;GACX,QAAQ,0BAA0B,KAAK;GACvC,iBAAiB;GAClB,EAAE,CAM2B,QAAQ,OAAO,GAAG,OAAO,OAAO;AAE9D,SAAO,CAAC,GAAG,iBAAiB,GAAG,OAAO;;CAGxC,MAAa,UACX,eACA,UAC8B;EAC9B,MAAM,cAAc,mBAAmB,cAAc;AAErD,MAAI,YAAY,UAAU;GACxB,MAAM,QAAQ,MAAM,KAAK,iCAAiC,YAAY;AAEtE,UAAO,EACL,UAFe,MAAM,KAAK,SAAS,KAAK,OAAO,SAAS,EAEtC,MAAM,KAAK,OAAO;IAClC,MAAM,EAAE,QAAQ,QAAQ;IACxB,MAAM,EAAE;IACR,UAAU,EAAE;IACZ,QAAQ,wBAAwB,YAAY,WAAW,EAAE,UAAU,EAAE,eAAe;IACrF,EAAE,EACJ;;AAGH,MAAIA,OAAK,QAAQ,OAAO,aAAa,GAAI,YAAW;AAEpD,MAAI,YAAY,aAAa,GAC3B,kBAAiB,SAAS;EAE5B,MAAM,SAASA,OAAK,WAAW,SAAS,GAAG,WAAWA,OAAK,KAAK,YAAY,UAAU,SAAS;EAE/F,MAAM,UAAyB,EAAE;AACjC,aAAW,MAAM,UAAU,MAAM,IAAI,QAAQ,OAAO,EAAE;AACpD,OAAI,CAAC,OAAO,QAAQ,IAAI,CAAC,OAAO,aAAa,CAAE;GAK/C,MAAM,eAAeA,OAAK,KAAK,QAAQ,OAAO,KAAK;AAEnD,WAAQ,KAAK;IACX,MAAM,OAAO,QAAQ,GAAG,SAAS;IACjC,MAAM,OAAO;IACb,UAAU;IACV,QAAQ,MAAM,KAAK,mBAAmB,aAAa;IACpD,CAAC;;AAGJ,SAAO,EAAE,SAAS;;CAGpB,MAAa,6BACX,eACA,UAC6C;EAC7C,MAAM,cAAc,mBAAmB,cAAc;AACrD,MAAI,CAAC,YAAY,SACf,OAAM,IAAI,MAAM,WAAW,YAAY,KAAK,gBAAgB;EAG9D,MAAM,QAAQ,MAAM,KAAK,iCAAiC,YAAY;AAGtE,SAAO,EACL,UAHe,MAAM,KAAK,SAAS,KAAK,OAAO,SAAS,EAGtC,MAAM,KAAK,OAAO;GAClC,MAAM,EAAE,QAAQ,QAAQ;GACxB,MAAM,EAAE;GACR,UAAU,EAAE;GACZ,QAAQ,wBAAwB,YAAY,WAAW,EAAE,UAAU,EAAE,eAAe;GACpF,MAAM,OAAO,EAAE,KAAK;GACrB,EAAE,EACJ;;;CAIH,MAAc,iCACZ,aACuB;AACvB,SAAO;GAAE,IAAI,YAAY;GAAY,MAAM,YAAY;GAAc;;CAGvE,MAAa,mBAAmB,OAAoD;AAClF,QAAM,IAAI,MACR,8FACD;;CAGH,aAAoB,KAClB,QACA,QACA,QAEA,kBACA,wBACA,iBACmB;EACnB,MAAM,WAAW,oBAAoB,QAAQ,OAAO;AAEpD,MAAI,CAAC,gBAAiB,mBAAkB,MAAM,6BAA6B;AAG3E,OAAK,MAAM,MAAM,gBAAiB,kBAAiB,GAAG,KAAK;AAC3D,OAAK,MAAM,MAAM,iBAAkB,KAAI,GAAG,cAAc,GAAI,kBAAiB,GAAG,UAAU;EAG1F,MAAM,qBAAqB,IAAI,IAAI,gBAAgB,KAAK,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;EACzE,MAAM,sBAAsB,IAAI,IAAI,iBAAiB,KAAK,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;AAGlF,MACE,IAAI,IAAI,CAAC,GAAG,mBAAmB,MAAM,EAAE,GAAG,oBAAoB,MAAM,CAAC,CAAC,CAAC,SACvE,mBAAmB,OAAO,oBAAoB,KAE9C,OAAM,IAAI,MACR,yFACD;AAEH,SAAO,IAAI,SACT,QACA,UACA,OAAO,eACP,QACA,oBACA,qBACA,uBACD"}
@@ -21,7 +21,8 @@ const ImportFileHandleUploadData = zod.z.object({
21
21
  });
22
22
  const ImportFileHandleIndexData = zod.z.object({
23
23
  storageId: zod.z.string(),
24
- path: zod.z.string()
24
+ path: zod.z.string(),
25
+ additionalInfo: zod.z.record(zod.z.string(), zod.z.string()).optional()
25
26
  });
26
27
  const ImportFileHandleData = zod.z.union([ImportFileHandleUploadData, ImportFileHandleIndexData]);
27
28
  /** Options from BlobUpload resource that have to be passed to getProgress. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs","names":["z"],"sources":["../../src/drivers/types.ts"],"sourcesContent":["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(\n `getSize: range (${JSON.stringify(range)}, newSize: ${newSize}) is greater than size (${size})`,\n );\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 /** Stable machine identifier, must not intersect with other storage ids */\n readonly id: string;\n /** Human-readable display name */\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"],"mappings":";;;;;AASA,MAAa,gCAAA,GAAA,wBAAA,UAAwC,EACnD,IAAI,EACF,qBAAqBA,IAAAA,EAAE,OAAO,EAC5B,WAAWA,IAAAA,EAAE,OAAO,QAAQ,EAC7B,CAAC,EACH,EACF,CAAC;AAIF,SAAgB,QAAQ,IAAkC,OAA4B;CACpF,MAAM,OAAO,GAAG,GAAG,qBAAqB;AACxC,KAAI,OAAO;EACT,MAAM,UAAU,MAAM,KAAK,MAAM;AACjC,MAAI,UAAU,KACZ,OAAM,IAAI,MACR,mBAAmB,KAAK,UAAU,MAAM,CAAC,aAAa,QAAQ,0BAA0B,KAAK,GAC9F;AAGH,SAAO;;AAGT,QAAO;;AAOT,MAAa,6BAA6BA,IAAAA,EAAE,OAAO;CAEjD,WAAWA,IAAAA,EAAE,QAAQ;CAErB,eAAeA,IAAAA,EAAE,QAAQ;CAEzB,WAAWA,IAAAA,EAAE,QAAQ;CAErB,kBAAkBA,IAAAA,EAAE,QAAQ;CAC7B,CAAC;AAGF,MAAa,4BAA4BA,IAAAA,EAAE,OAAO;CAEhD,WAAWA,IAAAA,EAAE,QAAQ;CAErB,MAAMA,IAAAA,EAAE,QAAQ;CACjB,CAAC;AAGF,MAAa,uBAAuBA,IAAAA,EAAE,MAAM,CAC1C,4BACA,0BACD,CAAC;;;AAMF,MAAa,0BAAA,GAAA,wBAAA,UAAkC;CAC7C,MAAM;CACN,QAAQ,EACN,MAAM,OACP;CACF,CAAC;AAEF,MAAa,yBAAA,GAAA,wBAAA,UAAiC,EAC5C,QAAQ,EACN,aAAa,OACd,EACF,CAAC"}
1
+ {"version":3,"file":"types.cjs","names":["z"],"sources":["../../src/drivers/types.ts"],"sourcesContent":["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(\n `getSize: range (${JSON.stringify(range)}, newSize: ${newSize}) is greater than size (${size})`,\n );\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 /**\n * Federative identity envelope from LsAPI.List.Response.ListItem.additional_info.\n * Absent for non-federative storages (backwards compatible: old handles parse unchanged).\n */\n additionalInfo: z.record(z.string(), z.string()).optional(),\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 /** Stable machine identifier, must not intersect with other storage ids */\n readonly id: string;\n /** Human-readable display name */\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"],"mappings":";;;;;AASA,MAAa,gCAAA,GAAA,wBAAA,UAAwC,EACnD,IAAI,EACF,qBAAqBA,IAAAA,EAAE,OAAO,EAC5B,WAAWA,IAAAA,EAAE,OAAO,QAAQ,EAC7B,CAAC,EACH,EACF,CAAC;AAIF,SAAgB,QAAQ,IAAkC,OAA4B;CACpF,MAAM,OAAO,GAAG,GAAG,qBAAqB;AACxC,KAAI,OAAO;EACT,MAAM,UAAU,MAAM,KAAK,MAAM;AACjC,MAAI,UAAU,KACZ,OAAM,IAAI,MACR,mBAAmB,KAAK,UAAU,MAAM,CAAC,aAAa,QAAQ,0BAA0B,KAAK,GAC9F;AAGH,SAAO;;AAGT,QAAO;;AAOT,MAAa,6BAA6BA,IAAAA,EAAE,OAAO;CAEjD,WAAWA,IAAAA,EAAE,QAAQ;CAErB,eAAeA,IAAAA,EAAE,QAAQ;CAEzB,WAAWA,IAAAA,EAAE,QAAQ;CAErB,kBAAkBA,IAAAA,EAAE,QAAQ;CAC7B,CAAC;AAGF,MAAa,4BAA4BA,IAAAA,EAAE,OAAO;CAEhD,WAAWA,IAAAA,EAAE,QAAQ;CAErB,MAAMA,IAAAA,EAAE,QAAQ;CAKhB,gBAAgBA,IAAAA,EAAE,OAAOA,IAAAA,EAAE,QAAQ,EAAEA,IAAAA,EAAE,QAAQ,CAAC,CAAC,UAAU;CAC5D,CAAC;AAGF,MAAa,uBAAuBA,IAAAA,EAAE,MAAM,CAC1C,4BACA,0BACD,CAAC;;;AAMF,MAAa,0BAAA,GAAA,wBAAA,UAAkC;CAC7C,MAAM;CACN,QAAQ,EACN,MAAM,OACP;CACF,CAAC;AAEF,MAAa,yBAAA,GAAA,wBAAA,UAAiC,EAC5C,QAAQ,EACN,aAAa,OACd,EACF,CAAC"}
@@ -36,12 +36,19 @@ type ImportFileHandleUploadData = z.infer<typeof ImportFileHandleUploadData>;
36
36
  declare const ImportFileHandleIndexData: z.ZodObject<{
37
37
  /** Pl storage id */storageId: z.ZodString; /** Path inside storage */
38
38
  path: z.ZodString;
39
+ /**
40
+ * Federative identity envelope from LsAPI.List.Response.ListItem.additional_info.
41
+ * Absent for non-federative storages (backwards compatible: old handles parse unchanged).
42
+ */
43
+ additionalInfo: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
39
44
  }, "strip", z.ZodTypeAny, {
40
45
  path: string;
41
46
  storageId: string;
47
+ additionalInfo?: Record<string, string> | undefined;
42
48
  }, {
43
49
  path: string;
44
50
  storageId: string;
51
+ additionalInfo?: Record<string, string> | undefined;
45
52
  }>;
46
53
  type ImportFileHandleIndexData = z.infer<typeof ImportFileHandleIndexData>;
47
54
  declare const ImportFileHandleData: z.ZodUnion<[z.ZodObject<{
@@ -62,12 +69,19 @@ declare const ImportFileHandleData: z.ZodUnion<[z.ZodObject<{
62
69
  }>, z.ZodObject<{
63
70
  /** Pl storage id */storageId: z.ZodString; /** Path inside storage */
64
71
  path: z.ZodString;
72
+ /**
73
+ * Federative identity envelope from LsAPI.List.Response.ListItem.additional_info.
74
+ * Absent for non-federative storages (backwards compatible: old handles parse unchanged).
75
+ */
76
+ additionalInfo: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
65
77
  }, "strip", z.ZodTypeAny, {
66
78
  path: string;
67
79
  storageId: string;
80
+ additionalInfo?: Record<string, string> | undefined;
68
81
  }, {
69
82
  path: string;
70
83
  storageId: string;
84
+ additionalInfo?: Record<string, string> | undefined;
71
85
  }>]>;
72
86
  type ImportFileHandleData = z.infer<typeof ImportFileHandleData>;
73
87
  /** Options from BlobUpload resource that have to be passed to getProgress. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/drivers/types.ts"],"mappings":";;;;;;;cASa,4BAAA,6BAA4B,sBAAA;EAAA;;;;;;;;KAQ7B,4BAAA,GAA+B,aAAA,QAAqB,4BAAA;AAAA,iBAEhD,OAAA,CAAQ,EAAA,EAAI,4BAAA,EAA8B,KAAA,GAAQ,UAAA;AAAA,cAoBrD,0BAAA,EAA0B,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;KAU3B,0BAAA,GAA6B,CAAA,CAAE,KAAA,QAAa,0BAAA;AAAA,cAE3C,yBAAA,EAAyB,CAAA,CAAA,SAAA;EAhCV,4CAAsC;;;;;;;;;KAsCtD,yBAAA,GAA4B,CAAA,CAAE,KAAA,QAAa,yBAAA;AAAA,cAE1C,oBAAA,EAAoB,CAAA,CAAA,QAAA,EAAA,CAAA,CAAA,SAAA;yEApBM;8BAAA;;;;;;;;;;;;;;;;;;;;;;;KAwB3B,oBAAA,GAAuB,CAAA,CAAE,KAAA,QAAa,oBAAA;;;cAKrC,sBAAA,EAAsB,0BAAA,CAAA,sBAAA,CAAA,CAAA,CAAA,SAAA;EAnBM,uEAAe;8BAA0B;0BAOhF;;;;;;;;;;;;;;;cAmBW,qBAAA,EAIX,0BAAA,CAJgC,sBAAA;EAAA,SAAA,WAAA;AAAA;AAAA,KAMtB,sBAAA,GAAyB,aAAA,QAAqB,sBAAA;AAAA,KAC9C,qBAAA,GAAwB,aAAA,QAAqB,qBAAA;AAAA,KAE7C,sBAAA,GAAyB,sBAAA,GAAyB,qBAAA;;KAOlD,sBAAA;+BAED,SAAA;EApC0B;;;;;;EAAA,SA4C1B,SAAA;AAAA;AA1CX;AAAA,KA8CY,uBAAA;sFAED,EAAA;WAEA,IAAA;WAGA,IAAA,UArDsB;EAAA,SAwDtB,WAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/drivers/types.ts"],"mappings":";;;;;;;cASa,4BAAA,6BAA4B,sBAAA;EAAA;;;;;;;;KAQ7B,4BAAA,GAA+B,aAAA,QAAqB,4BAAA;AAAA,iBAEhD,OAAA,CAAQ,EAAA,EAAI,4BAAA,EAA8B,KAAA,GAAQ,UAAA;AAAA,cAoBrD,0BAAA,EAA0B,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;KAU3B,0BAAA,GAA6B,CAAA,CAAE,KAAA,QAAa,0BAAA;AAAA,cAE3C,yBAAA,EAAyB,CAAA,CAAA,SAAA;EAhCV,4CAAsC;;EAAU;;AAoB5E;;;;;;;;;;;;KAuBY,yBAAA,GAA4B,CAAA,CAAE,KAAA,QAAa,yBAAA;AAAA,cAE1C,oBAAA,EAAoB,CAAA,CAAA,QAAA,EAAA,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;EAfrB;;;;;;;;;;;;;;KAmBA,oBAAA,GAAuB,CAAA,CAAE,KAAA,QAAa,oBAAA;;;cAKrC,sBAAA,EAAsB,0BAAA,CAAA,sBAAA,CAAA,CAAA,CAAA,SAAA;;8BAtBG;0BAAA;;;;;;;;;;;;;;;cA6BzB,qBAAA,EAIX,0BAAA,CAJgC,sBAAA;EAAA,SAAA,WAAA;AAAA;AAAA,KAMtB,sBAAA,GAAyB,aAAA,QAAqB,sBAAA;AAAA,KAC9C,qBAAA,GAAwB,aAAA,QAAqB,qBAAA;AAAA,KAE7C,sBAAA,GAAyB,sBAAA,GAAyB,qBAAA;;KAOlD,sBAAA;+BAED,SAAA;;;;;AApCX;;WA4CW,SAAA;AAAA;;KAIC,uBAAA;EAhD2C,oFAkD5C,EAAA,UAlDqE;EAAA,SAoDrE,IAAA,UA/CT;EAAA,SAkDS,IAAA;WAGA,WAAA;AAAA"}
@@ -20,7 +20,8 @@ const ImportFileHandleUploadData = z.object({
20
20
  });
21
21
  const ImportFileHandleIndexData = z.object({
22
22
  storageId: z.string(),
23
- path: z.string()
23
+ path: z.string(),
24
+ additionalInfo: z.record(z.string(), z.string()).optional()
24
25
  });
25
26
  const ImportFileHandleData = z.union([ImportFileHandleUploadData, ImportFileHandleIndexData]);
26
27
  /** Options from BlobUpload resource that have to be passed to getProgress. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../src/drivers/types.ts"],"sourcesContent":["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(\n `getSize: range (${JSON.stringify(range)}, newSize: ${newSize}) is greater than size (${size})`,\n );\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 /** Stable machine identifier, must not intersect with other storage ids */\n readonly id: string;\n /** Human-readable display name */\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"],"mappings":";;;;AASA,MAAa,+BAA+B,SAAS,EACnD,IAAI,EACF,qBAAqB,EAAE,OAAO,EAC5B,WAAW,EAAE,OAAO,QAAQ,EAC7B,CAAC,EACH,EACF,CAAC;AAIF,SAAgB,QAAQ,IAAkC,OAA4B;CACpF,MAAM,OAAO,GAAG,GAAG,qBAAqB;AACxC,KAAI,OAAO;EACT,MAAM,UAAU,MAAM,KAAK,MAAM;AACjC,MAAI,UAAU,KACZ,OAAM,IAAI,MACR,mBAAmB,KAAK,UAAU,MAAM,CAAC,aAAa,QAAQ,0BAA0B,KAAK,GAC9F;AAGH,SAAO;;AAGT,QAAO;;AAOT,MAAa,6BAA6B,EAAE,OAAO;CAEjD,WAAW,EAAE,QAAQ;CAErB,eAAe,EAAE,QAAQ;CAEzB,WAAW,EAAE,QAAQ;CAErB,kBAAkB,EAAE,QAAQ;CAC7B,CAAC;AAGF,MAAa,4BAA4B,EAAE,OAAO;CAEhD,WAAW,EAAE,QAAQ;CAErB,MAAM,EAAE,QAAQ;CACjB,CAAC;AAGF,MAAa,uBAAuB,EAAE,MAAM,CAC1C,4BACA,0BACD,CAAC;;;AAMF,MAAa,yBAAyB,SAAS;CAC7C,MAAM;CACN,QAAQ,EACN,MAAM,OACP;CACF,CAAC;AAEF,MAAa,wBAAwB,SAAS,EAC5C,QAAQ,EACN,aAAa,OACd,EACF,CAAC"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../src/drivers/types.ts"],"sourcesContent":["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(\n `getSize: range (${JSON.stringify(range)}, newSize: ${newSize}) is greater than size (${size})`,\n );\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 /**\n * Federative identity envelope from LsAPI.List.Response.ListItem.additional_info.\n * Absent for non-federative storages (backwards compatible: old handles parse unchanged).\n */\n additionalInfo: z.record(z.string(), z.string()).optional(),\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 /** Stable machine identifier, must not intersect with other storage ids */\n readonly id: string;\n /** Human-readable display name */\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"],"mappings":";;;;AASA,MAAa,+BAA+B,SAAS,EACnD,IAAI,EACF,qBAAqB,EAAE,OAAO,EAC5B,WAAW,EAAE,OAAO,QAAQ,EAC7B,CAAC,EACH,EACF,CAAC;AAIF,SAAgB,QAAQ,IAAkC,OAA4B;CACpF,MAAM,OAAO,GAAG,GAAG,qBAAqB;AACxC,KAAI,OAAO;EACT,MAAM,UAAU,MAAM,KAAK,MAAM;AACjC,MAAI,UAAU,KACZ,OAAM,IAAI,MACR,mBAAmB,KAAK,UAAU,MAAM,CAAC,aAAa,QAAQ,0BAA0B,KAAK,GAC9F;AAGH,SAAO;;AAGT,QAAO;;AAOT,MAAa,6BAA6B,EAAE,OAAO;CAEjD,WAAW,EAAE,QAAQ;CAErB,eAAe,EAAE,QAAQ;CAEzB,WAAW,EAAE,QAAQ;CAErB,kBAAkB,EAAE,QAAQ;CAC7B,CAAC;AAGF,MAAa,4BAA4B,EAAE,OAAO;CAEhD,WAAW,EAAE,QAAQ;CAErB,MAAM,EAAE,QAAQ;CAKhB,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC,UAAU;CAC5D,CAAC;AAGF,MAAa,uBAAuB,EAAE,MAAM,CAC1C,4BACA,0BACD,CAAC;;;AAMF,MAAa,yBAAyB,SAAS;CAC7C,MAAM;CACN,QAAQ,EACN,MAAM,OACP;CACF,CAAC;AAEF,MAAa,wBAAwB,SAAS,EAC5C,QAAQ,EACN,aAAa,OACd,EACF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -14,9 +14,9 @@ import { UploadTask, isMyUpload, isSignMatch, isTerminalUploadError, isUpload, n
14
14
  import { LogsStreamDriver, LogsStreamDriverOps } from "./drivers/logs_stream.js";
15
15
  import { LogsDriver } from "./drivers/logs.js";
16
16
  import { DownloadUrlDriver, DownloadUrlDriverOps, DownloadUrlSyncReader, UrlResult } from "./drivers/download_url/driver.js";
17
- import { InternalLsDriver, ListRemoteFilesResultWithAdditionalInfo, LsDriver, LsEntryWithAdditionalInfo, OpenFileDialogCallback } from "./drivers/ls.js";
17
+ import { InternalLsDriver, ListRemoteFilesResultWithFileStats, LsDriver, LsEntryWithFileStats, OpenFileDialogCallback } from "./drivers/ls.js";
18
18
  import { DefaultVirtualLocalStorages } from "./drivers/virtual_storages.js";
19
19
  import { Updater, WrongResourceTypeError } from "./drivers/helpers/helpers.js";
20
20
  import { DownloadNetworkError, DownloadNetworkError400, OffByOneError, isDownloadNetworkError, isDownloadNetworkError400, isOffByOneError } from "./helpers/download_errors.js";
21
21
  import { validateAbsolute } from "./helpers/validate.js";
22
- export { BadRequestError, ClientDownload, ClientLogs, ClientLs, ClientProgress, ClientUpload, DefaultVirtualLocalStorages, DownloadBlobToURLDriver, DownloadBlobToURLDriverOps, DownloadDriver, DownloadDriverOps, DownloadNetworkError, DownloadNetworkError400, DownloadUrlDriver, DownloadUrlDriverOps, DownloadUrlSyncReader, DownloadableBlobSnapshot, ImportFileHandleData, ImportFileHandleIndexData, ImportFileHandleUploadData, ImportResourceSnapshot, IndexResourceSnapshot, InternalLsDriver, ListRemoteFilesResultWithAdditionalInfo, LocalStorageProjection, LogsDriver, LogsStreamDriver, LogsStreamDriverOps, LsDriver, LsEntryWithAdditionalInfo, MTimeError, NetworkError, NoFileForUploading, OffByOneError, OnDemandBlobResourceSnapshot, OpenFileDialogCallback, PollingOps, ProgressStatus, UnexpectedEOF, UnknownStorageError, Updater, UploadDriver, UploadDriverOps, UploadResourceSnapshot, UploadTask, UrlResult, VirtualLocalStorageSpec, WrongLocalFileUrl, WrongResourceTypeError, createDownloadClient, createLogsClient, createLsFilesClient, createUploadBlobClient, createUploadProgressClient, getFullPath, getSize, isDownloadNetworkError, isDownloadNetworkError400, isMyUpload, isOffByOneError, isSignMatch, isTerminalUploadError, isUpload, makeBlobImportSnapshot, makeDownloadableBlobSnapshot, newLocalStorageIdsToRoot, nonRecoverableError, parseLocalUrl, uploadBlob, validateAbsolute };
22
+ export { BadRequestError, ClientDownload, ClientLogs, ClientLs, ClientProgress, ClientUpload, DefaultVirtualLocalStorages, DownloadBlobToURLDriver, DownloadBlobToURLDriverOps, DownloadDriver, DownloadDriverOps, DownloadNetworkError, DownloadNetworkError400, DownloadUrlDriver, DownloadUrlDriverOps, DownloadUrlSyncReader, DownloadableBlobSnapshot, ImportFileHandleData, ImportFileHandleIndexData, ImportFileHandleUploadData, ImportResourceSnapshot, IndexResourceSnapshot, InternalLsDriver, ListRemoteFilesResultWithFileStats, LocalStorageProjection, LogsDriver, LogsStreamDriver, LogsStreamDriverOps, LsDriver, LsEntryWithFileStats, MTimeError, NetworkError, NoFileForUploading, OffByOneError, OnDemandBlobResourceSnapshot, OpenFileDialogCallback, PollingOps, ProgressStatus, UnexpectedEOF, UnknownStorageError, Updater, UploadDriver, UploadDriverOps, UploadResourceSnapshot, UploadTask, UrlResult, VirtualLocalStorageSpec, WrongLocalFileUrl, WrongResourceTypeError, createDownloadClient, createLogsClient, createLsFilesClient, createUploadBlobClient, createUploadProgressClient, getFullPath, getSize, isDownloadNetworkError, isDownloadNetworkError400, isMyUpload, isOffByOneError, isSignMatch, isTerminalUploadError, isUpload, makeBlobImportSnapshot, makeDownloadableBlobSnapshot, newLocalStorageIdsToRoot, nonRecoverableError, parseLocalUrl, uploadBlob, validateAbsolute };
@@ -55,6 +55,16 @@ var LsAPI_ListItem$Type = class extends _protobuf_ts_runtime.MessageType {
55
55
  kind: "scalar",
56
56
  T: 8
57
57
  },
58
+ {
59
+ no: 8,
60
+ name: "additional_info",
61
+ kind: "map",
62
+ K: 9,
63
+ V: {
64
+ kind: "scalar",
65
+ T: 9
66
+ }
67
+ },
58
68
  {
59
69
  no: 10,
60
70
  name: "full_name",
@@ -86,6 +96,7 @@ var LsAPI_ListItem$Type = class extends _protobuf_ts_runtime.MessageType {
86
96
  message.name = "";
87
97
  message.size = 0n;
88
98
  message.isDir = false;
99
+ message.additionalInfo = {};
89
100
  message.fullName = "";
90
101
  message.directory = "";
91
102
  message.version = "";
@@ -106,6 +117,9 @@ var LsAPI_ListItem$Type = class extends _protobuf_ts_runtime.MessageType {
106
117
  case 3:
107
118
  message.isDir = reader.bool();
108
119
  break;
120
+ case 8:
121
+ this.binaryReadMap8(message.additionalInfo, reader, options);
122
+ break;
109
123
  case 10:
110
124
  message.fullName = reader.string();
111
125
  break;
@@ -127,10 +141,27 @@ var LsAPI_ListItem$Type = class extends _protobuf_ts_runtime.MessageType {
127
141
  }
128
142
  return message;
129
143
  }
144
+ binaryReadMap8(map, reader, options) {
145
+ let len = reader.uint32(), end = reader.pos + len, key, val;
146
+ while (reader.pos < end) {
147
+ let [fieldNo, wireType] = reader.tag();
148
+ switch (fieldNo) {
149
+ case 1:
150
+ key = reader.string();
151
+ break;
152
+ case 2:
153
+ val = reader.string();
154
+ break;
155
+ default: throw new globalThis.Error("unknown map entry field for MiLaboratories.Controller.Shared.LsAPI.ListItem.additional_info");
156
+ }
157
+ }
158
+ map[key ?? ""] = val ?? "";
159
+ }
130
160
  internalBinaryWrite(message, writer, options) {
131
161
  if (message.name !== "") writer.tag(1, _protobuf_ts_runtime.WireType.LengthDelimited).string(message.name);
132
162
  if (message.size !== 0n) writer.tag(2, _protobuf_ts_runtime.WireType.Varint).uint64(message.size);
133
163
  if (message.isDir !== false) writer.tag(3, _protobuf_ts_runtime.WireType.Varint).bool(message.isDir);
164
+ for (let k of globalThis.Object.keys(message.additionalInfo)) writer.tag(8, _protobuf_ts_runtime.WireType.LengthDelimited).fork().tag(1, _protobuf_ts_runtime.WireType.LengthDelimited).string(k).tag(2, _protobuf_ts_runtime.WireType.LengthDelimited).string(message.additionalInfo[k]).join();
134
165
  if (message.fullName !== "") writer.tag(10, _protobuf_ts_runtime.WireType.LengthDelimited).string(message.fullName);
135
166
  if (message.directory !== "") writer.tag(11, _protobuf_ts_runtime.WireType.LengthDelimited).string(message.directory);
136
167
  if (message.lastModified) require_timestamp.Timestamp.internalBinaryWrite(message.lastModified, writer.tag(12, _protobuf_ts_runtime.WireType.LengthDelimited).fork(), options).join();