zarr-metadata 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +11 -7
  2. package/dist/chunk-grid/index.d.ts +27 -0
  3. package/dist/chunk-grid/index.d.ts.map +1 -0
  4. package/dist/chunk-grid/index.js +21 -0
  5. package/dist/chunk-grid/index.js.map +1 -0
  6. package/dist/chunk-grid/rectilinear.d.ts +14 -0
  7. package/dist/chunk-grid/rectilinear.d.ts.map +1 -0
  8. package/dist/{chunk-grids.js → chunk-grid/rectilinear.js} +3 -60
  9. package/dist/chunk-grid/rectilinear.js.map +1 -0
  10. package/dist/chunk-grid/regular.d.ts +7 -0
  11. package/dist/chunk-grid/regular.d.ts.map +1 -0
  12. package/dist/chunk-grid/regular.js +36 -0
  13. package/dist/chunk-grid/regular.js.map +1 -0
  14. package/dist/codec/index.d.ts +34 -0
  15. package/dist/codec/index.d.ts.map +1 -0
  16. package/dist/codec/index.js +35 -0
  17. package/dist/codec/index.js.map +1 -0
  18. package/dist/codec/sharding-indexed.d.ts +26 -0
  19. package/dist/codec/sharding-indexed.d.ts.map +1 -0
  20. package/dist/codec/sharding-indexed.js +80 -0
  21. package/dist/codec/sharding-indexed.js.map +1 -0
  22. package/dist/codec/transpose.d.ts +19 -0
  23. package/dist/codec/transpose.d.ts.map +1 -0
  24. package/dist/codec/transpose.js +66 -0
  25. package/dist/codec/transpose.js.map +1 -0
  26. package/dist/data-type/bool.d.ts +4 -0
  27. package/dist/data-type/bool.d.ts.map +1 -0
  28. package/dist/data-type/bool.js +7 -0
  29. package/dist/data-type/bool.js.map +1 -0
  30. package/dist/data-type/bytes.d.ts +11 -0
  31. package/dist/data-type/bytes.d.ts.map +1 -0
  32. package/dist/data-type/bytes.js +18 -0
  33. package/dist/data-type/bytes.js.map +1 -0
  34. package/dist/data-type/complex128.d.ts +3 -0
  35. package/dist/data-type/complex128.d.ts.map +1 -0
  36. package/dist/data-type/complex128.js +4 -0
  37. package/dist/data-type/complex128.js.map +1 -0
  38. package/dist/data-type/complex64.d.ts +3 -0
  39. package/dist/data-type/complex64.d.ts.map +1 -0
  40. package/dist/data-type/complex64.js +4 -0
  41. package/dist/data-type/complex64.js.map +1 -0
  42. package/dist/data-type/descriptor.d.ts +44 -0
  43. package/dist/data-type/descriptor.d.ts.map +1 -0
  44. package/dist/data-type/descriptor.js +57 -0
  45. package/dist/data-type/descriptor.js.map +1 -0
  46. package/dist/data-type/float16.d.ts +3 -0
  47. package/dist/data-type/float16.d.ts.map +1 -0
  48. package/dist/data-type/float16.js +4 -0
  49. package/dist/data-type/float16.js.map +1 -0
  50. package/dist/data-type/float32.d.ts +3 -0
  51. package/dist/data-type/float32.d.ts.map +1 -0
  52. package/dist/data-type/float32.js +4 -0
  53. package/dist/data-type/float32.js.map +1 -0
  54. package/dist/data-type/float64.d.ts +3 -0
  55. package/dist/data-type/float64.d.ts.map +1 -0
  56. package/dist/data-type/float64.js +4 -0
  57. package/dist/data-type/float64.js.map +1 -0
  58. package/dist/data-type/index.d.ts +23 -0
  59. package/dist/data-type/index.d.ts.map +1 -0
  60. package/dist/data-type/index.js +92 -0
  61. package/dist/data-type/index.js.map +1 -0
  62. package/dist/data-type/int16.d.ts +3 -0
  63. package/dist/data-type/int16.d.ts.map +1 -0
  64. package/dist/data-type/int16.js +4 -0
  65. package/dist/data-type/int16.js.map +1 -0
  66. package/dist/data-type/int32.d.ts +3 -0
  67. package/dist/data-type/int32.d.ts.map +1 -0
  68. package/dist/data-type/int32.js +4 -0
  69. package/dist/data-type/int32.js.map +1 -0
  70. package/dist/data-type/int64.d.ts +3 -0
  71. package/dist/data-type/int64.d.ts.map +1 -0
  72. package/dist/data-type/int64.js +4 -0
  73. package/dist/data-type/int64.js.map +1 -0
  74. package/dist/data-type/int8.d.ts +3 -0
  75. package/dist/data-type/int8.d.ts.map +1 -0
  76. package/dist/data-type/int8.js +4 -0
  77. package/dist/data-type/int8.js.map +1 -0
  78. package/dist/data-type/numpy-datetime64.d.ts +18 -0
  79. package/dist/data-type/numpy-datetime64.d.ts.map +1 -0
  80. package/dist/data-type/numpy-datetime64.js +14 -0
  81. package/dist/data-type/numpy-datetime64.js.map +1 -0
  82. package/dist/data-type/numpy-timedelta64.d.ts +4 -0
  83. package/dist/data-type/numpy-timedelta64.d.ts.map +1 -0
  84. package/dist/data-type/numpy-timedelta64.js +4 -0
  85. package/dist/data-type/numpy-timedelta64.js.map +1 -0
  86. package/dist/data-type/raw.d.ts +10 -0
  87. package/dist/data-type/raw.d.ts.map +1 -0
  88. package/dist/data-type/raw.js +26 -0
  89. package/dist/data-type/raw.js.map +1 -0
  90. package/dist/data-type/string.d.ts +6 -0
  91. package/dist/data-type/string.d.ts.map +1 -0
  92. package/dist/data-type/string.js +7 -0
  93. package/dist/data-type/string.js.map +1 -0
  94. package/dist/data-type/struct.d.ts +17 -0
  95. package/dist/data-type/struct.d.ts.map +1 -0
  96. package/dist/data-type/struct.js +44 -0
  97. package/dist/data-type/struct.js.map +1 -0
  98. package/dist/data-type/uint16.d.ts +3 -0
  99. package/dist/data-type/uint16.d.ts.map +1 -0
  100. package/dist/data-type/uint16.js +4 -0
  101. package/dist/data-type/uint16.js.map +1 -0
  102. package/dist/data-type/uint32.d.ts +3 -0
  103. package/dist/data-type/uint32.d.ts.map +1 -0
  104. package/dist/data-type/uint32.js +4 -0
  105. package/dist/data-type/uint32.js.map +1 -0
  106. package/dist/data-type/uint64.d.ts +3 -0
  107. package/dist/data-type/uint64.d.ts.map +1 -0
  108. package/dist/data-type/uint64.js +4 -0
  109. package/dist/data-type/uint64.js.map +1 -0
  110. package/dist/data-type/uint8.d.ts +3 -0
  111. package/dist/data-type/uint8.d.ts.map +1 -0
  112. package/dist/data-type/uint8.js +4 -0
  113. package/dist/data-type/uint8.js.map +1 -0
  114. package/dist/index.d.ts +3 -3
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js.map +1 -1
  117. package/dist/semantics.d.ts +4 -4
  118. package/dist/semantics.d.ts.map +1 -1
  119. package/dist/semantics.js +9 -15
  120. package/dist/semantics.js.map +1 -1
  121. package/package.json +4 -2
  122. package/src/chunk-grid/index.ts +40 -0
  123. package/src/{chunk-grids.ts → chunk-grid/rectilinear.ts} +5 -75
  124. package/src/chunk-grid/regular.ts +42 -0
  125. package/src/codec/index.ts +76 -0
  126. package/src/codec/sharding-indexed.ts +113 -0
  127. package/src/codec/transpose.ts +80 -0
  128. package/src/data-type/bool.ts +8 -0
  129. package/src/data-type/bytes.ts +26 -0
  130. package/src/data-type/complex128.ts +4 -0
  131. package/src/data-type/complex64.ts +4 -0
  132. package/src/data-type/descriptor.ts +115 -0
  133. package/src/data-type/float16.ts +4 -0
  134. package/src/data-type/float32.ts +4 -0
  135. package/src/data-type/float64.ts +4 -0
  136. package/src/data-type/index.ts +129 -0
  137. package/src/data-type/int16.ts +4 -0
  138. package/src/data-type/int32.ts +4 -0
  139. package/src/data-type/int64.ts +4 -0
  140. package/src/data-type/int8.ts +4 -0
  141. package/src/data-type/numpy-datetime64.ts +33 -0
  142. package/src/data-type/numpy-timedelta64.ts +9 -0
  143. package/src/data-type/raw.ts +31 -0
  144. package/src/data-type/string.ts +11 -0
  145. package/src/data-type/struct.ts +55 -0
  146. package/src/data-type/uint16.ts +4 -0
  147. package/src/data-type/uint32.ts +4 -0
  148. package/src/data-type/uint64.ts +4 -0
  149. package/src/data-type/uint8.ts +4 -0
  150. package/src/index.ts +14 -3
  151. package/src/semantics.ts +9 -15
  152. package/dist/chunk-grids.d.ts +0 -40
  153. package/dist/chunk-grids.d.ts.map +0 -1
  154. package/dist/chunk-grids.js.map +0 -1
  155. package/dist/codecs.d.ts +0 -37
  156. package/dist/codecs.d.ts.map +0 -1
  157. package/dist/codecs.js +0 -182
  158. package/dist/codecs.js.map +0 -1
  159. package/dist/data-types.d.ts +0 -12
  160. package/dist/data-types.d.ts.map +0 -1
  161. package/dist/data-types.js +0 -70
  162. package/dist/data-types.js.map +0 -1
  163. package/src/codecs.ts +0 -214
  164. package/src/data-types.ts +0 -81
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint16.d.ts","sourceRoot":"","sources":["../../src/data-type/uint16.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,eAAO,MAAM,MAAM,8CAAkC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { intDataType } from "./descriptor.js";
2
+ /** The core `uint16` data type. */
3
+ export const uint16 = intDataType("uint16", 0, 65535);
4
+ //# sourceMappingURL=uint16.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint16.js","sourceRoot":"","sources":["../../src/data-type/uint16.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,mCAAmC;AACnC,MAAM,CAAC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** The core `uint32` data type. */
2
+ export declare const uint32: import("./descriptor.js").DataTypeDescriptor;
3
+ //# sourceMappingURL=uint32.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint32.d.ts","sourceRoot":"","sources":["../../src/data-type/uint32.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,eAAO,MAAM,MAAM,8CAAuC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { intDataType } from "./descriptor.js";
2
+ /** The core `uint32` data type. */
3
+ export const uint32 = intDataType("uint32", 0, 4294967295);
4
+ //# sourceMappingURL=uint32.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint32.js","sourceRoot":"","sources":["../../src/data-type/uint32.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,mCAAmC;AACnC,MAAM,CAAC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** The core `uint64` data type. */
2
+ export declare const uint64: import("./descriptor.js").DataTypeDescriptor;
3
+ //# sourceMappingURL=uint64.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint64.d.ts","sourceRoot":"","sources":["../../src/data-type/uint64.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,eAAO,MAAM,MAAM,8CAAiD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { intDataType } from "./descriptor.js";
2
+ /** The core `uint64` data type. */
3
+ export const uint64 = intDataType("uint64", 0, 18446744073709551615);
4
+ //# sourceMappingURL=uint64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint64.js","sourceRoot":"","sources":["../../src/data-type/uint64.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,mCAAmC;AACnC,MAAM,CAAC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,CAAC,EAAE,oBAAoB,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** The core `uint8` data type. */
2
+ export declare const uint8: import("./descriptor.js").DataTypeDescriptor;
3
+ //# sourceMappingURL=uint8.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint8.d.ts","sourceRoot":"","sources":["../../src/data-type/uint8.ts"],"names":[],"mappings":"AAEA,kCAAkC;AAClC,eAAO,MAAM,KAAK,8CAA+B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { intDataType } from "./descriptor.js";
2
+ /** The core `uint8` data type. */
3
+ export const uint8 = intDataType("uint8", 0, 255);
4
+ //# sourceMappingURL=uint8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint8.js","sourceRoot":"","sources":["../../src/data-type/uint8.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,kCAAkC;AAClC,MAAM,CAAC,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -7,9 +7,9 @@
7
7
  */
8
8
  export type { JSONValue, ZarrV3MetadataFieldJSON, ZarrV3NamedConfigJSON } from "./common.js";
9
9
  export { flattenTree, formatTree, isEmptyTree, MetadataValidationError, treeOf, type ErrorTree, type Issue, type IssueKind, type IssuePath, type ParseResult, type PathedIssue, } from "./errors.js";
10
- export type { ChunkGridVerdict, RectilinearChunkGridConfiguration, RectilinearDimSpec, RegularChunkGridConfiguration, } from "./chunk-grids.js";
11
- export type { ShardingIndexedCodecConfiguration, TransposeCodecConfiguration, } from "./codecs.js";
12
- export type { ComplexFillValue, FloatFillValue } from "./data-types.js";
10
+ export type { ChunkGridVerdict, RectilinearChunkGridConfiguration, RectilinearDimSpec, RegularChunkGridConfiguration, } from "./chunk-grid/index.js";
11
+ export type { ShardingIndexedCodecConfiguration, TransposeCodecConfiguration, } from "./codec/index.js";
12
+ export type { BytesFillValue, ComplexFillValue, FloatFillValue, NumpyDatetime64Configuration, NumpyDatetime64FillValue, NumpyTimeUnit, RawBytesFillValue, StringFillValue, StructConfiguration, StructField, } from "./data-type/index.js";
13
13
  export * from "./schemas.js";
14
14
  export * from "./semantics.js";
15
15
  export type { StandardSchemaV1 } from "./standard-schema.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,SAAS,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,uBAAuB,EACvB,MAAM,EACN,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,gBAAgB,EAChB,iCAAiC,EACjC,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,iCAAiC,EACjC,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACxE,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,SAAS,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,uBAAuB,EACvB,MAAM,EACN,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,gBAAgB,EAChB,iCAAiC,EACjC,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,iCAAiC,EACjC,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,4BAA4B,EAC5B,wBAAwB,EACxB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,uBAAuB,EACvB,MAAM,GAOP,MAAM,aAAa,CAAC;AAYrB,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,WAAW,EACX,UAAU,EACV,WAAW,EACX,uBAAuB,EACvB,MAAM,GAOP,MAAM,aAAa,CAAC;AAuBrB,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC"}
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Semantic (cross-field) validation for v3 array metadata: the
3
3
  * orchestrator. The rules themselves live with their content —
4
- * `chunk-grids.ts`, `codecs.ts`, and `data-types.ts` each hold the syntax
5
- * (types) and semantics (procedures) for the names this package
6
- * interprets, mirroring how the spec, the Python reference's type layout,
7
- * and the zarr-extensions registry are organized. This module only walks
4
+ * `chunk-grid/`, `codec/`, and `data-type/` hold one module per
5
+ * interpreted name (grids, codecs, data types), each with its syntax
6
+ * (types) and semantics (procedures), mirroring how the spec, the Python
7
+ * reference's type layout, and the zarr-extensions registry are organized. This module only walks
8
8
  * documents: extract shape, ask each content module for its verdicts,
9
9
  * thread the chunk-size context into codec pipelines, and descend into a
10
10
  * group's inline consolidated entries.
@@ -1 +1 @@
1
- {"version":3,"file":"semantics.d.ts","sourceRoot":"","sources":["../src/semantics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAU,KAAK,SAAS,EAAoB,MAAM,aAAa,CAAC;AA4BvE;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAElE;AA0BD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAE7D"}
1
+ {"version":3,"file":"semantics.d.ts","sourceRoot":"","sources":["../src/semantics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAU,KAAK,SAAS,EAAoB,MAAM,aAAa,CAAC;AAsBvE;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAElE;AA0BD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAE7D"}
package/dist/semantics.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Semantic (cross-field) validation for v3 array metadata: the
3
3
  * orchestrator. The rules themselves live with their content —
4
- * `chunk-grids.ts`, `codecs.ts`, and `data-types.ts` each hold the syntax
5
- * (types) and semantics (procedures) for the names this package
6
- * interprets, mirroring how the spec, the Python reference's type layout,
7
- * and the zarr-extensions registry are organized. This module only walks
4
+ * `chunk-grid/`, `codec/`, and `data-type/` hold one module per
5
+ * interpreted name (grids, codecs, data types), each with its syntax
6
+ * (types) and semantics (procedures), mirroring how the spec, the Python
7
+ * reference's type layout, and the zarr-extensions registry are organized. This module only walks
8
8
  * documents: extract shape, ask each content module for its verdicts,
9
9
  * thread the chunk-size context into codec pipelines, and descend into a
10
10
  * group's inline consolidated entries.
@@ -17,11 +17,11 @@
17
17
  * content-agnostic and corpus-governed; it never reads the content
18
18
  * modules.
19
19
  */
20
- import { chunkGridVerdict } from "./chunk-grids.js";
21
- import { pipelineIssues } from "./codecs.js";
22
- import { fillValueIssue } from "./data-types.js";
20
+ import { chunkGridVerdict } from "./chunk-grid/index.js";
21
+ import { pipelineIssues } from "./codec/index.js";
22
+ import { dataTypeVerdict } from "./data-type/index.js";
23
23
  import { treeOf } from "./errors.js";
24
- import { fieldParts, isIntArray, isPlainObject } from "./guards.js";
24
+ import { isIntArray, isPlainObject } from "./guards.js";
25
25
  function arraySemanticsIssues(value) {
26
26
  if (!isPlainObject(value) || value["node_type"] !== "array")
27
27
  return [];
@@ -29,13 +29,7 @@ function arraySemanticsIssues(value) {
29
29
  const shape = isIntArray(value["shape"]) ? value["shape"] : undefined;
30
30
  const grid = chunkGridVerdict(value["chunk_grid"], shape);
31
31
  issues.push(...grid.issues.map((issue) => ({ ...issue, path: ["chunk_grid", ...issue.path] })));
32
- const dataType = fieldParts(value["data_type"]);
33
- if (dataType !== undefined && "fill_value" in value) {
34
- const message = fillValueIssue(dataType.name, value["fill_value"]);
35
- if (message !== undefined) {
36
- issues.push({ path: ["fill_value"], message, kind: "invalid_value" });
37
- }
38
- }
32
+ issues.push(...dataTypeVerdict(value["data_type"], "fill_value" in value, value["fill_value"]));
39
33
  const codecs = value["codecs"];
40
34
  if (Array.isArray(codecs)) {
41
35
  issues.push(...pipelineIssues(codecs, ["codecs"], shape?.length, grid.chunkSizes));
@@ -1 +1 @@
1
- {"version":3,"file":"semantics.js","sourceRoot":"","sources":["../src/semantics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"semantics.js","sourceRoot":"","sources":["../src/semantics.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zarr-metadata",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Spec-defined metadata types and validators for Zarr v2 and v3.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,7 +34,8 @@
34
34
  "clean": "rm -rf dist",
35
35
  "prepack": "npm run clean && npm run build",
36
36
  "test": "vitest run",
37
- "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json"
37
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
38
+ "docs": "typedoc"
38
39
  },
39
40
  "keywords": [
40
41
  "zarr",
@@ -45,6 +46,7 @@
45
46
  "@changesets/cli": "^3.0.1",
46
47
  "@standard-schema/spec": "^1.1.0",
47
48
  "@types/node": "^26.4.0",
49
+ "typedoc": "^0.28.20",
48
50
  "typescript": "^5.6.0",
49
51
  "vitest": "^3.0.0"
50
52
  }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The chunk grids this package interprets, one module per grid, assembled
3
+ * into the dispatch the semantic layer uses. The structural document layer
4
+ * never reads these modules — extension points are uninterpreted there by
5
+ * spec design.
6
+ */
7
+ import type { PathedIssue } from "../errors.js";
8
+ import { fieldParts, isPlainObject } from "../guards.js";
9
+ import { regularIssues } from "./regular.js";
10
+ import { rectilinearIssues } from "./rectilinear.js";
11
+
12
+ export type { RegularChunkGridConfiguration } from "./regular.js";
13
+ export type { RectilinearChunkGridConfiguration, RectilinearDimSpec } from "./rectilinear.js";
14
+
15
+ /** What interpreting a chunk grid yields for the rest of the semantic layer. */
16
+ export interface ChunkGridVerdict {
17
+ /** Issues, pathed relative to the `chunk_grid` field. */
18
+ issues: PathedIssue[];
19
+ /**
20
+ * Distinct chunk lengths per dimension — the division context a
21
+ * sharding codec's inner chunks must satisfy — when derivable.
22
+ */
23
+ chunkSizes: number[][] | undefined;
24
+ }
25
+
26
+ /**
27
+ * Interpret a document's `chunk_grid` field: required members, cross-field
28
+ * rules against `shape`, and the division context for codec pipelines.
29
+ * Unrecognized grid names yield no issues and no context — the extension
30
+ * name space is open.
31
+ */
32
+ export function chunkGridVerdict(rawGrid: unknown, shape: number[] | undefined): ChunkGridVerdict {
33
+ if (!isPlainObject(rawGrid) && typeof rawGrid !== "string") {
34
+ return { issues: [], chunkSizes: undefined }; // structural layer's problem
35
+ }
36
+ const name = fieldParts(rawGrid)?.name;
37
+ if (name === "regular") return regularIssues(rawGrid, shape);
38
+ if (name === "rectilinear") return rectilinearIssues(rawGrid, shape);
39
+ return { issues: [], chunkSizes: undefined };
40
+ }
@@ -1,17 +1,7 @@
1
- /**
2
- * The chunk grids this package interprets: syntax (configuration types) and
3
- * semantics (the spec's prose rules) for `regular` and `rectilinear`, in
4
- * one place per grid. The structural document layer never reads this
5
- * module — extension points are uninterpreted there by spec design.
6
- */
7
-
8
- import type { PathedIssue } from "./errors.js";
9
- import { configurationMissing, fieldParts, isIntArray, isPlainObject } from "./guards.js";
10
-
11
- /** Configuration of the core `regular` chunk grid. */
12
- export interface RegularChunkGridConfiguration {
13
- chunk_shape: number[];
14
- }
1
+ /** The zarr-extensions `rectilinear` chunk grid: syntax and semantics. */
2
+ import type { PathedIssue } from "../errors.js";
3
+ import { configurationMissing, fieldParts, isIntArray } from "../guards.js";
4
+ import type { ChunkGridVerdict } from "./index.js";
15
5
 
16
6
  /**
17
7
  * One dimension's spec in a rectilinear grid: a bare integer (uniform
@@ -26,51 +16,7 @@ export interface RectilinearChunkGridConfiguration {
26
16
  chunk_shapes: RectilinearDimSpec[];
27
17
  }
28
18
 
29
- /** What interpreting a chunk grid yields for the rest of the semantic layer. */
30
- export interface ChunkGridVerdict {
31
- /** Issues, pathed relative to the `chunk_grid` field. */
32
- issues: PathedIssue[];
33
- /**
34
- * Distinct chunk lengths per dimension — the division context a
35
- * sharding codec's inner chunks must satisfy — when derivable.
36
- */
37
- chunkSizes: number[][] | undefined;
38
- }
39
-
40
- function regularIssues(rawGrid: unknown, shape: number[] | undefined): ChunkGridVerdict {
41
- const issues: PathedIssue[] = [];
42
- let chunkSizes: number[][] | undefined;
43
- const configuration = fieldParts(rawGrid)?.configuration;
44
- if (configurationMissing(rawGrid)) {
45
- issues.push({
46
- path: [],
47
- message: '"regular" requires a configuration with "chunk_shape"',
48
- kind: "missing_key",
49
- });
50
- } else if (configuration !== undefined && !Object.hasOwn(configuration, "chunk_shape")) {
51
- issues.push({
52
- path: ["configuration", "chunk_shape"],
53
- message: "missing required key",
54
- kind: "missing_key",
55
- });
56
- }
57
- const configured = configuration?.["chunk_shape"];
58
- if (isIntArray(configured)) {
59
- if (shape !== undefined && configured.length !== shape.length) {
60
- issues.push({
61
- path: ["configuration", "chunk_shape"],
62
- message: `expected one length per dimension of shape (${shape.length})`,
63
- kind: "invalid_value",
64
- });
65
- // wrong arity: unusable as division context
66
- } else {
67
- chunkSizes = configured.map((length) => [length]);
68
- }
69
- }
70
- return { issues, chunkSizes };
71
- }
72
-
73
- function rectilinearIssues(rawGrid: unknown, shape: number[] | undefined): ChunkGridVerdict {
19
+ export function rectilinearIssues(rawGrid: unknown, shape: number[] | undefined): ChunkGridVerdict {
74
20
  const issues: PathedIssue[] = [];
75
21
  let chunkSizes: number[][] | undefined;
76
22
  const configuration = fieldParts(rawGrid)?.configuration;
@@ -140,19 +86,3 @@ function rectilinearIssues(rawGrid: unknown, shape: number[] | undefined): Chunk
140
86
  }
141
87
  return { issues, chunkSizes };
142
88
  }
143
-
144
- /**
145
- * Interpret a document's `chunk_grid` field: required members, cross-field
146
- * rules against `shape`, and the division context for codec pipelines.
147
- * Unrecognized grid names yield no issues and no context — the extension
148
- * name space is open.
149
- */
150
- export function chunkGridVerdict(rawGrid: unknown, shape: number[] | undefined): ChunkGridVerdict {
151
- if (!isPlainObject(rawGrid) && typeof rawGrid !== "string") {
152
- return { issues: [], chunkSizes: undefined }; // structural layer's problem
153
- }
154
- const name = fieldParts(rawGrid)?.name;
155
- if (name === "regular") return regularIssues(rawGrid, shape);
156
- if (name === "rectilinear") return rectilinearIssues(rawGrid, shape);
157
- return { issues: [], chunkSizes: undefined };
158
- }
@@ -0,0 +1,42 @@
1
+ /** The core `regular` chunk grid: syntax and semantics. */
2
+ import type { PathedIssue } from "../errors.js";
3
+ import { configurationMissing, fieldParts, isIntArray } from "../guards.js";
4
+ import type { ChunkGridVerdict } from "./index.js";
5
+
6
+ /** Configuration of the core `regular` chunk grid. */
7
+ export interface RegularChunkGridConfiguration {
8
+ chunk_shape: number[];
9
+ }
10
+
11
+ export function regularIssues(rawGrid: unknown, shape: number[] | undefined): ChunkGridVerdict {
12
+ const issues: PathedIssue[] = [];
13
+ let chunkSizes: number[][] | undefined;
14
+ const configuration = fieldParts(rawGrid)?.configuration;
15
+ if (configurationMissing(rawGrid)) {
16
+ issues.push({
17
+ path: [],
18
+ message: '"regular" requires a configuration with "chunk_shape"',
19
+ kind: "missing_key",
20
+ });
21
+ } else if (configuration !== undefined && !Object.hasOwn(configuration, "chunk_shape")) {
22
+ issues.push({
23
+ path: ["configuration", "chunk_shape"],
24
+ message: "missing required key",
25
+ kind: "missing_key",
26
+ });
27
+ }
28
+ const configured = configuration?.["chunk_shape"];
29
+ if (isIntArray(configured)) {
30
+ if (shape !== undefined && configured.length !== shape.length) {
31
+ issues.push({
32
+ path: ["configuration", "chunk_shape"],
33
+ message: `expected one length per dimension of shape (${shape.length})`,
34
+ kind: "invalid_value",
35
+ });
36
+ // wrong arity: unusable as division context
37
+ } else {
38
+ chunkSizes = configured.map((length) => [length]);
39
+ }
40
+ }
41
+ return { issues, chunkSizes };
42
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The codecs this package interprets, one module per codec, plus the
3
+ * pipeline walker that threads dimensional context between codecs
4
+ * (mirroring zarr-python's chunk-spec threading): a valid transpose
5
+ * permutes the per-dimension chunk sizes for the codecs after it, and any
6
+ * codec this package cannot reason about — `reshape` may change a chunk's
7
+ * rank, and unknown codecs may do anything — invalidates the dimensional
8
+ * context for the rest of the pipeline instead of letting stale
9
+ * array-level facts produce false verdicts.
10
+ *
11
+ * Other codecs' required fields (blosc, gzip, zstd, ...) are deliberately
12
+ * NOT known here: they are registry-schema facts enforced by schema-driven
13
+ * tooling, and a second hardcoded source of truth would drift.
14
+ */
15
+ import type { PathedIssue } from "../errors.js";
16
+ import { configurationMissing, fieldParts, type Path } from "../guards.js";
17
+ import { shardingIndexedIssues } from "./sharding-indexed.js";
18
+ import { transposeIssues } from "./transpose.js";
19
+
20
+ export type { ShardingIndexedCodecConfiguration } from "./sharding-indexed.js";
21
+ export type { TransposeCodecConfiguration } from "./transpose.js";
22
+
23
+ /** The dimensional facts threaded between the codecs of one pipeline. */
24
+ export interface PipelineContext {
25
+ /** Array dimensionality at this point; undefined when unknowable. */
26
+ dims: number | undefined;
27
+ /**
28
+ * Distinct chunk lengths per dimension this pipeline may encode — what a
29
+ * sharding codec's inner chunks must divide. A regular grid contributes
30
+ * one size per dimension; a rectilinear grid may contribute several.
31
+ */
32
+ chunkSizes: number[][] | undefined;
33
+ }
34
+
35
+ /** The spent/unknowable context. */
36
+ export const DROPPED: PipelineContext = { dims: undefined, chunkSizes: undefined };
37
+
38
+ /** Walk one codec pipeline, threading the dimensional context. */
39
+ export function pipelineIssues(
40
+ pipeline: unknown[],
41
+ path: Path,
42
+ initialDims: number | undefined,
43
+ initialChunkSizes: number[][] | undefined,
44
+ ): PathedIssue[] {
45
+ const issues: PathedIssue[] = [];
46
+ let context: PipelineContext = { dims: initialDims, chunkSizes: initialChunkSizes };
47
+ pipeline.forEach((entry, index) => {
48
+ const parts = fieldParts(entry);
49
+ if (parts === undefined) {
50
+ context = DROPPED; // structurally invalid entry: no further reasoning
51
+ return;
52
+ }
53
+ const configMissing = configurationMissing(entry);
54
+ if (parts.name === "transpose") {
55
+ const result = transposeIssues(parts.configuration, configMissing, path, index, context);
56
+ issues.push(...result.issues);
57
+ context = result.context;
58
+ } else if (parts.name === "sharding_indexed") {
59
+ const result = shardingIndexedIssues(
60
+ parts.configuration,
61
+ configMissing,
62
+ path,
63
+ index,
64
+ context,
65
+ pipelineIssues,
66
+ );
67
+ issues.push(...result.issues);
68
+ context = result.context;
69
+ } else {
70
+ // A codec this package cannot reason about: stale array-level facts
71
+ // must not judge the codecs after it.
72
+ context = DROPPED;
73
+ }
74
+ });
75
+ return issues;
76
+ }
@@ -0,0 +1,113 @@
1
+ /** The core `sharding_indexed` codec: syntax and semantics. */
2
+ import type { PathedIssue } from "../errors.js";
3
+ import { isIntArray, type Path } from "../guards.js";
4
+ import { DROPPED, type PipelineContext } from "./index.js";
5
+
6
+ /** Configuration of the core `sharding_indexed` codec. */
7
+ export interface ShardingIndexedCodecConfiguration {
8
+ chunk_shape: number[];
9
+ codecs: unknown[];
10
+ index_codecs: unknown[];
11
+ index_location?: "start" | "end";
12
+ }
13
+
14
+ type Walk = (
15
+ pipeline: unknown[],
16
+ path: Path,
17
+ dims: number | undefined,
18
+ chunkSizes: number[][] | undefined,
19
+ ) => PathedIssue[];
20
+
21
+ /**
22
+ * Judge one sharding entry: it requires `chunk_shape`, `codecs`, and
23
+ * `index_codecs`; its chunk_shape must match the array's dimensionality
24
+ * and evenly divide every chunk it shards. The inner pipeline is walked
25
+ * with the shard's own chunk context (`index_codecs` encode the shard
26
+ * index, whose shape differs — no dimensional context applies there), and
27
+ * the array -> bytes boundary spends the context for whatever follows.
28
+ */
29
+ export function shardingIndexedIssues(
30
+ configuration: Record<string, unknown> | undefined,
31
+ configMissing: boolean,
32
+ path: Path,
33
+ index: number,
34
+ context: PipelineContext,
35
+ walk: Walk,
36
+ ): { issues: PathedIssue[]; context: PipelineContext } {
37
+ const issues: PathedIssue[] = [];
38
+ if (configMissing) {
39
+ issues.push({
40
+ path: [...path, index],
41
+ message:
42
+ '"sharding_indexed" requires a configuration with "chunk_shape", "codecs", and "index_codecs"',
43
+ kind: "missing_key",
44
+ });
45
+ return { issues, context: DROPPED };
46
+ }
47
+ if (configuration !== undefined) {
48
+ for (const key of ["chunk_shape", "codecs", "index_codecs"]) {
49
+ if (!Object.hasOwn(configuration, key)) {
50
+ issues.push({
51
+ path: [...path, index, "configuration", key],
52
+ message: "missing required key",
53
+ kind: "missing_key",
54
+ });
55
+ }
56
+ }
57
+ }
58
+ const chunkShape = configuration?.["chunk_shape"];
59
+ if (!isIntArray(chunkShape)) {
60
+ // Still walk a present inner pipeline (entries deserve their own
61
+ // verdicts) before the context becomes unknowable.
62
+ const inner = configuration?.["codecs"];
63
+ if (Array.isArray(inner)) {
64
+ issues.push(
65
+ ...walk(inner, [...path, index, "configuration", "codecs"], undefined, undefined),
66
+ );
67
+ }
68
+ return { issues, context: DROPPED };
69
+ }
70
+ const chunkShapePath = [...path, index, "configuration", "chunk_shape"];
71
+ if (context.dims !== undefined && chunkShape.length !== context.dims) {
72
+ issues.push({
73
+ path: chunkShapePath,
74
+ message: `expected one length per array dimension (${context.dims})`,
75
+ kind: "invalid_value",
76
+ });
77
+ } else if (
78
+ context.chunkSizes !== undefined &&
79
+ chunkShape.length === context.chunkSizes.length &&
80
+ chunkShape.every((length) => length > 0)
81
+ ) {
82
+ let violation: { axis: number; size: number } | undefined;
83
+ context.chunkSizes.forEach((sizes, axis) => {
84
+ if (violation !== undefined) return;
85
+ const bad = sizes.find((size) => size % (chunkShape[axis] as number) !== 0);
86
+ if (bad !== undefined) violation = { axis, size: bad };
87
+ });
88
+ if (violation !== undefined) {
89
+ const { axis, size } = violation;
90
+ const sizesNow = context.chunkSizes;
91
+ const uniform = sizesNow.every((sizes) => sizes.length === 1);
92
+ issues.push({
93
+ path: chunkShapePath,
94
+ message: uniform
95
+ ? `expected ${JSON.stringify(chunkShape)} to evenly divide the outer chunk shape ${JSON.stringify(sizesNow.map((sizes) => sizes[0]))}`
96
+ : `expected ${JSON.stringify(chunkShape)} to evenly divide every chunk size of the grid (dimension ${axis} has chunk size ${size})`,
97
+ kind: "invalid_value",
98
+ });
99
+ }
100
+ }
101
+ const inner = configuration?.["codecs"];
102
+ if (Array.isArray(inner)) {
103
+ issues.push(
104
+ ...walk(
105
+ inner,
106
+ [...path, index, "configuration", "codecs"],
107
+ chunkShape.length,
108
+ chunkShape.map((length) => [length]),
109
+ ),
110
+ );
111
+ }
112
+ return { issues, context: DROPPED };
113
+ }