@botejs/core 0.6.0 → 0.8.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.
package/README.md CHANGED
@@ -7,22 +7,15 @@ npm install @botejs/core
7
7
  ```
8
8
 
9
9
  ```ts
10
- // node examples/citylots.js
11
- import { join } from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
12
11
  import { open, fromFile } from '@botejs/core';
13
12
 
14
13
  // 181 MB GeoJSON:
15
14
  // { type: "...", features: [{ properties: { STREET: "..." }}] }
16
- const filePath = join(import.meta.dirname, 'citylots.json');
15
+ const filePath = fileURLToPath(new URL('../citylots.json', import.meta.url));
17
16
 
18
17
  await using cursor = await open(fromFile(filePath));
19
18
 
20
- console.log(`type: ${await cursor.get('type')}`);
21
- // type: 'FeatureCollection'
22
-
23
- console.log(`features: ${await cursor.count('features')}`);
24
- // features: 206_560
25
-
26
19
  const byStreet = await cursor
27
20
  .iter('features', {
28
21
  select: ['properties', 'STREET'],
@@ -35,21 +28,34 @@ const byStreet = await cursor
35
28
  }, new Map());
36
29
 
37
30
  console.log([...byStreet].sort((a, b) => b[1] - a[1]).slice(0, 10));
38
- // [[ 'UNKNOWN', 2843 ], [ 'MASON', 2651 ], [ 'PINE', 1799 ], ... ]
39
31
  ```
40
32
 
41
- Given a **seekable** source (e.g. a file, an HTTP range) or "forward-only" source (e.g. HTTP GET request) and a path, it retrieves values out of a JSON, without loading the whole thing in-memory.
33
+ Given a **seekable** or **forward** source and a path, it retrieves values out of a JSON, without loading the whole thing in-memory.
34
+
35
+ Here's a run (Apple M1 Pro 2021, default settings, RUNS=100):
36
+
37
+ | method | mean time (seconds) | mean peak footprint (MB) |
38
+ | ------------------ | ----------------- | ------------------------ |
39
+ | bote | 0.517 ± 0.018 s | 40.3 ± 2.5 |
40
+ | JSON.parse | 0.816 ± 0.031 s | 648.9 ± 2.4 |
41
+ | JSONStream | 4.452 ± 0.052 s | 57.9 ± 3.9 |
42
+ | @streamparser/json | 5.103 ± 0.084 s | 47.9 ± 2.3 |
43
+ | oboe.js | 8.566 ± 0.295 s | 100.0 ± 4.6 |
44
+ | stream-json | 13.346 ± 0.569 s | 207.6 ± 8.4 |
45
+
46
+ For comparison notes, go [here](https://github.com/jankdc/bote-comparison).
47
+
48
+ ## Features
49
+
50
+ * Modern `AsyncIterator` API with helpers that emulate the [tc39 ones](https://github.com/tc39/proposal-async-iterator-helpers)
51
+ * Validate with [Standard Schema](https://standardschema.dev/), avoiding those pesky `unknown`s
52
+ * Supports multiple sources of data (e.g. file, network, stream) or write a custom one (see [example](./examples/))
53
+ * For forward-only sources, there's support for replaying/buffering, allowing navigation to previous values
42
54
 
43
- Here's a comparison of running above (using Apple M1 Pro 2021's `/usr/bin/time -l`):
55
+ ## Documentation
44
56
 
45
- | method | mean time | mean peak footprint (MB) |
46
- | ------------------ | --------- | ------------------------ |
47
- | JSON.parse | 0.81 s | 647.0 |
48
- | bote | 1.062 s | 89.0 |
49
- | @streamparser/json | 4.363 s | 98.7 |
50
- | JSONStream | 4.417 s | 60.7 |
51
- | oboe.js | 9.649 s | 102.6 |
52
- | stream-json | 18.693 s | 184.3 |
57
+ Coming soon. Check the [./examples](./examples/) folder for usages. I've also heavily JSDoc'ed the hell out of the API so have fun
58
+ playing around with it for now.
53
59
 
54
60
  ## Status
55
61
 
package/dist/cursor.d.ts CHANGED
@@ -43,13 +43,6 @@ export interface Cursor {
43
43
  */
44
44
  get(...path: Segment[]): Promise<unknown>;
45
45
  get<Sch extends StandardSchemaV1>(...args: [...Segment[], Sch]): Promise<InferOutput<Sch>>;
46
- /**
47
- * Count the members of the array or object at `path`.
48
- *
49
- * @example
50
- * const total = await root.count('users');
51
- */
52
- count(...path: Segment[]): Promise<number>;
53
46
  /**
54
47
  * Stream the members of the array or object at `path` as an async iterable.
55
48
  * A trailing Standard Schema validates each item; a trailing {@link IterOptions}
package/dist/cursor.js CHANGED
@@ -43,11 +43,6 @@ export function wrap(native, state) {
43
43
  }
44
44
  return runStandardSchema(schema, value, path);
45
45
  },
46
- async count(...path) {
47
- ensureOpen(state);
48
- validatePath(path);
49
- return withPath(path, () => native.count(path));
50
- },
51
46
  iter(...args) {
52
47
  ensureOpen(state);
53
48
  const { path, tail } = splitArgs(args);
package/dist/index.d.ts CHANGED
@@ -7,4 +7,4 @@ export { type Source, type Reader, type ReadResult, type ForwardSource, type Fac
7
7
  export { fromFile, fromBuffer, fromHttpRange, type HttpRangeOptions } from './source/seekable.ts';
8
8
  export { fromReadable, fromHttpRequest, type ReadableOptions, type ReadableProducer, type HttpRequestOptions, } from './source/forward.ts';
9
9
  export { type IterStream } from './stream.ts';
10
- export { open, type OpenOptions, type ForwardOpenOptions } from './open.ts';
10
+ export { open, type SeekableOpenOptions } from './open.ts';
package/dist/open.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type RootCursor } from './cursor.ts';
2
2
  import type { SeekableSource, ForwardSource } from './source/base.ts';
3
3
  export declare const DEFAULT_SOURCE_CHUNK_BYTES: number;
4
- export interface OpenOptions {
4
+ export interface SeekableOpenOptions {
5
5
  /**
6
6
  * How much of the index that speeds up repeat lookups to keep in memory,
7
7
  * measured in entries. Higher means faster repeat queries but more memory;
@@ -24,14 +24,6 @@ export interface OpenOptions {
24
24
  */
25
25
  arrayIndexInterval?: number;
26
26
  }
27
- /**
28
- * Options for a forward source: every cache knob is forbidden (the structural-index
29
- * cache is forced off). `Omit` would collapse to `{}` and silently permit them, so
30
- * the knobs are mapped to `never` to reject them at compile time.
31
- */
32
- export type ForwardOpenOptions = {
33
- [K in keyof OpenOptions]?: never;
34
- };
35
27
  /**
36
28
  * Open a cursor over a source.
37
29
  *
@@ -43,5 +35,5 @@ export type ForwardOpenOptions = {
43
35
  * The returned `RootCursor` owns the reader: `close()` (or `await using`) drives
44
36
  * the reader's own `close()` exactly once.
45
37
  */
46
- export declare function open(source: SeekableSource, options?: OpenOptions): Promise<RootCursor>;
47
- export declare function open(source: ForwardSource, options?: ForwardOpenOptions): Promise<RootCursor>;
38
+ export declare function open(source: SeekableSource, options?: SeekableOpenOptions): Promise<RootCursor>;
39
+ export declare function open(source: ForwardSource): Promise<RootCursor>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botejs/core",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -36,7 +36,7 @@
36
36
  "prepublishOnly": "cp ../../README.md ./README.md && tsc"
37
37
  },
38
38
  "dependencies": {
39
- "@botejs/native": "^0.6.0"
39
+ "@botejs/native": "^0.7.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^22.0.0",