@smthrs/artifacts 0.0.0-stage → 1.0.0-rc.12

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 (171) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/LICENSE +21 -0
  3. package/README.md +175 -2
  4. package/dist/cjs/ArtifactBackupLease.d.ts +34 -0
  5. package/dist/cjs/ArtifactBackupLease.d.ts.map +1 -0
  6. package/dist/cjs/ArtifactBackupLease.js +183 -0
  7. package/dist/cjs/ArtifactBackupLease.js.map +7 -0
  8. package/dist/cjs/ArtifactStore.d.ts +129 -0
  9. package/dist/cjs/ArtifactStore.d.ts.map +1 -0
  10. package/dist/cjs/ArtifactStore.js +73 -0
  11. package/dist/cjs/ArtifactStore.js.map +7 -0
  12. package/dist/cjs/ArtifactStoreError.d.ts +82 -0
  13. package/dist/cjs/ArtifactStoreError.d.ts.map +1 -0
  14. package/dist/cjs/ArtifactStoreError.js +72 -0
  15. package/dist/cjs/ArtifactStoreError.js.map +7 -0
  16. package/dist/cjs/ArtifactStoreMetrics.d.ts +70 -0
  17. package/dist/cjs/ArtifactStoreMetrics.d.ts.map +1 -0
  18. package/dist/cjs/ArtifactStoreMetrics.js +51 -0
  19. package/dist/cjs/ArtifactStoreMetrics.js.map +7 -0
  20. package/dist/cjs/ArtifactSweep.d.ts +185 -0
  21. package/dist/cjs/ArtifactSweep.d.ts.map +1 -0
  22. package/dist/cjs/ArtifactSweep.js +171 -0
  23. package/dist/cjs/ArtifactSweep.js.map +7 -0
  24. package/dist/cjs/CombinedArtifacts.d.ts +103 -0
  25. package/dist/cjs/CombinedArtifacts.d.ts.map +1 -0
  26. package/dist/cjs/CombinedArtifacts.js +189 -0
  27. package/dist/cjs/CombinedArtifacts.js.map +7 -0
  28. package/dist/cjs/FileLease.d.ts +117 -0
  29. package/dist/cjs/FileLease.d.ts.map +1 -0
  30. package/dist/cjs/FileLease.js +208 -0
  31. package/dist/cjs/FileLease.js.map +7 -0
  32. package/dist/cjs/FileSystemArtifactStore.d.ts +93 -0
  33. package/dist/cjs/FileSystemArtifactStore.d.ts.map +1 -0
  34. package/dist/cjs/FileSystemArtifactStore.js +276 -0
  35. package/dist/cjs/FileSystemArtifactStore.js.map +7 -0
  36. package/dist/cjs/MemoryArtifactStore.d.ts +25 -0
  37. package/dist/cjs/MemoryArtifactStore.d.ts.map +1 -0
  38. package/dist/cjs/MemoryArtifactStore.js +84 -0
  39. package/dist/cjs/MemoryArtifactStore.js.map +7 -0
  40. package/dist/cjs/NoopArtifactStore.d.ts +17 -0
  41. package/dist/cjs/NoopArtifactStore.d.ts.map +1 -0
  42. package/dist/cjs/NoopArtifactStore.js +46 -0
  43. package/dist/cjs/NoopArtifactStore.js.map +7 -0
  44. package/dist/cjs/RemoteArtifacts.d.ts +237 -0
  45. package/dist/cjs/RemoteArtifacts.d.ts.map +1 -0
  46. package/dist/cjs/RemoteArtifacts.js +405 -0
  47. package/dist/cjs/RemoteArtifacts.js.map +7 -0
  48. package/dist/cjs/index.d.ts +65 -0
  49. package/dist/cjs/index.d.ts.map +1 -0
  50. package/dist/cjs/index.js +47 -0
  51. package/dist/cjs/index.js.map +7 -0
  52. package/dist/cjs/internal/ArtifactLocks.d.ts +30 -0
  53. package/dist/cjs/internal/ArtifactLocks.d.ts.map +1 -0
  54. package/dist/cjs/internal/ArtifactLocks.js +93 -0
  55. package/dist/cjs/internal/ArtifactLocks.js.map +7 -0
  56. package/dist/cjs/internal/ArtifactPath.d.ts +19 -0
  57. package/dist/cjs/internal/ArtifactPath.d.ts.map +1 -0
  58. package/dist/cjs/internal/ArtifactPath.js +74 -0
  59. package/dist/cjs/internal/ArtifactPath.js.map +7 -0
  60. package/dist/cjs/measureBytes.d.ts +18 -0
  61. package/dist/cjs/measureBytes.d.ts.map +1 -0
  62. package/dist/cjs/measureBytes.js +43 -0
  63. package/dist/cjs/measureBytes.js.map +7 -0
  64. package/dist/cjs/package.json +1 -0
  65. package/dist/cjs/snapshotBytes.d.ts +19 -0
  66. package/dist/cjs/snapshotBytes.d.ts.map +1 -0
  67. package/dist/cjs/snapshotBytes.js +41 -0
  68. package/dist/cjs/snapshotBytes.js.map +7 -0
  69. package/dist/cjs/validateDigest.d.ts +22 -0
  70. package/dist/cjs/validateDigest.d.ts.map +1 -0
  71. package/dist/cjs/validateDigest.js +42 -0
  72. package/dist/cjs/validateDigest.js.map +7 -0
  73. package/dist/esm/ArtifactBackupLease.d.ts +34 -0
  74. package/dist/esm/ArtifactBackupLease.d.ts.map +1 -0
  75. package/dist/esm/ArtifactBackupLease.js +126 -0
  76. package/dist/esm/ArtifactBackupLease.js.map +1 -0
  77. package/dist/esm/ArtifactStore.d.ts +129 -0
  78. package/dist/esm/ArtifactStore.d.ts.map +1 -0
  79. package/dist/esm/ArtifactStore.js +83 -0
  80. package/dist/esm/ArtifactStore.js.map +1 -0
  81. package/dist/esm/ArtifactStoreError.d.ts +82 -0
  82. package/dist/esm/ArtifactStoreError.d.ts.map +1 -0
  83. package/dist/esm/ArtifactStoreError.js +77 -0
  84. package/dist/esm/ArtifactStoreError.js.map +1 -0
  85. package/dist/esm/ArtifactStoreMetrics.d.ts +70 -0
  86. package/dist/esm/ArtifactStoreMetrics.d.ts.map +1 -0
  87. package/dist/esm/ArtifactStoreMetrics.js +77 -0
  88. package/dist/esm/ArtifactStoreMetrics.js.map +1 -0
  89. package/dist/esm/ArtifactSweep.d.ts +185 -0
  90. package/dist/esm/ArtifactSweep.d.ts.map +1 -0
  91. package/dist/esm/ArtifactSweep.js +210 -0
  92. package/dist/esm/ArtifactSweep.js.map +1 -0
  93. package/dist/esm/CombinedArtifacts.d.ts +103 -0
  94. package/dist/esm/CombinedArtifacts.d.ts.map +1 -0
  95. package/dist/esm/CombinedArtifacts.js +214 -0
  96. package/dist/esm/CombinedArtifacts.js.map +1 -0
  97. package/dist/esm/FileLease.d.ts +117 -0
  98. package/dist/esm/FileLease.d.ts.map +1 -0
  99. package/dist/esm/FileLease.js +249 -0
  100. package/dist/esm/FileLease.js.map +1 -0
  101. package/dist/esm/FileSystemArtifactStore.d.ts +93 -0
  102. package/dist/esm/FileSystemArtifactStore.d.ts.map +1 -0
  103. package/dist/esm/FileSystemArtifactStore.js +336 -0
  104. package/dist/esm/FileSystemArtifactStore.js.map +1 -0
  105. package/dist/esm/MemoryArtifactStore.d.ts +25 -0
  106. package/dist/esm/MemoryArtifactStore.d.ts.map +1 -0
  107. package/dist/esm/MemoryArtifactStore.js +67 -0
  108. package/dist/esm/MemoryArtifactStore.js.map +1 -0
  109. package/dist/esm/NoopArtifactStore.d.ts +17 -0
  110. package/dist/esm/NoopArtifactStore.d.ts.map +1 -0
  111. package/dist/esm/NoopArtifactStore.js +27 -0
  112. package/dist/esm/NoopArtifactStore.js.map +1 -0
  113. package/dist/esm/RemoteArtifacts.d.ts +237 -0
  114. package/dist/esm/RemoteArtifacts.d.ts.map +1 -0
  115. package/dist/esm/RemoteArtifacts.js +557 -0
  116. package/dist/esm/RemoteArtifacts.js.map +1 -0
  117. package/dist/esm/index.d.ts +65 -0
  118. package/dist/esm/index.d.ts.map +1 -0
  119. package/dist/esm/index.js +65 -0
  120. package/dist/esm/index.js.map +1 -0
  121. package/dist/esm/internal/ArtifactLocks.d.ts +30 -0
  122. package/dist/esm/internal/ArtifactLocks.d.ts.map +1 -0
  123. package/dist/esm/internal/ArtifactLocks.js +86 -0
  124. package/dist/esm/internal/ArtifactLocks.js.map +1 -0
  125. package/dist/esm/internal/ArtifactPath.d.ts +19 -0
  126. package/dist/esm/internal/ArtifactPath.d.ts.map +1 -0
  127. package/dist/esm/internal/ArtifactPath.js +59 -0
  128. package/dist/esm/internal/ArtifactPath.js.map +1 -0
  129. package/dist/esm/measureBytes.d.ts +18 -0
  130. package/dist/esm/measureBytes.d.ts.map +1 -0
  131. package/dist/esm/measureBytes.js +22 -0
  132. package/dist/esm/measureBytes.js.map +1 -0
  133. package/dist/esm/snapshotBytes.d.ts +19 -0
  134. package/dist/esm/snapshotBytes.d.ts.map +1 -0
  135. package/dist/esm/snapshotBytes.js +30 -0
  136. package/dist/esm/snapshotBytes.js.map +1 -0
  137. package/dist/esm/validateDigest.d.ts +22 -0
  138. package/dist/esm/validateDigest.d.ts.map +1 -0
  139. package/dist/esm/validateDigest.js +26 -0
  140. package/dist/esm/validateDigest.js.map +1 -0
  141. package/docs/README.md +202 -0
  142. package/docs/api.md +484 -0
  143. package/docs/concepts/content-addressing.md +174 -0
  144. package/docs/concepts/coordination.md +141 -0
  145. package/docs/concepts/tiers.md +147 -0
  146. package/docs/guides/fence-a-backup.md +123 -0
  147. package/docs/guides/reclaim-disk-space.md +143 -0
  148. package/docs/guides/serve-the-artifact-protocol.md +140 -0
  149. package/docs/guides/share-artifacts-across-machines.md +180 -0
  150. package/docs/guides/test-against-an-artifact-store.md +158 -0
  151. package/docs/installation.md +102 -0
  152. package/docs/quickstart.md +183 -0
  153. package/docs/troubleshooting.md +232 -0
  154. package/package.json +179 -3
  155. package/src/ArtifactBackupLease.ts +223 -0
  156. package/src/ArtifactStore.ts +152 -0
  157. package/src/ArtifactStoreError.ts +96 -0
  158. package/src/ArtifactStoreMetrics.ts +83 -0
  159. package/src/ArtifactSweep.ts +346 -0
  160. package/src/CombinedArtifacts.ts +369 -0
  161. package/src/FileLease.ts +397 -0
  162. package/src/FileSystemArtifactStore.ts +459 -0
  163. package/src/MemoryArtifactStore.ts +83 -0
  164. package/src/NoopArtifactStore.ts +30 -0
  165. package/src/RemoteArtifacts.ts +814 -0
  166. package/src/index.ts +71 -0
  167. package/src/internal/ArtifactLocks.ts +110 -0
  168. package/src/internal/ArtifactPath.ts +72 -0
  169. package/src/measureBytes.ts +28 -0
  170. package/src/snapshotBytes.ts +34 -0
  171. package/src/validateDigest.ts +31 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * The artifact store's typed failures: a refusal of the store itself, the
3
+ * typed miss, and a digest mismatch, with the stable codes a refusal carries.
4
+ *
5
+ * @since 1.0.0-rc.0
6
+ */
7
+ import * as Schema from "effect/Schema";
8
+ /**
9
+ * Stable error codes returned by artifact store operations.
10
+ *
11
+ * @category models
12
+ * @since 1.0.0-rc.0
13
+ * @slop
14
+ */
15
+ export declare const ArtifactStoreErrorCode: Schema.Literals<readonly ["digest_failed", "invalid_configuration", "invalid_digest", "unavailable", "transport_failed"]>;
16
+ /**
17
+ * Stable error codes returned by artifact store operations.
18
+ *
19
+ * @category models
20
+ * @since 1.0.0-rc.0
21
+ * @slop
22
+ */
23
+ export type ArtifactStoreErrorCode = typeof ArtifactStoreErrorCode.Type;
24
+ declare const ArtifactStoreError_base: Schema.Class<ArtifactStoreError, Schema.TaggedStruct<"@smthrs/artifacts/ArtifactStoreError", {
25
+ readonly code: Schema.Literals<readonly ["digest_failed", "invalid_configuration", "invalid_digest", "unavailable", "transport_failed"]>;
26
+ readonly message: Schema.String;
27
+ readonly cause: Schema.optional<Schema.Unknown>;
28
+ }>, import("effect/Cause").YieldableError>;
29
+ /**
30
+ * A typed failure of the store itself: the host or crypto provider refused an
31
+ * operation, the remote tier refused a request, or the caller supplied invalid
32
+ * configuration or an invalid content address.
33
+ *
34
+ * Distinct from {@link ArtifactMissing} and {@link ArtifactCorruption} on
35
+ * purpose. A miss is an ordinary, expected outcome that a second tier may
36
+ * still satisfy; corruption is an integrity violation of the store's strongest
37
+ * invariant. `invalid_configuration` and `invalid_digest` are permanent;
38
+ * retryability of host, crypto, and transport failures depends on the cause.
39
+ *
40
+ * @category errors
41
+ * @since 1.0.0-rc.0
42
+ * @slop
43
+ */
44
+ export declare class ArtifactStoreError extends ArtifactStoreError_base {
45
+ }
46
+ declare const ArtifactMissing_base: Schema.Class<ArtifactMissing, Schema.TaggedStruct<"@smthrs/artifacts/ArtifactMissing", {
47
+ readonly code: Schema.Literal<"artifact_missing">;
48
+ readonly digest: Schema.brand<Schema.String, "@smthrs/crypto/Sha256/Digest">;
49
+ }>, import("effect/Cause").YieldableError>;
50
+ /**
51
+ * The typed miss: this tier holds no bytes at the requested address.
52
+ *
53
+ * A miss is not a failure of the store — it is the answer a read-through
54
+ * composition is built to act on, so it is a distinct tag rather than an
55
+ * `unavailable` code that a caller would have to string-match.
56
+ *
57
+ * @category errors
58
+ * @since 1.0.0-rc.0
59
+ * @slop
60
+ */
61
+ export declare class ArtifactMissing extends ArtifactMissing_base {
62
+ }
63
+ declare const ArtifactCorruption_base: Schema.Class<ArtifactCorruption, Schema.TaggedStruct<"@smthrs/artifacts/ArtifactCorruption", {
64
+ readonly code: Schema.Literal<"artifact_corruption">;
65
+ readonly recordedDigest: Schema.brand<Schema.String, "@smthrs/crypto/Sha256/Digest">;
66
+ readonly measuredDigest: Schema.brand<Schema.String, "@smthrs/crypto/Sha256/Digest">;
67
+ }>, import("effect/Cause").YieldableError>;
68
+ /**
69
+ * Bytes stored at a content address no longer hash to it.
70
+ *
71
+ * Every read is digest-verified, so a truncated blob left by a crashing writer
72
+ * or by disk corruption is refused rather than handed back as if it were the
73
+ * recorded artifact.
74
+ *
75
+ * @category errors
76
+ * @since 1.0.0-rc.0
77
+ * @slop
78
+ */
79
+ export declare class ArtifactCorruption extends ArtifactCorruption_base {
80
+ }
81
+ export {};
82
+ //# sourceMappingURL=ArtifactStoreError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactStoreError.d.ts","sourceRoot":"","sources":["../../src/ArtifactStoreError.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,2HAMjC,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,sBAAsB,CAAC,IAAI,CAAA;;;;;;AAEvE;;;;;;;;;;;;;;GAcG;AACH,qBAAa,kBAAmB,SAAQ,uBAOvC;CAAG;;;;;AAEJ;;;;;;;;;;GAUG;AACH,qBAAa,eAAgB,SAAQ,oBAMpC;CAAG;;;;;;AAEJ;;;;;;;;;;GAUG;AACH,qBAAa,kBAAmB,SAAQ,uBAOvC;CAAG"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The artifact store's typed failures: a refusal of the store itself, the
3
+ * typed miss, and a digest mismatch, with the stable codes a refusal carries.
4
+ *
5
+ * @since 1.0.0-rc.0
6
+ */
7
+ import { Sha256 } from "@smthrs/crypto";
8
+ import * as Schema from "effect/Schema";
9
+ /**
10
+ * Stable error codes returned by artifact store operations.
11
+ *
12
+ * @category models
13
+ * @since 1.0.0-rc.0
14
+ * @slop
15
+ */
16
+ export const ArtifactStoreErrorCode = Schema.Literals([
17
+ "digest_failed",
18
+ "invalid_configuration",
19
+ "invalid_digest",
20
+ "unavailable",
21
+ "transport_failed"
22
+ ]);
23
+ /**
24
+ * A typed failure of the store itself: the host or crypto provider refused an
25
+ * operation, the remote tier refused a request, or the caller supplied invalid
26
+ * configuration or an invalid content address.
27
+ *
28
+ * Distinct from {@link ArtifactMissing} and {@link ArtifactCorruption} on
29
+ * purpose. A miss is an ordinary, expected outcome that a second tier may
30
+ * still satisfy; corruption is an integrity violation of the store's strongest
31
+ * invariant. `invalid_configuration` and `invalid_digest` are permanent;
32
+ * retryability of host, crypto, and transport failures depends on the cause.
33
+ *
34
+ * @category errors
35
+ * @since 1.0.0-rc.0
36
+ * @slop
37
+ */
38
+ export class ArtifactStoreError extends Schema.TaggedError()("@smthrs/artifacts/ArtifactStoreError", {
39
+ code: ArtifactStoreErrorCode,
40
+ message: Schema.String,
41
+ cause: Schema.optional(Schema.Unknown)
42
+ }) {
43
+ }
44
+ /**
45
+ * The typed miss: this tier holds no bytes at the requested address.
46
+ *
47
+ * A miss is not a failure of the store — it is the answer a read-through
48
+ * composition is built to act on, so it is a distinct tag rather than an
49
+ * `unavailable` code that a caller would have to string-match.
50
+ *
51
+ * @category errors
52
+ * @since 1.0.0-rc.0
53
+ * @slop
54
+ */
55
+ export class ArtifactMissing extends Schema.TaggedError()("@smthrs/artifacts/ArtifactMissing", {
56
+ code: Schema.Literal("artifact_missing"),
57
+ digest: Sha256.Digest
58
+ }) {
59
+ }
60
+ /**
61
+ * Bytes stored at a content address no longer hash to it.
62
+ *
63
+ * Every read is digest-verified, so a truncated blob left by a crashing writer
64
+ * or by disk corruption is refused rather than handed back as if it were the
65
+ * recorded artifact.
66
+ *
67
+ * @category errors
68
+ * @since 1.0.0-rc.0
69
+ * @slop
70
+ */
71
+ export class ArtifactCorruption extends Schema.TaggedError()("@smthrs/artifacts/ArtifactCorruption", {
72
+ code: Schema.Literal("artifact_corruption"),
73
+ recordedDigest: Sha256.Digest,
74
+ measuredDigest: Sha256.Digest
75
+ }) {
76
+ }
77
+ //# sourceMappingURL=ArtifactStoreError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactStoreError.js","sourceRoot":"","sources":["../../src/ArtifactStoreError.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,QAAQ,CAAC;IACpD,eAAe;IACf,uBAAuB;IACvB,gBAAgB;IAChB,aAAa;IACb,kBAAkB;CACnB,CAAC,CAAA;AAWF;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAC9E,sCAAsC,EACtC;IACE,IAAI,EAAE,sBAAsB;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;CACvC,CACF;CAAG;AAEJ;;;;;;;;;;GAUG;AACH,MAAM,OAAO,eAAgB,SAAQ,MAAM,CAAC,WAAW,EAAmB,CACxE,mCAAmC,EACnC;IACE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC,MAAM;CACtB,CACF;CAAG;AAEJ;;;;;;;;;;GAUG;AACH,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAC9E,sCAAsC,EACtC;IACE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAC,MAAM;IAC7B,cAAc,EAAE,MAAM,CAAC,MAAM;CAC9B,CACF;CAAG","sourcesContent":["/**\n * The artifact store's typed failures: a refusal of the store itself, the\n * typed miss, and a digest mismatch, with the stable codes a refusal carries.\n *\n * @since 1.0.0-rc.0\n */\n\nimport { Sha256 } from \"@smthrs/crypto\"\nimport * as Schema from \"effect/Schema\"\n\n/**\n * Stable error codes returned by artifact store operations.\n *\n * @category models\n * @since 1.0.0-rc.0\n * @slop\n */\nexport const ArtifactStoreErrorCode = Schema.Literals([\n \"digest_failed\",\n \"invalid_configuration\",\n \"invalid_digest\",\n \"unavailable\",\n \"transport_failed\"\n])\n\n/**\n * Stable error codes returned by artifact store operations.\n *\n * @category models\n * @since 1.0.0-rc.0\n * @slop\n */\nexport type ArtifactStoreErrorCode = typeof ArtifactStoreErrorCode.Type\n\n/**\n * A typed failure of the store itself: the host or crypto provider refused an\n * operation, the remote tier refused a request, or the caller supplied invalid\n * configuration or an invalid content address.\n *\n * Distinct from {@link ArtifactMissing} and {@link ArtifactCorruption} on\n * purpose. A miss is an ordinary, expected outcome that a second tier may\n * still satisfy; corruption is an integrity violation of the store's strongest\n * invariant. `invalid_configuration` and `invalid_digest` are permanent;\n * retryability of host, crypto, and transport failures depends on the cause.\n *\n * @category errors\n * @since 1.0.0-rc.0\n * @slop\n */\nexport class ArtifactStoreError extends Schema.TaggedError<ArtifactStoreError>()(\n \"@smthrs/artifacts/ArtifactStoreError\",\n {\n code: ArtifactStoreErrorCode,\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown)\n }\n) {}\n\n/**\n * The typed miss: this tier holds no bytes at the requested address.\n *\n * A miss is not a failure of the store — it is the answer a read-through\n * composition is built to act on, so it is a distinct tag rather than an\n * `unavailable` code that a caller would have to string-match.\n *\n * @category errors\n * @since 1.0.0-rc.0\n * @slop\n */\nexport class ArtifactMissing extends Schema.TaggedError<ArtifactMissing>()(\n \"@smthrs/artifacts/ArtifactMissing\",\n {\n code: Schema.Literal(\"artifact_missing\"),\n digest: Sha256.Digest\n }\n) {}\n\n/**\n * Bytes stored at a content address no longer hash to it.\n *\n * Every read is digest-verified, so a truncated blob left by a crashing writer\n * or by disk corruption is refused rather than handed back as if it were the\n * recorded artifact.\n *\n * @category errors\n * @since 1.0.0-rc.0\n * @slop\n */\nexport class ArtifactCorruption extends Schema.TaggedError<ArtifactCorruption>()(\n \"@smthrs/artifacts/ArtifactCorruption\",\n {\n code: Schema.Literal(\"artifact_corruption\"),\n recordedDigest: Sha256.Digest,\n measuredDigest: Sha256.Digest\n }\n) {}\n"]}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Standard metric definitions for content-addressed artifact storage.
3
+ *
4
+ * This module only defines the metric handles, following the shape of Effect's
5
+ * `ClusterMetrics`. No exporter ships in this package; provide one — for
6
+ * example `@smthrs/observability` — and these counters appear in it.
7
+ *
8
+ * Only the local `ArtifactStore` implementations, filesystem and memory, update
9
+ * them. `RemoteArtifacts` is deliberately uninstrumented, and the counters carry
10
+ * no tier attribute, so read them as *local artifact store traffic* rather than
11
+ * as artifact operations:
12
+ *
13
+ * - a `CombinedArtifacts` read the local tier serves counts one get;
14
+ * - a read the shared tier serves counts NO get, because no local store
15
+ * answered it;
16
+ * - the write-back that materializes such a read counts a put, indistinguishable
17
+ * from a producer publishing new bytes.
18
+ *
19
+ * Attributing operations per tier needs the tier in the metric, which would
20
+ * change the published counter shape; until then this is what the numbers mean.
21
+ *
22
+ * The one shared-tier signal is {@link remoteFailure}: a `CombinedArtifacts`
23
+ * upload or write-back that was refused, or abandoned at its deadline.
24
+ *
25
+ * @since 1.0.0-rc.0
26
+ */
27
+ import * as Metric from "effect/Metric";
28
+ /**
29
+ * Counter over successful artifact puts. A put that deduplicated against an
30
+ * existing verified blob still counts: the caller stored bytes and received
31
+ * an address either way.
32
+ *
33
+ * @category metrics
34
+ * @since 1.0.0-rc.0
35
+ * @slop
36
+ */
37
+ export declare const puts: Metric.Counter<number>;
38
+ /**
39
+ * Counter over successful artifact gets. Missing and corrupt reads fail with
40
+ * their typed errors and are deliberately not counted here; they are error
41
+ * evidence, not throughput.
42
+ *
43
+ * @category metrics
44
+ * @since 1.0.0-rc.0
45
+ * @slop
46
+ */
47
+ export declare const gets: Metric.Counter<number>;
48
+ /**
49
+ * Counter over opportunistic `CombinedArtifacts` transfers that failed or hit
50
+ * their deadline and were dropped: `put`'s upload to the shared tier and
51
+ * `get`'s write-back into the local tier.
52
+ *
53
+ * Read the attributed views on {@link remoteFailure}: every update carries an
54
+ * `operation` attribute, so this bare handle aggregates nothing and always
55
+ * reads zero.
56
+ *
57
+ * @category metrics
58
+ * @since 1.0.0-rc.1
59
+ */
60
+ export declare const remoteFailures: Metric.Counter<number>;
61
+ /**
62
+ * `remoteFailures` views keyed by the dropped transfer.
63
+ *
64
+ * @category metrics
65
+ * @since 1.0.0-rc.1
66
+ */
67
+ export declare const remoteFailure: {
68
+ readonly [Operation in "put" | "write_back"]: Metric.Metric<number, Metric.CounterState<number>>;
69
+ };
70
+ //# sourceMappingURL=ArtifactStoreMetrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactStoreMetrics.d.ts","sourceRoot":"","sources":["../../src/ArtifactStoreMetrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI,wBAEf,CAAA;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI,wBAEf,CAAA;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,wBAEzB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE;IAC1B,QAAQ,EAAE,SAAS,IAAI,KAAK,GAAG,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;CAIjG,CAAA"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Standard metric definitions for content-addressed artifact storage.
3
+ *
4
+ * This module only defines the metric handles, following the shape of Effect's
5
+ * `ClusterMetrics`. No exporter ships in this package; provide one — for
6
+ * example `@smthrs/observability` — and these counters appear in it.
7
+ *
8
+ * Only the local `ArtifactStore` implementations, filesystem and memory, update
9
+ * them. `RemoteArtifacts` is deliberately uninstrumented, and the counters carry
10
+ * no tier attribute, so read them as *local artifact store traffic* rather than
11
+ * as artifact operations:
12
+ *
13
+ * - a `CombinedArtifacts` read the local tier serves counts one get;
14
+ * - a read the shared tier serves counts NO get, because no local store
15
+ * answered it;
16
+ * - the write-back that materializes such a read counts a put, indistinguishable
17
+ * from a producer publishing new bytes.
18
+ *
19
+ * Attributing operations per tier needs the tier in the metric, which would
20
+ * change the published counter shape; until then this is what the numbers mean.
21
+ *
22
+ * The one shared-tier signal is {@link remoteFailure}: a `CombinedArtifacts`
23
+ * upload or write-back that was refused, or abandoned at its deadline.
24
+ *
25
+ * @since 1.0.0-rc.0
26
+ */
27
+ import * as Metric from "effect/Metric";
28
+ /**
29
+ * Counter over successful artifact puts. A put that deduplicated against an
30
+ * existing verified blob still counts: the caller stored bytes and received
31
+ * an address either way.
32
+ *
33
+ * @category metrics
34
+ * @since 1.0.0-rc.0
35
+ * @slop
36
+ */
37
+ export const puts = Metric.counter("flows_artifact_puts", {
38
+ description: "Successful artifact puts, including deduplicated ones"
39
+ });
40
+ /**
41
+ * Counter over successful artifact gets. Missing and corrupt reads fail with
42
+ * their typed errors and are deliberately not counted here; they are error
43
+ * evidence, not throughput.
44
+ *
45
+ * @category metrics
46
+ * @since 1.0.0-rc.0
47
+ * @slop
48
+ */
49
+ export const gets = Metric.counter("flows_artifact_gets", {
50
+ description: "Successful artifact gets"
51
+ });
52
+ /**
53
+ * Counter over opportunistic `CombinedArtifacts` transfers that failed or hit
54
+ * their deadline and were dropped: `put`'s upload to the shared tier and
55
+ * `get`'s write-back into the local tier.
56
+ *
57
+ * Read the attributed views on {@link remoteFailure}: every update carries an
58
+ * `operation` attribute, so this bare handle aggregates nothing and always
59
+ * reads zero.
60
+ *
61
+ * @category metrics
62
+ * @since 1.0.0-rc.1
63
+ */
64
+ export const remoteFailures = Metric.counter("flows_artifact_remote_failures", {
65
+ description: "Dropped combined-artifact transfers by operation"
66
+ });
67
+ /**
68
+ * `remoteFailures` views keyed by the dropped transfer.
69
+ *
70
+ * @category metrics
71
+ * @since 1.0.0-rc.1
72
+ */
73
+ export const remoteFailure = {
74
+ put: Metric.withAttributes(remoteFailures, { operation: "put" }),
75
+ write_back: Metric.withAttributes(remoteFailures, { operation: "write_back" })
76
+ };
77
+ //# sourceMappingURL=ArtifactStoreMetrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactStoreMetrics.js","sourceRoot":"","sources":["../../src/ArtifactStoreMetrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE;IACxD,WAAW,EAAE,uDAAuD;CACrE,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE;IACxD,WAAW,EAAE,0BAA0B;CACxC,CAAC,CAAA;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,gCAAgC,EAAE;IAC7E,WAAW,EAAE,kDAAkD;CAChE,CAAC,CAAA;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAEtB;IACF,GAAG,EAAE,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;CAC/E,CAAA","sourcesContent":["/**\n * Standard metric definitions for content-addressed artifact storage.\n *\n * This module only defines the metric handles, following the shape of Effect's\n * `ClusterMetrics`. No exporter ships in this package; provide one — for\n * example `@smthrs/observability` — and these counters appear in it.\n *\n * Only the local `ArtifactStore` implementations, filesystem and memory, update\n * them. `RemoteArtifacts` is deliberately uninstrumented, and the counters carry\n * no tier attribute, so read them as *local artifact store traffic* rather than\n * as artifact operations:\n *\n * - a `CombinedArtifacts` read the local tier serves counts one get;\n * - a read the shared tier serves counts NO get, because no local store\n * answered it;\n * - the write-back that materializes such a read counts a put, indistinguishable\n * from a producer publishing new bytes.\n *\n * Attributing operations per tier needs the tier in the metric, which would\n * change the published counter shape; until then this is what the numbers mean.\n *\n * The one shared-tier signal is {@link remoteFailure}: a `CombinedArtifacts`\n * upload or write-back that was refused, or abandoned at its deadline.\n *\n * @since 1.0.0-rc.0\n */\n\nimport * as Metric from \"effect/Metric\"\n\n/**\n * Counter over successful artifact puts. A put that deduplicated against an\n * existing verified blob still counts: the caller stored bytes and received\n * an address either way.\n *\n * @category metrics\n * @since 1.0.0-rc.0\n * @slop\n */\nexport const puts = Metric.counter(\"flows_artifact_puts\", {\n description: \"Successful artifact puts, including deduplicated ones\"\n})\n\n/**\n * Counter over successful artifact gets. Missing and corrupt reads fail with\n * their typed errors and are deliberately not counted here; they are error\n * evidence, not throughput.\n *\n * @category metrics\n * @since 1.0.0-rc.0\n * @slop\n */\nexport const gets = Metric.counter(\"flows_artifact_gets\", {\n description: \"Successful artifact gets\"\n})\n\n/**\n * Counter over opportunistic `CombinedArtifacts` transfers that failed or hit\n * their deadline and were dropped: `put`'s upload to the shared tier and\n * `get`'s write-back into the local tier.\n *\n * Read the attributed views on {@link remoteFailure}: every update carries an\n * `operation` attribute, so this bare handle aggregates nothing and always\n * reads zero.\n *\n * @category metrics\n * @since 1.0.0-rc.1\n */\nexport const remoteFailures = Metric.counter(\"flows_artifact_remote_failures\", {\n description: \"Dropped combined-artifact transfers by operation\"\n})\n\n/**\n * `remoteFailures` views keyed by the dropped transfer.\n *\n * @category metrics\n * @since 1.0.0-rc.1\n */\nexport const remoteFailure: {\n readonly [Operation in \"put\" | \"write_back\"]: Metric.Metric<number, Metric.CounterState<number>>\n} = {\n put: Metric.withAttributes(remoteFailures, { operation: \"put\" }),\n write_back: Metric.withAttributes(remoteFailures, { operation: \"write_back\" })\n}\n"]}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * The sweep half of artifact garbage collection: enumerate this host's blobs
3
+ * and delete one, fenced by its age.
4
+ *
5
+ * This surface is deliberately NOT part of `ArtifactStore.Service`. The store
6
+ * contract is shared by memory, filesystem, and network tiers, and a remote
7
+ * tier can neither enumerate its address space nor accept a delete — Bazel
8
+ * draws the same line: its disk-cache collector
9
+ * (class `DiskCacheGarbageCollector` in
10
+ * `com.google.devtools.build.lib.remote.disk`) walks the local directory, while
11
+ * the remote tier owns its own retention. Only the
12
+ * host-local filesystem store implements this.
13
+ *
14
+ * The *policy* — which digests are live, how old a dead blob must be before it
15
+ * goes — belongs to the engine composition, which is the only place the
16
+ * durable roots (attempt rows, cache entries) are visible. This module ships
17
+ * mechanics alone; `@smthrs/engine-store` owns the mark policy and grace
18
+ * period.
19
+ *
20
+ * @since 1.0.0-rc.0
21
+ */
22
+ import * as Context from "effect/Context";
23
+ import * as Effect from "effect/Effect";
24
+ import * as FileSystem from "effect/FileSystem";
25
+ import * as Layer from "effect/Layer";
26
+ import * as ArtifactStore from "./ArtifactStore.ts";
27
+ /**
28
+ * One enumerated blob: its content address, when it was last written or
29
+ * freshened, and its size.
30
+ *
31
+ * `modifiedAtMs` is the age evidence a sweep fences on — the same signal git
32
+ * (`git prune --expire`) and Bazel's disk-cache collector read, because it is
33
+ * the one timestamp a filesystem maintains without any bookkeeping of ours.
34
+ *
35
+ * @category models
36
+ * @since 1.0.0-rc.0
37
+ * @slop
38
+ */
39
+ export interface BlobStat {
40
+ readonly digest: string;
41
+ readonly modifiedAtMs: number;
42
+ readonly sizeBytes: number;
43
+ }
44
+ /**
45
+ * Fencing predicate for a sweep deletion.
46
+ *
47
+ * @category models
48
+ * @since 1.0.0-rc.0
49
+ * @slop
50
+ */
51
+ export interface RemoveOptions {
52
+ /**
53
+ * Deletes the blob only while its mtime is still at or before this bound.
54
+ * A blob freshened after the caller computed its live set — a concurrent
55
+ * `put` re-referencing the same bytes — fails the fence and survives, the
56
+ * same shape as `CacheStore.evict`'s `ifRecordedBy`: the guard rides in the
57
+ * delete, never in a prior read alone.
58
+ */
59
+ readonly ifUnmodifiedSinceMs?: number | undefined;
60
+ }
61
+ /**
62
+ * Host-local blob enumeration and fenced deletion.
63
+ *
64
+ * @category models
65
+ * @since 1.0.0-rc.0
66
+ * @slop
67
+ */
68
+ export interface Service {
69
+ /**
70
+ * Every content-addressed blob this host's store currently holds. In-flight
71
+ * `.tmp-*` scratch files, foreign files, and blobs whose age cannot be
72
+ * measured are excluded — what the sweep cannot judge it must not touch.
73
+ */
74
+ readonly inventory: Effect.Effect<Array<BlobStat>, ArtifactStore.ArtifactStoreError>;
75
+ /**
76
+ * Deletes the blob at `digest`, returning whether bytes were removed. A
77
+ * missing blob reports `false` rather than failing, so a crashed and
78
+ * re-run sweep converges instead of erroring on its own progress.
79
+ *
80
+ * `false` covers three outcomes a caller cannot tell apart, all of which mean
81
+ * "nothing was reclaimed, and retrying later is safe": the blob was already
82
+ * gone, it failed the `ifUnmodifiedSinceMs` fence, or a live backup lease
83
+ * fenced the deletion (see `ArtifactBackupLease`). The last one is not
84
+ * progress — the blob is still there — so a collector that counts reclaimed
85
+ * bytes must not count it, and the next pass after the backup finishes
86
+ * removes it.
87
+ */
88
+ readonly remove: (digest: string, options?: RemoveOptions) => Effect.Effect<boolean, ArtifactStore.ArtifactStoreError>;
89
+ }
90
+ declare const ArtifactSweep_base: Context.ServiceClass<ArtifactSweep, "@smthrs/artifacts/ArtifactSweep", Service>;
91
+ /**
92
+ * Service tag for host-local artifact sweeping.
93
+ *
94
+ * The identity string equals this module's package path, per the house rule
95
+ * that a new identity is the defining module path.
96
+ *
97
+ * @category services
98
+ * @since 1.0.0-rc.0
99
+ * @slop
100
+ */
101
+ export declare class ArtifactSweep extends ArtifactSweep_base {
102
+ }
103
+ /**
104
+ * How the sweep reaches the objects directory.
105
+ *
106
+ * Deliberately not `ArtifactStore.FileSystemOptions`: the sweep never writes a
107
+ * blob, so `durability` would be an accepted argument it ignores. Both fields
108
+ * must match the store built over the same directory — see `coordination`.
109
+ *
110
+ * @category models
111
+ * @since 1.0.0-rc.0
112
+ */
113
+ export interface SweepOptions {
114
+ /**
115
+ * The objects directory to enumerate, the one the paired
116
+ * `ArtifactStore.makeFileSystem` publishes into. Defaults to
117
+ * `ArtifactStore.defaultDirectory`.
118
+ */
119
+ readonly directory?: string | undefined;
120
+ /**
121
+ * `required` takes the same per-digest lock file a publishing writer takes,
122
+ * and consults the backup lease, before deleting. It fences nothing unless
123
+ * the paired store was built with `required` too: a store on `process` never
124
+ * takes the lock this sweep waits on, so the fence would read as armed while
125
+ * protecting nothing. `process` is the explicit weaker browser/test mode.
126
+ */
127
+ readonly coordination?: "required" | "process" | undefined;
128
+ }
129
+ /**
130
+ * Builds the filesystem-backed sweep surface over the same objects directory
131
+ * an `ArtifactStore.makeFileSystem` publishes into.
132
+ *
133
+ * Enumeration is conservative by construction. Only paths in the store's
134
+ * canonical fanout shape — `xx/<digest>` with `xx` equal to the digest's
135
+ * two-hex prefix — are blobs; anything else in the directory (a temp file, a
136
+ * lock file, a foreign file, a fanout directory itself) is skipped, never
137
+ * deleted. A blob that vanishes between listing and stat was removed by someone
138
+ * else and is likewise skipped.
139
+ *
140
+ * Pair it with the store over the SAME `directory` and the SAME `coordination`.
141
+ * Nothing checks the pairing, and a mismatch is silent: a sweep on `required`
142
+ * beside a store on `process` deletes blobs no writer is fenced against.
143
+ *
144
+ * Under `required`, one deletion costs two lock acquisitions — the per-digest
145
+ * lock, then the workspace-global backup-lease gate — which is roughly ten
146
+ * filesystem operations and two forked heartbeat fibers per blob. The gate is
147
+ * one file for the whole workspace, so concurrent deletions serialize through
148
+ * it. That is the price of never deleting a blob a running backup already
149
+ * recorded; size a collection window with it in mind.
150
+ *
151
+ * @category constructors
152
+ * @since 1.0.0-rc.0
153
+ * @slop
154
+ */
155
+ export declare const makeFileSystem: (fs: FileSystem.FileSystem, options?: SweepOptions) => Service;
156
+ /**
157
+ * Provides the filesystem-backed sweep surface.
158
+ *
159
+ * Give it the same `directory` and `coordination` as the `ArtifactStore` layer
160
+ * it sweeps behind; see {@link makeFileSystem}.
161
+ *
162
+ * @category layers
163
+ * @since 1.0.0-rc.0
164
+ * @slop
165
+ */
166
+ export declare const layerFileSystem: (options?: SweepOptions) => Layer.Layer<ArtifactSweep, never, FileSystem.FileSystem>;
167
+ /**
168
+ * Builds a sweep surface whose every operation fails as unavailable, with
169
+ * per-method overrides.
170
+ *
171
+ * @category constructors
172
+ * @since 1.0.0-rc.0
173
+ * @slop
174
+ */
175
+ export declare const makeNoop: (overrides?: Partial<Service>) => Service;
176
+ /**
177
+ * Provides a no-op sweep surface.
178
+ *
179
+ * @category layers
180
+ * @since 1.0.0-rc.0
181
+ * @slop
182
+ */
183
+ export declare const layerNoop: (overrides?: Partial<Service>) => Layer.Layer<ArtifactSweep>;
184
+ export {};
185
+ //# sourceMappingURL=ArtifactSweep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactSweep.d.ts","sourceRoot":"","sources":["../../src/ArtifactSweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAIrC,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AAInD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAClD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAA;IACpF;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,MAAM,EAAE,CACf,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,aAAa,KACpB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAA;CAC9D;;AAED;;;;;;;;;GASG;AACH,qBAAa,aAAc,SAAQ,kBAA4E;CAAG;AAelH;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAA;CAC3D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,cAAc,GACzB,IAAI,UAAU,CAAC,UAAU,EACzB,UAAS,YAAiB,KACzB,OA2HF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAS,YAAiB,KACzB,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAC2C,CAAA;AAErG;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,GAAI,YAAW,OAAO,CAAC,OAAO,CAAM,KAAG,OAI1D,CAAA;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GAAI,YAAW,OAAO,CAAC,OAAO,CAAM,KAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CACnC,CAAA"}