@cloudbitmaps/core 0.21.0 → 0.22.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 (72) hide show
  1. package/README.md +16 -5
  2. package/dist/{chunk-IGLIZBR7.js → chunk-OSU7W2Y3.js} +74 -30
  3. package/dist/chunk-OSU7W2Y3.js.map +7 -0
  4. package/dist/core/bit-route.d.ts +7 -0
  5. package/dist/core/codec.d.ts +1 -1
  6. package/dist/core/combine-expr.d.ts +9 -5
  7. package/dist/core/combine-feed.d.ts +11 -3
  8. package/dist/core/combine-many.d.ts +17 -13
  9. package/dist/core/determinism.d.ts +2 -1
  10. package/dist/core/erase-id.d.ts +18 -8
  11. package/dist/core/erasure.d.ts +1 -1
  12. package/dist/core/errors.d.ts +53 -9
  13. package/dist/core/load.d.ts +48 -14
  14. package/dist/core/metrics.d.ts +1 -1
  15. package/dist/core/ports.d.ts +7 -6
  16. package/dist/core/registry-scan.d.ts +0 -5
  17. package/dist/core/retention-sweep.d.ts +1 -1
  18. package/dist/core/retention.d.ts +1 -1
  19. package/dist/core/retry.d.ts +4 -0
  20. package/dist/core/rollback.d.ts +1 -0
  21. package/dist/driver-kit.d.ts +7 -2
  22. package/dist/driver-kit.js +5 -10
  23. package/dist/driver-kit.js.map +1 -1
  24. package/dist/drivers/backends.d.ts +2 -0
  25. package/dist/drivers/crypto.d.ts +1 -1
  26. package/dist/export/index.d.ts +9 -8
  27. package/dist/index.d.ts +11 -10
  28. package/dist/index.js +766 -634
  29. package/dist/index.js.map +4 -4
  30. package/package.json +7 -2
  31. package/dist/chunk-IGLIZBR7.js.map +0 -7
  32. package/dist/core/absent-operands.d.ts +0 -8
  33. package/dist/core/bulk-load.d.ts +0 -148
  34. package/dist/core/cas-retry.d.ts +0 -27
  35. package/dist/core/check.d.ts +0 -22
  36. package/dist/core/chunk-checks.d.ts +0 -39
  37. package/dist/core/chunk-stream.d.ts +0 -22
  38. package/dist/core/chunk-window.d.ts +0 -37
  39. package/dist/core/combine-ledger.d.ts +0 -43
  40. package/dist/core/crbm/crc32c.d.ts +0 -10
  41. package/dist/core/crbm/fingerprint.d.ts +0 -23
  42. package/dist/core/crbm/format.d.ts +0 -150
  43. package/dist/core/crbm/frame.d.ts +0 -10
  44. package/dist/core/crbm/plan-reads.d.ts +0 -50
  45. package/dist/core/crbm/varint.d.ts +0 -14
  46. package/dist/core/crbm/writer.d.ts +0 -72
  47. package/dist/core/crbm-open.d.ts +0 -154
  48. package/dist/core/crbm-write.d.ts +0 -75
  49. package/dist/core/due-index.d.ts +0 -53
  50. package/dist/core/generation-gc.d.ts +0 -293
  51. package/dist/core/generation-list.d.ts +0 -11
  52. package/dist/core/id-window.d.ts +0 -46
  53. package/dist/core/invalidation-scope.d.ts +0 -77
  54. package/dist/core/item-pull.d.ts +0 -29
  55. package/dist/core/known-generations-shape.d.ts +0 -13
  56. package/dist/core/known-generations.d.ts +0 -147
  57. package/dist/core/ledger-seed.d.ts +0 -17
  58. package/dist/core/metadata.d.ts +0 -42
  59. package/dist/core/order.d.ts +0 -2
  60. package/dist/core/publish.d.ts +0 -207
  61. package/dist/core/reader-defaults.d.ts +0 -29
  62. package/dist/core/summary.d.ts +0 -110
  63. package/dist/core/token.d.ts +0 -41
  64. package/dist/drivers/_shared/entropy.d.ts +0 -5
  65. package/dist/drivers/_shared/registry.d.ts +0 -107
  66. package/dist/drivers/localfs/exact-case.d.ts +0 -34
  67. package/dist/drivers/localfs/fs-util.d.ts +0 -55
  68. package/dist/drivers/localfs/paths.d.ts +0 -40
  69. package/dist/drivers/localfs/registry.d.ts +0 -50
  70. package/dist/drivers/localfs/storage.d.ts +0 -28
  71. package/dist/drivers/memory.d.ts +0 -64
  72. package/dist/testing/fuzz-core.d.ts +0 -15
package/README.md CHANGED
@@ -7,9 +7,18 @@ when you install the two packages you want. Install those instead:
7
7
  pnpm add @cloudbitmaps/roaring @cloudbitmaps/s3 # the store, and the storage you have (or /gcs, or /azure-blob)
8
8
  ```
9
9
 
10
- On npm 12 and pnpm 10 and later, allow `roaring`'s one install script first, or the install exits 0 and the package throws at `import`. Put this in your `package.json`: `{ "allowScripts": { "roaring": true }, "pnpm": { "onlyBuiltDependencies": ["roaring"] } }`. npm 11 runs the script but warns until you allow it the same way; pnpm 9 needs nothing extra. [Details](https://github.com/cloudbitmaps/cloudbitmaps/blob/main/docs/guide/getting-started.md#cannot-find-module-buildreleaseroaringnode-after-a-successful-install).
10
+ `roaring` needs its one install script to fetch its native binary, and newer clients run a dependency's script only if you allow it. Allow it before you install:
11
11
 
12
- Depend on `@cloudbitmaps/core` directly only to write a flavor or a driver.
12
+ - **npm 12:** add `{ "allowScripts": { "roaring": true } }` to your `package.json`. Without it the install exits 0 and the package throws at `import`. npm 11 runs the script but warns until you allow it the same way.
13
+ - **pnpm 11 and later:** put `allowBuilds: { roaring: true }` in a `pnpm-workspace.yaml` beside your `package.json`. Those versions no longer read the `package.json` `pnpm` key. Without it the install exits 1 with `ERR_PNPM_IGNORED_BUILDS`.
14
+ - **pnpm 10:** add `{ "pnpm": { "onlyBuiltDependencies": ["roaring"] } }` to your `package.json`. Without it the install exits 0 and the package throws at `import`.
15
+ - **pnpm 9:** nothing extra.
16
+
17
+ [Details](https://github.com/cloudbitmaps/cloudbitmaps/blob/main/docs/guide/getting-started.md#cannot-find-module-buildreleaseroaringnode-after-a-successful-install).
18
+
19
+ Depend on `@cloudbitmaps/core` directly only to write a driver, through `@cloudbitmaps/core/driver-kit`.
20
+
21
+ > **The main entry of this package is internal.** It is the engine `@cloudbitmaps/roaring` and the driver packages are built on, and it is outside the stability promise: it can change in any minor release, and a change to it gets no CHANGELOG Breaking entry. Install `@cloudbitmaps/roaring` and a driver. The public entry here is `@cloudbitmaps/core/driver-kit`, the contract for writing a driver.
13
22
 
14
23
  > **ESM-only, Node ≥ 22.12.** Use `import`; for `require()`, Jest and TypeScript, see
15
24
  > [CommonJS, Jest and TypeScript](https://github.com/cloudbitmaps/cloudbitmaps/blob/main/docs/guide/getting-started.md#commonjs-jest-and-typescript).
@@ -24,9 +33,11 @@ and crypto-shred, erasure by rewrite, retention, and the in-memory and local-fil
24
33
  dependencies and no cloud SDK**. The cloud backends are their own packages, built against
25
34
  `@cloudbitmaps/core/driver-kit`, the declared contract a driver depends on. A third-party driver can use it too.
26
35
 
27
- Its main entry is the flavor-author kit: the read engine, the standalone forms of the store's methods (`loadSegment`,
28
- `dropSegment`, `retireExpired` and the rest), and the retry and budget internals. `@cloudbitmaps/roaring` re-exports,
29
- by name, what an application uses.
36
+ Its main entry is the internal engine (the read engine, the standalone forms of the store's methods, and the retry and
37
+ budget internals) that `@cloudbitmaps/roaring` and the driver packages import; it is not a public API. What an
38
+ application uses is re-exported, by name, from `@cloudbitmaps/roaring`. The driver contracts (the storage and registry
39
+ ports, the registry's record types, the read-source and keystore ports) are exported by `@cloudbitmaps/core/driver-kit`
40
+ alone, which is complete: every type its signatures name is exported there too.
30
41
 
31
42
  ## How the storage path is laid out
32
43
 
@@ -3,7 +3,7 @@ var ERROR_BRAND = /* @__PURE__ */ Symbol.for("cloudbitmaps.error");
3
3
  var TRANSIENT_BRAND = /* @__PURE__ */ Symbol.for("cloudbitmaps.error.transient");
4
4
  var NAMES = /* @__PURE__ */ new WeakMap();
5
5
  var CloudRoaringError = class extends Error {
6
- /** Cross-bundle brand — see the predicates ({@link isCloudRoaringError}, …). Non-enumerable-ish (symbol key ⇒ not in JSON). */
6
+ /** Cross-bundle brand — see {@link errorKind}. Non-enumerable-ish (symbol key ⇒ not in JSON). */
7
7
  [ERROR_BRAND] = true;
8
8
  constructor(message) {
9
9
  super(message);
@@ -12,6 +12,7 @@ var CloudRoaringError = class extends Error {
12
12
  };
13
13
  var ValidationError = class extends CloudRoaringError {
14
14
  };
15
+ var CONTENTION_NEXT_STEP = "; another writer changed the segment's row while this call ran. Re-run the call: it reads the row afresh";
15
16
  var WriteConflictError = class extends CloudRoaringError {
16
17
  };
17
18
  var IntegrityError = class extends CloudRoaringError {
@@ -48,6 +49,21 @@ var UnsupportedError = class extends CloudRoaringError {
48
49
  var CapabilityError = class extends CloudRoaringError {
49
50
  };
50
51
  var BudgetExceededError = class extends CloudRoaringError {
52
+ /** The option to raise to let the call through. */
53
+ option;
54
+ /** The bound in force: requests, bytes or rows, by `option`. */
55
+ limit;
56
+ /**
57
+ * What the call had reached when refused. By `option`: the requests the call needs (`'budget.maxRequests'`), a
58
+ * lower bound on the resident bytes it needs (`'maxBufferedBytes'`), or `limit + 1` (`'maxScanSegments'`).
59
+ */
60
+ spent;
61
+ constructor(message, details) {
62
+ super(message);
63
+ this.option = details.option;
64
+ this.limit = details.limit;
65
+ this.spent = details.spent;
66
+ }
51
67
  };
52
68
  var KeyUnavailableError = class extends CloudRoaringError {
53
69
  };
@@ -84,15 +100,6 @@ function isWriteConflictError(err) {
84
100
  function isTransientError(err) {
85
101
  return hasBrand(err, TRANSIENT_BRAND);
86
102
  }
87
- function isLeaseExpiredError(err) {
88
- return isCloudRoaringError(err) && err.name === "LeaseExpiredError";
89
- }
90
- function isStaleOperandError(err) {
91
- return isCloudRoaringError(err) && err.name === "StaleOperandError";
92
- }
93
- function isLeaseLimitError(err) {
94
- return isCloudRoaringError(err) && err.name === "LeaseLimitError";
95
- }
96
103
  function isNotFoundError(err) {
97
104
  return isCloudRoaringError(err) && err.name === "NotFoundError";
98
105
  }
@@ -102,26 +109,56 @@ function isIntegrityError(err) {
102
109
  function isValidationError(err) {
103
110
  return isCloudRoaringError(err) && err.name === "ValidationError";
104
111
  }
105
- function isUnsupportedError(err) {
106
- return isCloudRoaringError(err) && err.name === "UnsupportedError";
107
- }
108
- function isCapabilityError(err) {
109
- return isCloudRoaringError(err) && err.name === "CapabilityError";
110
- }
111
- function isBudgetExceededError(err) {
112
- return isCloudRoaringError(err) && err.name === "BudgetExceededError";
113
- }
114
112
  function isKeyUnavailableError(err) {
115
113
  return isCloudRoaringError(err) && err.name === "KeyUnavailableError";
116
114
  }
115
+ var KIND_NAMES = {
116
+ CloudRoaringError: true,
117
+ ValidationError: true,
118
+ WriteConflictError: true,
119
+ IntegrityError: true,
120
+ NotFoundError: true,
121
+ UnsupportedError: true,
122
+ CapabilityError: true,
123
+ TransientError: true,
124
+ KeyUnavailableError: true,
125
+ BudgetExceededError: true,
126
+ LeaseExpiredError: true,
127
+ LeaseLimitError: true,
128
+ StaleOperandError: true
129
+ };
130
+ function errorKind(err) {
131
+ if (hasBrand(err, TRANSIENT_BRAND)) return "TransientError";
132
+ if (!hasBrand(err, ERROR_BRAND)) return void 0;
133
+ const name = err.name;
134
+ return typeof name === "string" && Object.hasOwn(KIND_NAMES, name) ? name : "CloudRoaringError";
135
+ }
117
136
 
118
137
  // src/core/bit-route.ts
119
138
  var U32_MAX = 4294967295;
120
139
  var CHUNK_COUNT = 65536;
121
140
  var LOW_16 = 65535;
141
+ var idErrors = /* @__PURE__ */ new WeakSet();
142
+ function isBadIdError(err) {
143
+ return err instanceof ValidationError && idErrors.has(err);
144
+ }
145
+ function badId(id) {
146
+ let got;
147
+ if (id === null) got = "null";
148
+ else if (id === void 0) got = "undefined";
149
+ else if (typeof id === "object") got = "an object";
150
+ else if (typeof id !== "number") got = `${/^[aeiou]/.test(typeof id) ? "an" : "a"} ${typeof id}`;
151
+ else if (!Number.isFinite(id)) got = "NaN or an infinity";
152
+ else if (id < 0) got = "a negative number";
153
+ else if (!Number.isInteger(id)) got = "a number with a fraction";
154
+ else got = `a number above ${U32_MAX} (ids are 32-bit)`;
155
+ const err = new ValidationError(`an id must be an integer from 0 to ${U32_MAX}; got ${got}`);
156
+ idErrors.add(err);
157
+ return err;
158
+ }
122
159
  function splitId(id) {
123
160
  if (!Number.isInteger(id) || id < 0 || id > U32_MAX) {
124
- throw new ValidationError(`an id must be an integer from 0 to ${U32_MAX}`);
161
+ throw badId(id);
125
162
  }
126
163
  return { chunkKey: id >>> 16, remainder: id & LOW_16 };
127
164
  }
@@ -322,7 +359,13 @@ function validatePart(value, field) {
322
359
  );
323
360
  }
324
361
  }
362
+ function requireRefObject(ref, hint = "") {
363
+ if (typeof ref !== "object" || ref === null) {
364
+ throw new ValidationError(`a segment ref is an object such as { segment: 'name' }${hint}`);
365
+ }
366
+ }
325
367
  function validateSegmentRef(ref) {
368
+ requireRefObject(ref);
326
369
  validatePart(ref.segment, "segment");
327
370
  if (ref.namespace !== void 0) validatePart(ref.namespace, "namespace");
328
371
  }
@@ -339,6 +382,7 @@ function validateUserNamespace(namespace) {
339
382
  }
340
383
  }
341
384
  function validateUserRef(ref) {
385
+ requireRefObject(ref, "; store.segment() takes the bare name");
342
386
  validatePart(ref.segment, "segment");
343
387
  if (ref.namespace !== void 0) validateUserNamespace(ref.namespace);
344
388
  }
@@ -657,7 +701,9 @@ async function takeLease(ref, deps, take) {
657
701
  }
658
702
  }
659
703
  if (unanswered !== void 0) throw unanswered;
660
- throw new WriteConflictError(`lease: contention taking a lease on segment "${ref.segment}"`);
704
+ throw new WriteConflictError(
705
+ `lease: contention taking a lease on segment "${ref.segment}"${CONTENTION_NEXT_STEP}`
706
+ );
661
707
  }
662
708
  async function releaseLease(ref, deps, holder) {
663
709
  let resends = 0;
@@ -691,7 +737,9 @@ async function releaseLease(ref, deps, holder) {
691
737
  }
692
738
  }
693
739
  if (unanswered !== void 0) throw unanswered;
694
- throw new WriteConflictError(`lease: contention releasing a lease on segment "${ref.segment}"`);
740
+ throw new WriteConflictError(
741
+ `lease: contention releasing a lease on segment "${ref.segment}"${CONTENTION_NEXT_STEP}`
742
+ );
695
743
  }
696
744
 
697
745
  // src/drivers/_shared/keys.ts
@@ -1752,6 +1800,7 @@ function entropyIsAvailable(entropy) {
1752
1800
  export {
1753
1801
  CloudRoaringError,
1754
1802
  ValidationError,
1803
+ CONTENTION_NEXT_STEP,
1755
1804
  WriteConflictError,
1756
1805
  IntegrityError,
1757
1806
  NotFoundError,
@@ -1763,24 +1812,19 @@ export {
1763
1812
  BudgetExceededError,
1764
1813
  KeyUnavailableError,
1765
1814
  TransientError,
1766
- isCloudRoaringError,
1767
1815
  isWriteConflictError,
1768
1816
  isTransientError,
1769
- isLeaseExpiredError,
1770
- isStaleOperandError,
1771
- isLeaseLimitError,
1772
1817
  isNotFoundError,
1773
1818
  isIntegrityError,
1774
1819
  isValidationError,
1775
- isUnsupportedError,
1776
- isCapabilityError,
1777
- isBudgetExceededError,
1778
1820
  isKeyUnavailableError,
1821
+ errorKind,
1779
1822
  requireInteger,
1780
1823
  requirePositiveInteger,
1781
1824
  requireFiniteNumber,
1782
1825
  U32_MAX,
1783
1826
  CHUNK_COUNT,
1827
+ isBadIdError,
1784
1828
  splitId,
1785
1829
  MAX_REMAINDER,
1786
1830
  joinId,
@@ -1879,4 +1923,4 @@ export {
1879
1923
  requirePositiveInt,
1880
1924
  requireBool
1881
1925
  };
1882
- //# sourceMappingURL=chunk-IGLIZBR7.js.map
1926
+ //# sourceMappingURL=chunk-OSU7W2Y3.js.map