@lakutata/containerd 0.0.0-stage → 3.0.0-beta.1

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 (301) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +409 -2
  3. package/THIRD_PARTY_NOTICES.md +310 -0
  4. package/dist/cjs/client/BuildKit.d.ts +176 -0
  5. package/dist/cjs/client/BuildKit.js +536 -0
  6. package/dist/cjs/client/BuildKitMessages.d.ts +35 -0
  7. package/dist/cjs/client/BuildKitMessages.js +123 -0
  8. package/dist/cjs/client/ContainerStore.d.ts +558 -0
  9. package/dist/cjs/client/ContainerStore.js +1384 -0
  10. package/dist/cjs/client/ContainerdClient.d.ts +244 -0
  11. package/dist/cjs/client/ContainerdClient.js +455 -0
  12. package/dist/cjs/client/DockerIgnore.d.ts +44 -0
  13. package/dist/cjs/client/DockerIgnore.js +186 -0
  14. package/dist/cjs/client/Fifo.d.ts +31 -0
  15. package/dist/cjs/client/Fifo.js +66 -0
  16. package/dist/cjs/client/ImageStore.d.ts +258 -0
  17. package/dist/cjs/client/ImageStore.js +636 -0
  18. package/dist/cjs/client/Messages.d.ts +103 -0
  19. package/dist/cjs/client/Messages.js +397 -0
  20. package/dist/cjs/client/Networks.d.ts +221 -0
  21. package/dist/cjs/client/Networks.js +630 -0
  22. package/dist/cjs/client/Platforms.d.ts +53 -0
  23. package/dist/cjs/client/Platforms.js +169 -0
  24. package/dist/cjs/client/Reference.d.ts +33 -0
  25. package/dist/cjs/client/Reference.js +70 -0
  26. package/dist/cjs/client/Registry.d.ts +145 -0
  27. package/dist/cjs/client/Registry.js +272 -0
  28. package/dist/cjs/client/Rootfs.d.ts +83 -0
  29. package/dist/cjs/client/Rootfs.js +245 -0
  30. package/dist/cjs/client/Seccomp.d.ts +36 -0
  31. package/dist/cjs/client/Seccomp.js +156 -0
  32. package/dist/cjs/client/Spec.d.ts +151 -0
  33. package/dist/cjs/client/Spec.js +227 -0
  34. package/dist/cjs/client/Volumes.d.ts +42 -0
  35. package/dist/cjs/client/Volumes.js +80 -0
  36. package/dist/cjs/containerd/Containerd.d.ts +442 -0
  37. package/dist/cjs/containerd/Containerd.js +929 -0
  38. package/dist/cjs/containerd/exceptions/ContainerdConnectionException.d.ts +9 -0
  39. package/dist/cjs/containerd/exceptions/ContainerdConnectionException.js +16 -0
  40. package/dist/cjs/containerd/exceptions/ContainerdContainerNameConflictException.d.ts +8 -0
  41. package/dist/cjs/containerd/exceptions/ContainerdContainerNameConflictException.js +15 -0
  42. package/dist/cjs/containerd/exceptions/ContainerdContainerNotFoundException.d.ts +9 -0
  43. package/dist/cjs/containerd/exceptions/ContainerdContainerNotFoundException.js +16 -0
  44. package/dist/cjs/containerd/exceptions/ContainerdContainerStateException.d.ts +10 -0
  45. package/dist/cjs/containerd/exceptions/ContainerdContainerStateException.js +17 -0
  46. package/dist/cjs/containerd/exceptions/ContainerdImageBuildException.d.ts +9 -0
  47. package/dist/cjs/containerd/exceptions/ContainerdImageBuildException.js +16 -0
  48. package/dist/cjs/containerd/exceptions/ContainerdImageExportException.d.ts +9 -0
  49. package/dist/cjs/containerd/exceptions/ContainerdImageExportException.js +16 -0
  50. package/dist/cjs/containerd/exceptions/ContainerdImageImportException.d.ts +9 -0
  51. package/dist/cjs/containerd/exceptions/ContainerdImageImportException.js +16 -0
  52. package/dist/cjs/containerd/exceptions/ContainerdImageNotFoundException.d.ts +9 -0
  53. package/dist/cjs/containerd/exceptions/ContainerdImageNotFoundException.js +16 -0
  54. package/dist/cjs/containerd/exceptions/ContainerdImagePullException.d.ts +9 -0
  55. package/dist/cjs/containerd/exceptions/ContainerdImagePullException.js +16 -0
  56. package/dist/cjs/containerd/exceptions/ContainerdImagePushException.d.ts +8 -0
  57. package/dist/cjs/containerd/exceptions/ContainerdImagePushException.js +15 -0
  58. package/dist/cjs/containerd/exceptions/ContainerdNetworkConflictException.d.ts +9 -0
  59. package/dist/cjs/containerd/exceptions/ContainerdNetworkConflictException.js +16 -0
  60. package/dist/cjs/containerd/exceptions/ContainerdNetworkNotFoundException.d.ts +9 -0
  61. package/dist/cjs/containerd/exceptions/ContainerdNetworkNotFoundException.js +16 -0
  62. package/dist/cjs/containerd/exceptions/ContainerdPathNotFoundException.d.ts +8 -0
  63. package/dist/cjs/containerd/exceptions/ContainerdPathNotFoundException.js +15 -0
  64. package/dist/cjs/containerd/exceptions/ContainerdPlatformException.d.ts +9 -0
  65. package/dist/cjs/containerd/exceptions/ContainerdPlatformException.js +16 -0
  66. package/dist/cjs/containerd/exceptions/ContainerdVolumeInUseException.d.ts +8 -0
  67. package/dist/cjs/containerd/exceptions/ContainerdVolumeInUseException.js +15 -0
  68. package/dist/cjs/containerd/exceptions/ContainerdVolumeNotFoundException.d.ts +8 -0
  69. package/dist/cjs/containerd/exceptions/ContainerdVolumeNotFoundException.js +15 -0
  70. package/dist/cjs/containerd/lib/ContainerdContainer.d.ts +292 -0
  71. package/dist/cjs/containerd/lib/ContainerdContainer.js +536 -0
  72. package/dist/cjs/containerd/lib/ContainerdContainerTTY.d.ts +116 -0
  73. package/dist/cjs/containerd/lib/ContainerdContainerTTY.js +178 -0
  74. package/dist/cjs/containerd/lib/ContainerdErrors.d.ts +6 -0
  75. package/dist/cjs/containerd/lib/ContainerdErrors.js +37 -0
  76. package/dist/cjs/containerd/lib/ContainerdImage.d.ts +149 -0
  77. package/dist/cjs/containerd/lib/ContainerdImage.js +222 -0
  78. package/dist/cjs/containerd/options/ContainerdPruneOptions.d.ts +44 -0
  79. package/dist/cjs/containerd/options/ContainerdPruneOptions.js +51 -0
  80. package/dist/cjs/containerd/options/ContainerdRegistryAuthOptions.d.ts +32 -0
  81. package/dist/cjs/containerd/options/ContainerdRegistryAuthOptions.js +45 -0
  82. package/dist/cjs/containerd/options/container/ContainerCommitOptions.d.ts +57 -0
  83. package/dist/cjs/containerd/options/container/ContainerCommitOptions.js +66 -0
  84. package/dist/cjs/containerd/options/container/ContainerCreateOptions.d.ts +273 -0
  85. package/dist/cjs/containerd/options/container/ContainerCreateOptions.js +239 -0
  86. package/dist/cjs/containerd/options/container/ContainerExecOptions.d.ts +53 -0
  87. package/dist/cjs/containerd/options/container/ContainerExecOptions.js +63 -0
  88. package/dist/cjs/containerd/options/container/ContainerExportDirectoryOptions.d.ts +32 -0
  89. package/dist/cjs/containerd/options/container/ContainerExportDirectoryOptions.js +45 -0
  90. package/dist/cjs/containerd/options/container/ContainerKillOptions.d.ts +30 -0
  91. package/dist/cjs/containerd/options/container/ContainerKillOptions.js +41 -0
  92. package/dist/cjs/containerd/options/container/ContainerLogsOptions.d.ts +34 -0
  93. package/dist/cjs/containerd/options/container/ContainerLogsOptions.js +44 -0
  94. package/dist/cjs/containerd/options/container/ContainerRemoveOptions.d.ts +22 -0
  95. package/dist/cjs/containerd/options/container/ContainerRemoveOptions.js +34 -0
  96. package/dist/cjs/containerd/options/container/ContainerResourceOptions.d.ts +63 -0
  97. package/dist/cjs/containerd/options/container/ContainerResourceOptions.js +67 -0
  98. package/dist/cjs/containerd/options/container/ContainerStopOptions.d.ts +30 -0
  99. package/dist/cjs/containerd/options/container/ContainerStopOptions.js +41 -0
  100. package/dist/cjs/containerd/options/container/ContainerTTYConsoleSizeOptions.d.ts +26 -0
  101. package/dist/cjs/containerd/options/container/ContainerTTYConsoleSizeOptions.js +40 -0
  102. package/dist/cjs/containerd/options/container/ContainerTTYOptions.d.ts +50 -0
  103. package/dist/cjs/containerd/options/container/ContainerTTYOptions.js +63 -0
  104. package/dist/cjs/containerd/options/image/ImageBuildOptions.d.ts +88 -0
  105. package/dist/cjs/containerd/options/image/ImageBuildOptions.js +95 -0
  106. package/dist/cjs/containerd/options/image/ImageExportOptions.d.ts +25 -0
  107. package/dist/cjs/containerd/options/image/ImageExportOptions.js +39 -0
  108. package/dist/cjs/containerd/options/image/ImageImportOptions.d.ts +38 -0
  109. package/dist/cjs/containerd/options/image/ImageImportOptions.js +47 -0
  110. package/dist/cjs/containerd/options/image/ImagePullOptions.d.ts +53 -0
  111. package/dist/cjs/containerd/options/image/ImagePullOptions.js +66 -0
  112. package/dist/cjs/containerd/options/image/ImagePushOptions.d.ts +44 -0
  113. package/dist/cjs/containerd/options/image/ImagePushOptions.js +58 -0
  114. package/dist/cjs/containerd/options/network/NetworkCreateOptions.d.ts +82 -0
  115. package/dist/cjs/containerd/options/network/NetworkCreateOptions.js +83 -0
  116. package/dist/cjs/containerd/options/volume/VolumeCreateOptions.d.ts +26 -0
  117. package/dist/cjs/containerd/options/volume/VolumeCreateOptions.js +40 -0
  118. package/dist/cjs/containerd/types/ContainerdBind.d.ts +28 -0
  119. package/dist/cjs/containerd/types/ContainerdBind.js +2 -0
  120. package/dist/cjs/containerd/types/ContainerdBuildOutputCallback.d.ts +6 -0
  121. package/dist/cjs/containerd/types/ContainerdBuildOutputCallback.js +2 -0
  122. package/dist/cjs/containerd/types/ContainerdContainerNetwork.d.ts +40 -0
  123. package/dist/cjs/containerd/types/ContainerdContainerNetwork.js +2 -0
  124. package/dist/cjs/containerd/types/ContainerdContainerPort.d.ts +22 -0
  125. package/dist/cjs/containerd/types/ContainerdContainerPort.js +2 -0
  126. package/dist/cjs/containerd/types/ContainerdContainerState.d.ts +42 -0
  127. package/dist/cjs/containerd/types/ContainerdContainerState.js +2 -0
  128. package/dist/cjs/containerd/types/ContainerdContainerStats.d.ts +107 -0
  129. package/dist/cjs/containerd/types/ContainerdContainerStats.js +2 -0
  130. package/dist/cjs/containerd/types/ContainerdDevice.d.ts +25 -0
  131. package/dist/cjs/containerd/types/ContainerdDevice.js +2 -0
  132. package/dist/cjs/containerd/types/ContainerdExecResult.d.ts +18 -0
  133. package/dist/cjs/containerd/types/ContainerdExecResult.js +2 -0
  134. package/dist/cjs/containerd/types/ContainerdImageConfig.d.ts +46 -0
  135. package/dist/cjs/containerd/types/ContainerdImageConfig.js +2 -0
  136. package/dist/cjs/containerd/types/ContainerdNetworkInfo.d.ts +49 -0
  137. package/dist/cjs/containerd/types/ContainerdNetworkInfo.js +2 -0
  138. package/dist/cjs/containerd/types/ContainerdProgressCallback.d.ts +29 -0
  139. package/dist/cjs/containerd/types/ContainerdProgressCallback.js +2 -0
  140. package/dist/cjs/containerd/types/ContainerdPruneResult.d.ts +21 -0
  141. package/dist/cjs/containerd/types/ContainerdPruneResult.js +2 -0
  142. package/dist/cjs/containerd/types/ContainerdRestartPolicy.d.ts +13 -0
  143. package/dist/cjs/containerd/types/ContainerdRestartPolicy.js +2 -0
  144. package/dist/cjs/containerd/types/ContainerdTmpfs.d.ts +20 -0
  145. package/dist/cjs/containerd/types/ContainerdTmpfs.js +2 -0
  146. package/dist/cjs/containerd/types/ContainerdVolume.d.ts +19 -0
  147. package/dist/cjs/containerd/types/ContainerdVolume.js +2 -0
  148. package/dist/cjs/containerd/types/ContainerdVolumeInfo.d.ts +26 -0
  149. package/dist/cjs/containerd/types/ContainerdVolumeInfo.js +2 -0
  150. package/dist/cjs/exports/Containerd.d.ts +69 -0
  151. package/dist/cjs/exports/Containerd.js +87 -0
  152. package/dist/cjs/package.json +1 -0
  153. package/dist/esm/client/BuildKit.js +488 -0
  154. package/dist/esm/client/BuildKitMessages.js +120 -0
  155. package/dist/esm/client/ContainerStore.js +1339 -0
  156. package/dist/esm/client/ContainerdClient.js +416 -0
  157. package/dist/esm/client/DockerIgnore.js +179 -0
  158. package/dist/esm/client/Fifo.js +59 -0
  159. package/dist/esm/client/ImageStore.js +628 -0
  160. package/dist/esm/client/Messages.js +393 -0
  161. package/dist/esm/client/Networks.js +621 -0
  162. package/dist/esm/client/Platforms.js +156 -0
  163. package/dist/esm/client/Reference.js +66 -0
  164. package/dist/esm/client/Registry.js +263 -0
  165. package/dist/esm/client/Rootfs.js +234 -0
  166. package/dist/esm/client/Seccomp.js +152 -0
  167. package/dist/esm/client/Spec.js +220 -0
  168. package/dist/esm/client/Volumes.js +73 -0
  169. package/dist/esm/containerd/Containerd.js +923 -0
  170. package/dist/esm/containerd/exceptions/ContainerdConnectionException.js +12 -0
  171. package/dist/esm/containerd/exceptions/ContainerdContainerNameConflictException.js +11 -0
  172. package/dist/esm/containerd/exceptions/ContainerdContainerNotFoundException.js +12 -0
  173. package/dist/esm/containerd/exceptions/ContainerdContainerStateException.js +13 -0
  174. package/dist/esm/containerd/exceptions/ContainerdImageBuildException.js +12 -0
  175. package/dist/esm/containerd/exceptions/ContainerdImageExportException.js +12 -0
  176. package/dist/esm/containerd/exceptions/ContainerdImageImportException.js +12 -0
  177. package/dist/esm/containerd/exceptions/ContainerdImageNotFoundException.js +12 -0
  178. package/dist/esm/containerd/exceptions/ContainerdImagePullException.js +12 -0
  179. package/dist/esm/containerd/exceptions/ContainerdImagePushException.js +11 -0
  180. package/dist/esm/containerd/exceptions/ContainerdNetworkConflictException.js +12 -0
  181. package/dist/esm/containerd/exceptions/ContainerdNetworkNotFoundException.js +12 -0
  182. package/dist/esm/containerd/exceptions/ContainerdPathNotFoundException.js +11 -0
  183. package/dist/esm/containerd/exceptions/ContainerdPlatformException.js +12 -0
  184. package/dist/esm/containerd/exceptions/ContainerdVolumeInUseException.js +11 -0
  185. package/dist/esm/containerd/exceptions/ContainerdVolumeNotFoundException.js +11 -0
  186. package/dist/esm/containerd/lib/ContainerdContainer.js +533 -0
  187. package/dist/esm/containerd/lib/ContainerdContainerTTY.js +175 -0
  188. package/dist/esm/containerd/lib/ContainerdErrors.js +34 -0
  189. package/dist/esm/containerd/lib/ContainerdImage.js +219 -0
  190. package/dist/esm/containerd/options/ContainerdPruneOptions.js +47 -0
  191. package/dist/esm/containerd/options/ContainerdRegistryAuthOptions.js +41 -0
  192. package/dist/esm/containerd/options/container/ContainerCommitOptions.js +62 -0
  193. package/dist/esm/containerd/options/container/ContainerCreateOptions.js +235 -0
  194. package/dist/esm/containerd/options/container/ContainerExecOptions.js +59 -0
  195. package/dist/esm/containerd/options/container/ContainerExportDirectoryOptions.js +41 -0
  196. package/dist/esm/containerd/options/container/ContainerKillOptions.js +37 -0
  197. package/dist/esm/containerd/options/container/ContainerLogsOptions.js +40 -0
  198. package/dist/esm/containerd/options/container/ContainerRemoveOptions.js +30 -0
  199. package/dist/esm/containerd/options/container/ContainerResourceOptions.js +63 -0
  200. package/dist/esm/containerd/options/container/ContainerStopOptions.js +37 -0
  201. package/dist/esm/containerd/options/container/ContainerTTYConsoleSizeOptions.js +36 -0
  202. package/dist/esm/containerd/options/container/ContainerTTYOptions.js +59 -0
  203. package/dist/esm/containerd/options/image/ImageBuildOptions.js +91 -0
  204. package/dist/esm/containerd/options/image/ImageExportOptions.js +35 -0
  205. package/dist/esm/containerd/options/image/ImageImportOptions.js +43 -0
  206. package/dist/esm/containerd/options/image/ImagePullOptions.js +62 -0
  207. package/dist/esm/containerd/options/image/ImagePushOptions.js +54 -0
  208. package/dist/esm/containerd/options/network/NetworkCreateOptions.js +79 -0
  209. package/dist/esm/containerd/options/volume/VolumeCreateOptions.js +36 -0
  210. package/dist/esm/containerd/types/ContainerdBind.js +1 -0
  211. package/dist/esm/containerd/types/ContainerdBuildOutputCallback.js +1 -0
  212. package/dist/esm/containerd/types/ContainerdContainerNetwork.js +1 -0
  213. package/dist/esm/containerd/types/ContainerdContainerPort.js +1 -0
  214. package/dist/esm/containerd/types/ContainerdContainerState.js +1 -0
  215. package/dist/esm/containerd/types/ContainerdContainerStats.js +1 -0
  216. package/dist/esm/containerd/types/ContainerdDevice.js +1 -0
  217. package/dist/esm/containerd/types/ContainerdExecResult.js +1 -0
  218. package/dist/esm/containerd/types/ContainerdImageConfig.js +1 -0
  219. package/dist/esm/containerd/types/ContainerdNetworkInfo.js +1 -0
  220. package/dist/esm/containerd/types/ContainerdProgressCallback.js +1 -0
  221. package/dist/esm/containerd/types/ContainerdPruneResult.js +1 -0
  222. package/dist/esm/containerd/types/ContainerdRestartPolicy.js +1 -0
  223. package/dist/esm/containerd/types/ContainerdTmpfs.js +1 -0
  224. package/dist/esm/containerd/types/ContainerdVolume.js +1 -0
  225. package/dist/esm/containerd/types/ContainerdVolumeInfo.js +1 -0
  226. package/dist/esm/exports/Containerd.js +68 -0
  227. package/dist/types/client/BuildKit.d.ts +176 -0
  228. package/dist/types/client/BuildKitMessages.d.ts +35 -0
  229. package/dist/types/client/ContainerStore.d.ts +558 -0
  230. package/dist/types/client/ContainerdClient.d.ts +244 -0
  231. package/dist/types/client/DockerIgnore.d.ts +44 -0
  232. package/dist/types/client/Fifo.d.ts +31 -0
  233. package/dist/types/client/ImageStore.d.ts +258 -0
  234. package/dist/types/client/Messages.d.ts +103 -0
  235. package/dist/types/client/Networks.d.ts +221 -0
  236. package/dist/types/client/Platforms.d.ts +53 -0
  237. package/dist/types/client/Reference.d.ts +33 -0
  238. package/dist/types/client/Registry.d.ts +145 -0
  239. package/dist/types/client/Rootfs.d.ts +83 -0
  240. package/dist/types/client/Seccomp.d.ts +36 -0
  241. package/dist/types/client/Spec.d.ts +151 -0
  242. package/dist/types/client/Volumes.d.ts +42 -0
  243. package/dist/types/containerd/Containerd.d.ts +442 -0
  244. package/dist/types/containerd/exceptions/ContainerdConnectionException.d.ts +9 -0
  245. package/dist/types/containerd/exceptions/ContainerdContainerNameConflictException.d.ts +8 -0
  246. package/dist/types/containerd/exceptions/ContainerdContainerNotFoundException.d.ts +9 -0
  247. package/dist/types/containerd/exceptions/ContainerdContainerStateException.d.ts +10 -0
  248. package/dist/types/containerd/exceptions/ContainerdImageBuildException.d.ts +9 -0
  249. package/dist/types/containerd/exceptions/ContainerdImageExportException.d.ts +9 -0
  250. package/dist/types/containerd/exceptions/ContainerdImageImportException.d.ts +9 -0
  251. package/dist/types/containerd/exceptions/ContainerdImageNotFoundException.d.ts +9 -0
  252. package/dist/types/containerd/exceptions/ContainerdImagePullException.d.ts +9 -0
  253. package/dist/types/containerd/exceptions/ContainerdImagePushException.d.ts +8 -0
  254. package/dist/types/containerd/exceptions/ContainerdNetworkConflictException.d.ts +9 -0
  255. package/dist/types/containerd/exceptions/ContainerdNetworkNotFoundException.d.ts +9 -0
  256. package/dist/types/containerd/exceptions/ContainerdPathNotFoundException.d.ts +8 -0
  257. package/dist/types/containerd/exceptions/ContainerdPlatformException.d.ts +9 -0
  258. package/dist/types/containerd/exceptions/ContainerdVolumeInUseException.d.ts +8 -0
  259. package/dist/types/containerd/exceptions/ContainerdVolumeNotFoundException.d.ts +8 -0
  260. package/dist/types/containerd/lib/ContainerdContainer.d.ts +292 -0
  261. package/dist/types/containerd/lib/ContainerdContainerTTY.d.ts +116 -0
  262. package/dist/types/containerd/lib/ContainerdErrors.d.ts +6 -0
  263. package/dist/types/containerd/lib/ContainerdImage.d.ts +149 -0
  264. package/dist/types/containerd/options/ContainerdPruneOptions.d.ts +44 -0
  265. package/dist/types/containerd/options/ContainerdRegistryAuthOptions.d.ts +32 -0
  266. package/dist/types/containerd/options/container/ContainerCommitOptions.d.ts +57 -0
  267. package/dist/types/containerd/options/container/ContainerCreateOptions.d.ts +273 -0
  268. package/dist/types/containerd/options/container/ContainerExecOptions.d.ts +53 -0
  269. package/dist/types/containerd/options/container/ContainerExportDirectoryOptions.d.ts +32 -0
  270. package/dist/types/containerd/options/container/ContainerKillOptions.d.ts +30 -0
  271. package/dist/types/containerd/options/container/ContainerLogsOptions.d.ts +34 -0
  272. package/dist/types/containerd/options/container/ContainerRemoveOptions.d.ts +22 -0
  273. package/dist/types/containerd/options/container/ContainerResourceOptions.d.ts +63 -0
  274. package/dist/types/containerd/options/container/ContainerStopOptions.d.ts +30 -0
  275. package/dist/types/containerd/options/container/ContainerTTYConsoleSizeOptions.d.ts +26 -0
  276. package/dist/types/containerd/options/container/ContainerTTYOptions.d.ts +50 -0
  277. package/dist/types/containerd/options/image/ImageBuildOptions.d.ts +88 -0
  278. package/dist/types/containerd/options/image/ImageExportOptions.d.ts +25 -0
  279. package/dist/types/containerd/options/image/ImageImportOptions.d.ts +38 -0
  280. package/dist/types/containerd/options/image/ImagePullOptions.d.ts +53 -0
  281. package/dist/types/containerd/options/image/ImagePushOptions.d.ts +44 -0
  282. package/dist/types/containerd/options/network/NetworkCreateOptions.d.ts +82 -0
  283. package/dist/types/containerd/options/volume/VolumeCreateOptions.d.ts +26 -0
  284. package/dist/types/containerd/types/ContainerdBind.d.ts +28 -0
  285. package/dist/types/containerd/types/ContainerdBuildOutputCallback.d.ts +6 -0
  286. package/dist/types/containerd/types/ContainerdContainerNetwork.d.ts +40 -0
  287. package/dist/types/containerd/types/ContainerdContainerPort.d.ts +22 -0
  288. package/dist/types/containerd/types/ContainerdContainerState.d.ts +42 -0
  289. package/dist/types/containerd/types/ContainerdContainerStats.d.ts +107 -0
  290. package/dist/types/containerd/types/ContainerdDevice.d.ts +25 -0
  291. package/dist/types/containerd/types/ContainerdExecResult.d.ts +18 -0
  292. package/dist/types/containerd/types/ContainerdImageConfig.d.ts +46 -0
  293. package/dist/types/containerd/types/ContainerdNetworkInfo.d.ts +49 -0
  294. package/dist/types/containerd/types/ContainerdProgressCallback.d.ts +29 -0
  295. package/dist/types/containerd/types/ContainerdPruneResult.d.ts +21 -0
  296. package/dist/types/containerd/types/ContainerdRestartPolicy.d.ts +13 -0
  297. package/dist/types/containerd/types/ContainerdTmpfs.d.ts +20 -0
  298. package/dist/types/containerd/types/ContainerdVolume.d.ts +19 -0
  299. package/dist/types/containerd/types/ContainerdVolumeInfo.d.ts +26 -0
  300. package/dist/types/exports/Containerd.d.ts +69 -0
  301. package/package.json +51 -4
@@ -0,0 +1,628 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { createReadStream, createWriteStream } from 'node:fs';
3
+ import { mkdir, mkdtemp, readFile, rm, stat } from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { pipeline } from 'node:stream/promises';
7
+ import { extract as tarExtract, pack as tarPack } from 'tar-stream';
8
+ import { isGRPCError } from './ContainerdClient.js';
9
+ import { GRPCStatus } from '@lakutata/grpc';
10
+ import { formatPlatform, hostPlatform, matchPlatform, normalizePlatform, platformRank } from './Platforms.js';
11
+ import { imageName, parseReference } from './Reference.js';
12
+ import { digestOf, isIndex, isManifest, MediaTypes, RegistryClient } from './Registry.js';
13
+ /**
14
+ * The labels of containerd binding its content (its garbage collection keeps what an image references)
15
+ */
16
+ const Labels = {
17
+ contentRef: (kind, index) => `containerd.io/gc.ref.content.${kind}${index === undefined ? '' : `.${index}`}`,
18
+ snapshotRef: (snapshotter) => `containerd.io/gc.ref.snapshot.${snapshotter}`,
19
+ uncompressed: 'containerd.io/uncompressed',
20
+ source: (registry) => `containerd.io/distribution.source.${registry}`
21
+ };
22
+ /**
23
+ * The bytes of a stream, whole
24
+ * @param chunks
25
+ */
26
+ async function collect(chunks) {
27
+ const all = [];
28
+ for await (const chunk of chunks)
29
+ all.push(Buffer.from(chunk));
30
+ return Buffer.concat(all);
31
+ }
32
+ /**
33
+ * The identifiers of the chain of layers (OCI): the ones of the snapshots of their unpacking
34
+ * @param diffIds
35
+ */
36
+ export function chainIds(diffIds) {
37
+ const chain = [];
38
+ for (const diffId of diffIds) {
39
+ chain.push(chain.length ? `sha256:${createHash('sha256').update(`${chain[chain.length - 1]} ${diffId}`).digest('hex')}` : diffId);
40
+ }
41
+ return chain;
42
+ }
43
+ /**
44
+ * The platform of the configuration of an image
45
+ * @param config
46
+ */
47
+ function configPlatform(config) {
48
+ return normalizePlatform({ os: config.os, architecture: config.architecture, variant: config.variant });
49
+ }
50
+ /**
51
+ * The images of containerd: pulled from the registries, unpacked into the snapshots, pushed, imported and exported
52
+ * (OCI image layouts, the archives of docker save), as ctr and nerdctl do: their content bound by the labels of the
53
+ * garbage collection of containerd, under a lease until the image references it
54
+ */
55
+ export class ImageStore {
56
+ /**
57
+ * @param client
58
+ * @param snapshotter
59
+ * @param temporary the directory of the archives extracted (a disk of the machine, not a small tmpfs)
60
+ * @param runnablePlatforms the platforms the machine runs, unpacked by the pulls and the imports (the one of the
61
+ * machine by default)
62
+ */
63
+ constructor(client, snapshotter, temporary = os.tmpdir(), runnablePlatforms = () => [hostPlatform()]) {
64
+ this.client = client;
65
+ this.snapshotter = snapshotter;
66
+ this.temporary = temporary;
67
+ this.runnablePlatforms = runnablePlatforms;
68
+ }
69
+ /**
70
+ * The JSON of a content
71
+ * @param digest
72
+ */
73
+ async readJson(digest) {
74
+ return JSON.parse((await this.client.readAll(digest)).toString('utf8'));
75
+ }
76
+ /**
77
+ * The best manifest of an index for a platform, among the ones the content store has (or all)
78
+ * @param index
79
+ * @param platform
80
+ * @param local
81
+ */
82
+ async chooseManifest(index, platform, local) {
83
+ let best;
84
+ for (const descriptor of index.manifests) {
85
+ if (!isManifest(descriptor.mediaType) || !descriptor.platform)
86
+ continue;
87
+ const rank = platformRank(descriptor.platform, platform);
88
+ if (rank === undefined || (best && best.rank <= rank))
89
+ continue;
90
+ if (local && !(await this.client.contentInfo(descriptor.digest)))
91
+ continue;
92
+ best = { descriptor: descriptor, rank: rank };
93
+ }
94
+ return best?.descriptor;
95
+ }
96
+ /**
97
+ * The image of a name (the reference given or its normalized name), undefined when it does not exist
98
+ * @param name
99
+ */
100
+ async get(name) {
101
+ return await this.client.getImage(imageName(name)) ?? (imageName(name) === name ? undefined : await this.client.getImage(name));
102
+ }
103
+ /**
104
+ * Resolve an image for a platform: its manifest and its configuration (the manifest of the platform of its index)
105
+ * @param name
106
+ * @param platform the one of the machine by default
107
+ */
108
+ async resolve(name, platform = hostPlatform()) {
109
+ const image = await this.get(name);
110
+ if (!image)
111
+ throw Object.assign(new Error(`The image ${name} does not exist`), { code: 'NOT_FOUND' });
112
+ const target = image.target;
113
+ let manifestDescriptor = target;
114
+ if (isIndex(target.mediaType)) {
115
+ const chosen = await this.chooseManifest(await this.readJson(target.digest), platform, true);
116
+ if (!chosen)
117
+ throw Object.assign(new Error(`The image ${name} has no manifest of the platform ${formatPlatform(platform)}`), { code: 'PLATFORM' });
118
+ manifestDescriptor = chosen;
119
+ }
120
+ const manifest = await this.readJson(manifestDescriptor.digest);
121
+ const config = await this.readJson(manifest.config.digest);
122
+ return { image: image, name: image.name, target: target, manifestDescriptor: manifestDescriptor, manifest: manifest, config: config, platform: configPlatform(config) };
123
+ }
124
+ /**
125
+ * The platforms of an image the content store has (the ones pulled)
126
+ * @param name
127
+ */
128
+ async platforms(name) {
129
+ const image = await this.get(name);
130
+ if (!image)
131
+ return [];
132
+ if (!isIndex(image.target.mediaType))
133
+ return [configPlatform(await this.readJson((await this.readJson(image.target.digest)).config.digest))];
134
+ const platforms = [];
135
+ for (const descriptor of (await this.readJson(image.target.digest)).manifests) {
136
+ if (descriptor.platform && isManifest(descriptor.mediaType) && await this.client.contentInfo(descriptor.digest))
137
+ platforms.push(normalizePlatform(descriptor.platform));
138
+ }
139
+ return platforms;
140
+ }
141
+ /**
142
+ * Unpack the layers of an image into the snapshots of the snapshotter (named by the chain of their identifiers), the
143
+ * configuration bound to the last one
144
+ * @param manifest
145
+ * @param lease
146
+ */
147
+ async unpack(manifest, lease) {
148
+ const config = await this.readJson(manifest.config.digest);
149
+ const diffIds = config.rootfs?.diff_ids ?? [];
150
+ if (diffIds.length !== manifest.layers.length)
151
+ throw new Error(`The image ${manifest.config.digest} has ${manifest.layers.length} layers and ${diffIds.length} identifiers of them`);
152
+ const chain = chainIds(diffIds);
153
+ for (let index = 0; index < chain.length; index++) {
154
+ if (await this.client.statSnapshot(this.snapshotter, chain[index]))
155
+ continue;
156
+ const key = `extract-${randomBytes(6).toString('hex')}-${chain[index]}`;
157
+ const mounts = await this.client.prepareSnapshot(this.snapshotter, key, index ? chain[index - 1] : '', {}, lease);
158
+ try {
159
+ const applied = await this.client.applyLayer(manifest.layers[index], mounts, lease);
160
+ if (applied.digest !== diffIds[index])
161
+ throw new Error(`The layer ${manifest.layers[index].digest} unpacked is ${applied.digest}, not ${diffIds[index]}`);
162
+ await this.client.commitSnapshot(this.snapshotter, chain[index], key, {}, lease);
163
+ }
164
+ catch (error) {
165
+ await this.client.removeSnapshot(this.snapshotter, key);
166
+ //Unpacked meanwhile
167
+ if (isGRPCError(error, GRPCStatus.ALREADY_EXISTS))
168
+ continue;
169
+ throw error;
170
+ }
171
+ }
172
+ if (chain.length)
173
+ await this.client.labelContent(manifest.config.digest, { [Labels.snapshotRef(this.snapshotter)]: chain[chain.length - 1] });
174
+ return chain[chain.length - 1] ?? '';
175
+ }
176
+ /**
177
+ * Write a manifest, its configuration and its layers (the blobs given by a source), bound by the labels of the
178
+ * garbage collection
179
+ * @param manifest
180
+ * @param blob the bytes of a blob (its stream)
181
+ * @param lease
182
+ * @param labels the labels of all the content (its source)
183
+ * @param progress
184
+ */
185
+ async writeImage(manifest, blob, lease, labels, progress) {
186
+ const configData = await blob(manifest.config);
187
+ const configBytes = configData instanceof Uint8Array ? Buffer.from(configData) : await collect(configData);
188
+ await this.client.writeContent(manifest.config, configBytes, lease, labels);
189
+ const config = JSON.parse(configBytes.toString('utf8'));
190
+ for (let index = 0; index < manifest.layers.length; index++) {
191
+ const layer = manifest.layers[index];
192
+ const uncompressed = config.rootfs?.diff_ids?.[index] ? { [Labels.uncompressed]: config.rootfs.diff_ids[index] } : {};
193
+ if (await this.client.contentInfo(layer.digest)) {
194
+ await this.client.labelContent(layer.digest, { ...labels, ...uncompressed });
195
+ progress?.({ digest: layer.digest, mediaType: layer.mediaType, current: layer.size, total: layer.size });
196
+ continue;
197
+ }
198
+ const data = await blob(layer);
199
+ let current = 0;
200
+ const counted = async function* () {
201
+ for await (const chunk of data) {
202
+ current += chunk.length;
203
+ progress?.({ digest: layer.digest, mediaType: layer.mediaType, current: current, total: layer.size });
204
+ yield chunk;
205
+ }
206
+ };
207
+ await this.client.writeContent(layer, data instanceof Uint8Array ? data : counted(), lease, { ...labels, ...uncompressed });
208
+ }
209
+ }
210
+ /**
211
+ * The labels of a manifest binding its configuration and its layers
212
+ * @param manifest
213
+ */
214
+ manifestLabels(manifest) {
215
+ const labels = { [Labels.contentRef('config')]: manifest.config.digest };
216
+ manifest.layers.forEach((layer, index) => labels[Labels.contentRef('l', index)] = layer.digest);
217
+ return labels;
218
+ }
219
+ /**
220
+ * Pull an image from its registry: the manifests of the platforms asked (of its index), their configurations and
221
+ * their layers; the image named by its reference (docker.io/library/busybox:latest), unpacked for the machine
222
+ * @param reference
223
+ * @param options
224
+ */
225
+ async pull(reference, options = {}) {
226
+ const parsed = parseReference(reference);
227
+ const registry = new RegistryClient(parsed, options.registry);
228
+ const platforms = options.platforms ?? [hostPlatform()];
229
+ const source = { [Labels.source(parsed.registry)]: parsed.repository };
230
+ const lease = await this.client.createLease();
231
+ try {
232
+ const root = await registry.resolve(parsed.digest ?? parsed.tag);
233
+ const manifests = [];
234
+ if (isIndex(root.descriptor.mediaType)) {
235
+ const index = JSON.parse(root.data.toString('utf8'));
236
+ const chosen = new Set();
237
+ if (platforms === 'all') {
238
+ index.manifests.filter((descriptor) => isManifest(descriptor.mediaType) && descriptor.platform?.os !== 'unknown').forEach((descriptor) => chosen.add(descriptor));
239
+ }
240
+ else {
241
+ for (const platform of platforms) {
242
+ const descriptor = await this.chooseManifest(index, platform, false);
243
+ if (!descriptor) {
244
+ const available = index.manifests.filter((item) => !!item.platform && item.platform.os !== 'unknown').map((item) => formatPlatform(normalizePlatform(item.platform))).join(', ');
245
+ throw Object.assign(new Error(`The image ${parsed.name} has no manifest of the platform ${formatPlatform(platform)} (it has ${available})`), { code: 'PLATFORM' });
246
+ }
247
+ chosen.add(descriptor);
248
+ }
249
+ }
250
+ for (const descriptor of chosen)
251
+ manifests.push({ descriptor: descriptor, data: await registry.fetchManifest(descriptor), index: index.manifests.indexOf(descriptor) });
252
+ }
253
+ else {
254
+ manifests.push(root);
255
+ }
256
+ for (const { descriptor, data } of manifests) {
257
+ const manifest = JSON.parse(data.toString('utf8'));
258
+ await this.writeImage(manifest, (blob) => registry.fetchBlob(blob), lease, source, options.progress);
259
+ await this.client.writeContent(descriptor, data, lease, { ...source, ...this.manifestLabels(manifest) });
260
+ }
261
+ if (isIndex(root.descriptor.mediaType)) {
262
+ const labels = { ...source };
263
+ manifests.forEach(({ descriptor, index }) => labels[Labels.contentRef('m', index)] = descriptor.digest);
264
+ await this.client.writeContent(root.descriptor, root.data, lease, labels);
265
+ }
266
+ await this.client.putImage({ name: parsed.name, target: root.descriptor }, lease);
267
+ if (options.unpack ?? true)
268
+ await this.unpackFor(parsed.name, lease);
269
+ return parsed.name;
270
+ }
271
+ finally {
272
+ await this.client.deleteLease(lease);
273
+ }
274
+ }
275
+ /**
276
+ * Unpack an image for the platforms the machine runs, among the ones the content store has (its manifests pulled):
277
+ * not the other platforms, nor the attestations (unknown/unknown)
278
+ * @param name
279
+ * @param lease
280
+ */
281
+ async unpackFor(name, lease) {
282
+ const image = await this.get(name);
283
+ if (!image)
284
+ return;
285
+ const manifests = isIndex(image.target.mediaType)
286
+ ? (await this.readJson(image.target.digest)).manifests.filter((descriptor) => isManifest(descriptor.mediaType))
287
+ : [image.target];
288
+ const runnable = this.runnablePlatforms();
289
+ for (const descriptor of manifests) {
290
+ if (!(await this.client.contentInfo(descriptor.digest)))
291
+ continue;
292
+ const manifest = await this.readJson(descriptor.digest);
293
+ const platform = descriptor.platform ? normalizePlatform(descriptor.platform) : configPlatform(await this.readJson(manifest.config.digest));
294
+ if (!runnable.some((item) => matchPlatform(platform, item)))
295
+ continue;
296
+ await this.unpack(manifest, lease);
297
+ }
298
+ }
299
+ /**
300
+ * Push an image to a registry (as another reference): the manifest of the platform asked; without it, the manifests
301
+ * of all the platforms and the index when the content store has all of them, the manifest of the machine's platform
302
+ * otherwise
303
+ * @param name
304
+ * @param options
305
+ */
306
+ async push(name, options = {}) {
307
+ const image = await this.get(name);
308
+ if (!image)
309
+ throw Object.assign(new Error(`The image ${name} does not exist`), { code: 'NOT_FOUND' });
310
+ const parsed = parseReference(options.reference ?? image.name);
311
+ const registry = new RegistryClient(parsed, options.registry);
312
+ const tag = parsed.tag ?? parsed.digest;
313
+ const pushManifest = async (descriptor, reference) => {
314
+ const data = await this.client.readAll(descriptor.digest);
315
+ const manifest = JSON.parse(data.toString('utf8'));
316
+ for (const blob of [manifest.config, ...manifest.layers]) {
317
+ await registry.pushBlob(blob, () => this.client.readContent(blob.digest));
318
+ options.progress?.({ digest: blob.digest, mediaType: blob.mediaType, current: blob.size, total: blob.size });
319
+ }
320
+ await registry.pushManifest(reference, descriptor.mediaType, data);
321
+ };
322
+ const target = image.target;
323
+ if (!isIndex(target.mediaType)) {
324
+ if (options.platform) {
325
+ const platform = configPlatform(await this.readJson((await this.readJson(target.digest)).config.digest));
326
+ if (!matchPlatform(platform, options.platform))
327
+ throw Object.assign(new Error(`The image ${name} has no manifest of the platform ${formatPlatform(options.platform)} to push (it is ${formatPlatform(platform)})`), { code: 'PLATFORM' });
328
+ }
329
+ return await pushManifest(target, tag);
330
+ }
331
+ const index = await this.readJson(target.digest);
332
+ const local = [];
333
+ for (const descriptor of index.manifests)
334
+ if (await this.client.contentInfo(descriptor.digest))
335
+ local.push(descriptor);
336
+ if (!options.platform && local.length === index.manifests.length) {
337
+ for (const descriptor of local)
338
+ await pushManifest(descriptor, descriptor.digest);
339
+ return await registry.pushManifest(tag, target.mediaType, await this.client.readAll(target.digest));
340
+ }
341
+ const chosen = await this.chooseManifest(index, options.platform ?? hostPlatform(), true);
342
+ if (!chosen)
343
+ throw Object.assign(new Error(`The image ${name} has no manifest of the platform ${formatPlatform(options.platform ?? hostPlatform())} to push`), { code: 'PLATFORM' });
344
+ await pushManifest(chosen, tag);
345
+ }
346
+ /**
347
+ * Commit the changes of a snapshot (the one of a container) on its image: a layer of their diff, the configuration
348
+ * of the image with its changes, a manifest of the platform, the image named (and unpacked)
349
+ * @param options
350
+ */
351
+ async commit(options) {
352
+ const base = await this.resolve(options.image, options.platform);
353
+ const name = imageName(options.name);
354
+ const lease = await this.client.createLease();
355
+ const view = `commit-${randomBytes(6).toString('hex')}`;
356
+ try {
357
+ const chain = chainIds(base.config.rootfs?.diff_ids ?? []);
358
+ const left = chain.length ? await this.client.viewSnapshot(this.snapshotter, view, chain[chain.length - 1], lease) : [];
359
+ const right = await this.client.snapshotMounts(this.snapshotter, options.snapshotKey);
360
+ const layer = await this.client.diff(left, right, lease);
361
+ const diffId = (await this.client.contentInfo(layer.digest))?.labels?.[Labels.uncompressed];
362
+ if (!diffId)
363
+ throw new Error(`The layer ${layer.digest} of the commit has no uncompressed digest`);
364
+ const created = new Date().toISOString();
365
+ const changes = options.changes ?? {};
366
+ const config = {
367
+ ...structuredClone(base.config),
368
+ created: created,
369
+ rootfs: { type: 'layers', diff_ids: [...base.config.rootfs?.diff_ids ?? [], diffId] }
370
+ };
371
+ const containerConfig = config.config ??= {};
372
+ if (changes.cmd)
373
+ containerConfig.Cmd = changes.cmd;
374
+ if (changes.entrypoint)
375
+ containerConfig.Entrypoint = changes.entrypoint;
376
+ if (changes.env) {
377
+ const env = new Map((containerConfig.Env ?? []).map((entry) => [entry.split('=')[0], entry]));
378
+ for (const entry of changes.env)
379
+ env.set(entry.split('=')[0], entry);
380
+ containerConfig.Env = [...env.values()];
381
+ }
382
+ if (changes.workingDir !== undefined)
383
+ containerConfig.WorkingDir = changes.workingDir;
384
+ if (changes.user !== undefined)
385
+ containerConfig.User = changes.user;
386
+ if (changes.labels)
387
+ containerConfig.Labels = { ...containerConfig.Labels ?? {}, ...changes.labels };
388
+ if (changes.exposedPorts)
389
+ containerConfig.ExposedPorts = { ...containerConfig.ExposedPorts ?? {}, ...Object.fromEntries(changes.exposedPorts.map((port) => [port.includes('/') ? port : `${port}/tcp`, {}])) };
390
+ if (options.author)
391
+ config.author = options.author;
392
+ config.history = [...config.history ?? [], { created: created, created_by: 'lakutata commit', ...options.comment ? { comment: options.comment } : {}, ...options.author ? { author: options.author } : {} }];
393
+ const configData = Buffer.from(JSON.stringify(config));
394
+ const configDescriptor = { mediaType: MediaTypes.OCI_CONFIG, digest: digestOf(configData), size: configData.length };
395
+ await this.client.writeContent(configDescriptor, configData, lease);
396
+ const manifest = {
397
+ schemaVersion: 2,
398
+ mediaType: MediaTypes.OCI_MANIFEST,
399
+ config: configDescriptor,
400
+ layers: [...base.manifest.layers.map((item) => ({ mediaType: item.mediaType, digest: item.digest, size: item.size })), { mediaType: layer.mediaType, digest: layer.digest, size: Number(layer.size) }]
401
+ };
402
+ const manifestData = Buffer.from(JSON.stringify(manifest));
403
+ const manifestDescriptor = { mediaType: MediaTypes.OCI_MANIFEST, digest: digestOf(manifestData), size: manifestData.length };
404
+ await this.client.writeContent(manifestDescriptor, manifestData, lease, this.manifestLabels(manifest));
405
+ await this.client.putImage({ name: name, target: manifestDescriptor }, lease);
406
+ await this.unpack(manifest, lease);
407
+ return name;
408
+ }
409
+ finally {
410
+ await this.client.removeSnapshot(this.snapshotter, view);
411
+ await this.client.deleteLease(lease);
412
+ }
413
+ }
414
+ /**
415
+ * Name an image again (a tag), its target the same
416
+ * @param name
417
+ * @param reference
418
+ */
419
+ async tag(name, reference) {
420
+ const image = await this.get(name);
421
+ if (!image)
422
+ throw Object.assign(new Error(`The image ${name} does not exist`), { code: 'NOT_FOUND' });
423
+ const target = imageName(reference);
424
+ await this.client.putImage({ name: target, target: image.target, labels: image.labels });
425
+ return target;
426
+ }
427
+ /**
428
+ * Remove an image (its content and its snapshots are collected by containerd once nothing references them)
429
+ * @param name
430
+ */
431
+ async remove(name) {
432
+ const image = await this.get(name);
433
+ if (!image)
434
+ throw Object.assign(new Error(`The image ${name} does not exist`), { code: 'NOT_FOUND' });
435
+ await this.client.deleteImage(image.name, true);
436
+ }
437
+ /**
438
+ * Import an archive of images: an OCI image layout (nerdctl save, docker save of Docker 25+), or an archive of
439
+ * docker save; the images named by the archive (or by a name given, to an archive of one image), unpacked for the
440
+ * platforms the machine runs
441
+ * @param source a file, or its stream
442
+ * @param options
443
+ */
444
+ async import(source, options = {}) {
445
+ await mkdir(this.temporary, { recursive: true });
446
+ const directory = await mkdtemp(path.join(this.temporary, 'lakutata-containerd-import-'));
447
+ const lease = await this.client.createLease();
448
+ try {
449
+ await this.extract(typeof source === 'string' ? createReadStream(source) : source, directory);
450
+ const file = (name) => path.join(directory, ...name.split('/'));
451
+ const blobFile = (digest) => file(`blobs/${digest.replace(':', '/')}`);
452
+ const exists = async (name) => !!(await stat(name).catch(() => undefined));
453
+ const names = [];
454
+ const named = (name) => options.name ? imageName(options.name) : name ? imageName(name) : undefined;
455
+ const index = await exists(file('index.json')) ? JSON.parse(await readFile(file('index.json'), 'utf8')) : undefined;
456
+ const entries = await exists(file('manifest.json')) ? JSON.parse(await readFile(file('manifest.json'), 'utf8')) : [];
457
+ if (options.name) {
458
+ //One name for one image (its tags: its entries of the same digest), checked before any import
459
+ const images = new Set((index?.manifests ?? []).map((entry) => entry.digest)).size || new Set(entries.map((entry) => entry.Config)).size;
460
+ if (images > 1)
461
+ throw new Error(`The archive has ${images} images: the name ${options.name} can only be given to an archive of one image`);
462
+ }
463
+ if (index) {
464
+ const blob = async (descriptor) => createReadStream(blobFile(descriptor.digest));
465
+ for (const entry of index.manifests) {
466
+ const name = named(entry.annotations?.['io.containerd.image.name'] ?? entry.annotations?.['org.opencontainers.image.ref.name']);
467
+ await this.writeTree(entry, blob, lease);
468
+ if (!name)
469
+ continue;
470
+ await this.client.putImage({ name: name, target: { mediaType: entry.mediaType, digest: entry.digest, size: entry.size } }, lease);
471
+ if (!names.includes(name))
472
+ names.push(name);
473
+ }
474
+ }
475
+ if (!names.length && entries.length) {
476
+ //docker save: uncompressed layers (or compressed ones), the configuration, the tags
477
+ for (const entry of entries) {
478
+ const configData = await readFile(file(entry.Config));
479
+ const layers = [];
480
+ const layerFiles = new Map();
481
+ for (const layer of entry.Layers) {
482
+ const data = await readFile(file(layer));
483
+ const digest = digestOf(data);
484
+ const magic = data.subarray(0, 4).toString('hex');
485
+ const mediaType = magic.startsWith('1f8b') ? MediaTypes.DOCKER_LAYER_GZIP : magic === '28b52ffd' ? 'application/vnd.oci.image.layer.v1.tar+zstd' : MediaTypes.DOCKER_LAYER;
486
+ layers.push({ mediaType: mediaType, digest: digest, size: data.length });
487
+ layerFiles.set(digest, file(layer));
488
+ }
489
+ const manifest = { schemaVersion: 2, mediaType: MediaTypes.DOCKER_MANIFEST, config: { mediaType: MediaTypes.DOCKER_CONFIG, digest: digestOf(configData), size: configData.length }, layers: layers };
490
+ const manifestData = Buffer.from(JSON.stringify(manifest));
491
+ const descriptor = { mediaType: MediaTypes.DOCKER_MANIFEST, digest: digestOf(manifestData), size: manifestData.length };
492
+ await this.writeImage(manifest, async (blob) => blob.digest === manifest.config.digest ? configData : createReadStream(layerFiles.get(blob.digest)), lease, {});
493
+ await this.client.writeContent(descriptor, manifestData, lease, this.manifestLabels(manifest));
494
+ const tags = options.name ? [options.name] : entry.RepoTags?.length ? entry.RepoTags : [`import-${Date.now()}@${descriptor.digest}`];
495
+ for (const tag of tags) {
496
+ const name = imageName(tag);
497
+ await this.client.putImage({ name: name, target: descriptor }, lease);
498
+ names.push(name);
499
+ }
500
+ }
501
+ }
502
+ if (!names.length)
503
+ throw new Error('The archive has no image: an OCI image layout (index.json) or an archive of docker save (manifest.json)');
504
+ if (options.unpack ?? true)
505
+ for (const name of names)
506
+ await this.unpackFor(name, lease);
507
+ return names;
508
+ }
509
+ finally {
510
+ await this.client.deleteLease(lease);
511
+ await rm(directory, { recursive: true, force: true });
512
+ }
513
+ }
514
+ /**
515
+ * Write a manifest or an index of an archive, and what it references (the manifests the archive has)
516
+ * @param descriptor
517
+ * @param blob
518
+ * @param lease
519
+ */
520
+ async writeTree(descriptor, blob, lease) {
521
+ const data = await collect(await blob(descriptor));
522
+ if (isIndex(descriptor.mediaType)) {
523
+ const index = JSON.parse(data.toString('utf8'));
524
+ const labels = {};
525
+ for (let position = 0; position < index.manifests.length; position++) {
526
+ const child = index.manifests[position];
527
+ try {
528
+ await this.writeTree(child, blob, lease);
529
+ labels[Labels.contentRef('m', position)] = child.digest;
530
+ }
531
+ catch (error) {
532
+ //The archives of a platform have the index of all of them
533
+ if (error.code !== 'ENOENT')
534
+ throw error;
535
+ }
536
+ }
537
+ return await this.client.writeContent(descriptor, data, lease, labels);
538
+ }
539
+ const manifest = JSON.parse(data.toString('utf8'));
540
+ await this.writeImage(manifest, blob, lease, {});
541
+ await this.client.writeContent(descriptor, data, lease, this.manifestLabels(manifest));
542
+ }
543
+ /**
544
+ * Extract an archive into a directory
545
+ * @param source
546
+ * @param directory
547
+ */
548
+ async extract(source, directory) {
549
+ const extractor = tarExtract();
550
+ extractor.on('entry', (header, entry, next) => {
551
+ const stream = entry;
552
+ const target = path.resolve(directory, header.name);
553
+ if (header.type !== 'file' || !target.startsWith(directory + path.sep)) {
554
+ stream.on('end', () => next()).resume();
555
+ return;
556
+ }
557
+ mkdir(path.dirname(target), { recursive: true })
558
+ .then(() => pipeline(stream, createWriteStream(target)))
559
+ .then(() => next(), (error) => next(error));
560
+ });
561
+ await pipeline(source, extractor);
562
+ }
563
+ /**
564
+ * Export images into an archive: an OCI image layout (named by io.containerd.image.name), with the manifest.json of
565
+ * docker load (the manifest of the platform of the machine, or the first one)
566
+ * @param names
567
+ * @param destination a file, or its stream
568
+ */
569
+ async export(names, destination) {
570
+ const blobs = new Map();
571
+ const entries = [];
572
+ const dockerManifests = [];
573
+ const blobPath = (digest) => `blobs/${digest.replace(':', '/')}`;
574
+ for (const name of names) {
575
+ const image = await this.get(name);
576
+ if (!image)
577
+ throw Object.assign(new Error(`The image ${name} does not exist`), { code: 'NOT_FOUND' });
578
+ const target = { mediaType: image.target.mediaType, digest: image.target.digest, size: Number(image.target.size) };
579
+ const reference = (() => {
580
+ try {
581
+ return parseReference(image.name);
582
+ }
583
+ catch {
584
+ return undefined;
585
+ }
586
+ })();
587
+ entries.push({ ...target, annotations: { 'io.containerd.image.name': image.name, ...reference?.tag ? { 'org.opencontainers.image.ref.name': reference.tag } : {} } });
588
+ blobs.set(target.digest, target);
589
+ const manifests = isIndex(target.mediaType) ? (await this.readJson(target.digest)).manifests : [target];
590
+ let first;
591
+ for (const descriptor of manifests) {
592
+ if (!isManifest(descriptor.mediaType) || !(await this.client.contentInfo(descriptor.digest)))
593
+ continue;
594
+ const manifest = await this.readJson(descriptor.digest);
595
+ blobs.set(descriptor.digest, descriptor);
596
+ for (const blob of [manifest.config, ...manifest.layers])
597
+ blobs.set(blob.digest, blob);
598
+ const config = await this.readJson(manifest.config.digest);
599
+ if (!first || platformRank(configPlatform(config), hostPlatform()) !== undefined)
600
+ first = manifest;
601
+ }
602
+ if (first && reference) {
603
+ const short = reference.registry === 'docker.io' ? reference.repository.replace(/^library\//, '') : `${reference.registry}/${reference.repository}`;
604
+ dockerManifests.push({ Config: blobPath(first.config.digest), RepoTags: reference.tag ? [`${short}:${reference.tag}`] : [], Layers: first.layers.map((layer) => blobPath(layer.digest)) });
605
+ }
606
+ }
607
+ const archive = tarPack();
608
+ const output = pipeline(archive, typeof destination === 'string' ? createWriteStream(destination) : destination);
609
+ const entry = (name, data) => new Promise((resolve, reject) => void archive.entry({ name: name, size: data.length, mode: 0o644 }, data, (error) => error ? reject(error) : resolve()));
610
+ try {
611
+ await entry('oci-layout', Buffer.from(JSON.stringify({ imageLayoutVersion: '1.0.0' })));
612
+ for (const blob of blobs.values()) {
613
+ const size = Number((await this.client.contentInfo(blob.digest))?.size ?? blob.size);
614
+ await new Promise((resolve, reject) => {
615
+ const writer = archive.entry({ name: blobPath(blob.digest), size: size, mode: 0o644 }, (error) => error ? reject(error) : resolve());
616
+ pipeline(this.client.readContent(blob.digest), writer).catch(reject);
617
+ });
618
+ }
619
+ await entry('index.json', Buffer.from(JSON.stringify({ schemaVersion: 2, mediaType: MediaTypes.OCI_INDEX, manifests: entries })));
620
+ await entry('manifest.json', Buffer.from(JSON.stringify(dockerManifests)));
621
+ archive.finalize();
622
+ }
623
+ catch (error) {
624
+ archive.destroy(error);
625
+ }
626
+ await output;
627
+ }
628
+ }