@botejs/core 0.3.0 → 0.4.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/dist/args.js CHANGED
@@ -1,11 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.splitArgs = splitArgs;
4
- exports.isSchema = isSchema;
5
- exports.normalizeIterTail = normalizeIterTail;
6
- exports.serializeSelect = serializeSelect;
7
- const path_ts_1 = require("./path.js");
8
- function splitArgs(args) {
1
+ import { validatePath } from "./path.js";
2
+ export function splitArgs(args) {
9
3
  let pathArgs;
10
4
  let tail;
11
5
  if (args.length === 0) {
@@ -23,27 +17,27 @@ function splitArgs(args) {
23
17
  tail = undefined;
24
18
  }
25
19
  }
26
- (0, path_ts_1.validatePath)(pathArgs);
20
+ validatePath(pathArgs);
27
21
  return { path: pathArgs, tail };
28
22
  }
29
- function isSchema(value) {
23
+ export function isSchema(value) {
30
24
  return typeof value === 'object' && value !== null && '~standard' in value;
31
25
  }
32
- function normalizeIterTail(tail) {
26
+ export function normalizeIterTail(tail) {
33
27
  if (!tail)
34
28
  return {};
35
29
  if (isSchema(tail))
36
30
  return { schema: tail };
37
31
  return tail;
38
32
  }
39
- function serializeSelect(select) {
33
+ export function serializeSelect(select) {
40
34
  if (typeof select === 'string' || typeof select === 'number') {
41
35
  const one = [select];
42
- (0, path_ts_1.validatePath)(one);
36
+ validatePath(one);
43
37
  return JSON.stringify({ one });
44
38
  }
45
39
  if (Array.isArray(select)) {
46
- (0, path_ts_1.validatePath)(select);
40
+ validatePath(select);
47
41
  if (select.length === 0) {
48
42
  throw new RangeError('iter: select sub-path must have at least one segment');
49
43
  }
@@ -57,7 +51,7 @@ function serializeSelect(select) {
57
51
  if (!Array.isArray(path)) {
58
52
  throw new TypeError(`iter: select field ${JSON.stringify(k)} must be a segment or path, got ${describeSelect(sub)}`);
59
53
  }
60
- (0, path_ts_1.validatePath)(path);
54
+ validatePath(path);
61
55
  if (path.length === 0) {
62
56
  throw new RangeError(`iter: select field ${JSON.stringify(k)} sub-path must have at least one segment`);
63
57
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { type IterOptions } from './args.ts';
2
- export { ValidationError, PathError, formatPath, type Path, type Segment, type StandardSchemaV1, } from './validate.ts';
2
+ export { ValidationError, PathError, formatPath, type Path, type PathFaultCode, type Segment, type StandardSchemaV1, } from './validate.ts';
3
3
  export { open, DEFAULT_ITER_BATCH, MAX_ITER_BATCH, type Cursor, type RootCursor, type OpenOptions, type WalkEntry, type IterIndex as IterKey, } from './open.ts';
4
4
  export { fromBuffer, fromFile, fromHttpRange, type FactoryOptions, type Source, type SourceReader, type HttpRangeOptions, } from './sources.ts';
package/dist/index.js CHANGED
@@ -1,21 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fromHttpRange = exports.fromFile = exports.fromBuffer = exports.MAX_ITER_BATCH = exports.DEFAULT_ITER_BATCH = exports.formatPath = exports.PathError = exports.ValidationError = void 0;
4
- // Node 18 and Node 20.3 predate `Symbol.asyncDispose`; mirror what TS emits for
5
- // `await using` so the well-known symbol is available across our engine range.
6
- if (!Symbol.asyncDispose) {
7
- ;
8
- Symbol.asyncDispose = Symbol.for('Symbol.asyncDispose');
9
- }
10
- var validate_ts_1 = require("./validate.js");
11
- Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return validate_ts_1.ValidationError; } });
12
- Object.defineProperty(exports, "PathError", { enumerable: true, get: function () { return validate_ts_1.PathError; } });
13
- Object.defineProperty(exports, "formatPath", { enumerable: true, get: function () { return validate_ts_1.formatPath; } });
14
- var open_ts_1 = require("./open.js");
15
- Object.defineProperty(exports, "open", { enumerable: true, get: function () { return open_ts_1.open; } });
16
- Object.defineProperty(exports, "DEFAULT_ITER_BATCH", { enumerable: true, get: function () { return open_ts_1.DEFAULT_ITER_BATCH; } });
17
- Object.defineProperty(exports, "MAX_ITER_BATCH", { enumerable: true, get: function () { return open_ts_1.MAX_ITER_BATCH; } });
18
- var sources_ts_1 = require("./sources.js");
19
- Object.defineProperty(exports, "fromBuffer", { enumerable: true, get: function () { return sources_ts_1.fromBuffer; } });
20
- Object.defineProperty(exports, "fromFile", { enumerable: true, get: function () { return sources_ts_1.fromFile; } });
21
- Object.defineProperty(exports, "fromHttpRange", { enumerable: true, get: function () { return sources_ts_1.fromHttpRange; } });
1
+ export { ValidationError, PathError, formatPath, } from "./validate.js";
2
+ export { open, DEFAULT_ITER_BATCH, MAX_ITER_BATCH, } from "./open.js";
3
+ export { fromBuffer, fromFile, fromHttpRange, } from "./sources.js";
package/dist/open.js CHANGED
@@ -1,21 +1,17 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MAX_ITER_BATCH = exports.DEFAULT_ITER_BATCH = exports.DEFAULT_SOURCE_CHUNK_BYTES = void 0;
4
- exports.open = open;
5
- const native_1 = require("@botejs/native");
6
- const path_ts_1 = require("./path.js");
7
- const validate_ts_1 = require("./validate.js");
8
- const args_ts_1 = require("./args.js");
9
- exports.DEFAULT_SOURCE_CHUNK_BYTES = 64 * 1024;
10
- exports.DEFAULT_ITER_BATCH = 1000;
11
- exports.MAX_ITER_BATCH = 1_000_000;
1
+ import { open as openNative } from '@botejs/native';
2
+ import { validatePath } from "./path.js";
3
+ import { runStandardSchema, validateItem, formatPath, PathError, } from "./validate.js";
4
+ import { splitArgs, isSchema, serializeSelect, normalizeIterTail, } from "./args.js";
5
+ export const DEFAULT_SOURCE_CHUNK_BYTES = 64 * 1024;
6
+ export const DEFAULT_ITER_BATCH = 1000;
7
+ export const MAX_ITER_BATCH = 1_000_000;
12
8
  /**
13
9
  * Open a cursor over a seekable source.
14
10
  *
15
11
  * The returned `RootCursor` owns the reader: `close()` (or `await using`)
16
12
  * drives the reader's own `close()` exactly once.
17
13
  */
18
- async function open(source, options) {
14
+ export async function open(source, options) {
19
15
  const { indexCacheEntries, objectMemberCap, arrayIndexInterval } = options ?? {};
20
16
  for (const [name, value] of [
21
17
  ['indexCacheEntries', indexCacheEntries],
@@ -27,7 +23,7 @@ async function open(source, options) {
27
23
  }
28
24
  }
29
25
  const reader = await source.open();
30
- const chunkBytes = reader.chunkBytes ?? exports.DEFAULT_SOURCE_CHUNK_BYTES;
26
+ const chunkBytes = reader.chunkBytes ?? DEFAULT_SOURCE_CHUNK_BYTES;
31
27
  let native;
32
28
  try {
33
29
  if (!Number.isInteger(reader.size) || reader.size < 0) {
@@ -39,7 +35,7 @@ async function open(source, options) {
39
35
  if (chunkBytes % 64 !== 0) {
40
36
  throw new RangeError(`open: chunkBytes must be a multiple of 64, got ${chunkBytes}`);
41
37
  }
42
- native = (0, native_1.open)({
38
+ native = openNative({
43
39
  size: reader.size,
44
40
  chunkBytes,
45
41
  indexCacheEntries,
@@ -75,14 +71,14 @@ async function closeReader(reader) {
75
71
  if (reader.close)
76
72
  await reader.close();
77
73
  }
78
- /** Sentinel the native layer prefixes onto shape-contradiction errors (see
79
- * `session.rs` `SessionError::Path`). */
80
- const NATIVE_PATH_ERROR_PREFIX = 'bote.PathError: ';
81
- /** Rethrow a native shape-contradiction error as a `PathError` carrying the
82
- * caller's path; pass anything else through unchanged. */
83
- function asPathError(err, path) {
84
- if (err instanceof Error && !(err instanceof validate_ts_1.PathError) && err.message.startsWith(NATIVE_PATH_ERROR_PREFIX)) {
85
- return new validate_ts_1.PathError(err.message.slice(NATIVE_PATH_ERROR_PREFIX.length), path);
74
+ const NATIVE_PATH_ERROR = /^bote:path:([a-z_]+)(?::(\d+))?$/;
75
+ function deserializeError(err, path) {
76
+ if (err instanceof Error && !(err instanceof PathError)) {
77
+ const match = NATIVE_PATH_ERROR.exec(err.message);
78
+ if (match) {
79
+ const segment = match[2] === undefined ? undefined : Number(match[2]);
80
+ return new PathError(path, match[1], segment);
81
+ }
86
82
  }
87
83
  return err;
88
84
  }
@@ -97,62 +93,65 @@ function wrap(native, state) {
97
93
  const cursor = {
98
94
  async hop(...path) {
99
95
  ensureOpen(state);
100
- (0, path_ts_1.validatePath)(path);
96
+ validatePath(path);
101
97
  let child;
102
98
  try {
103
99
  child = await native.hop(path);
104
100
  }
105
101
  catch (err) {
106
- throw asPathError(err, path);
102
+ throw deserializeError(err, path);
107
103
  }
108
104
  return child ? wrap(child, state) : null;
109
105
  },
110
106
  async has(...args) {
111
107
  ensureOpen(state);
112
- const { path, tail: schema } = (0, args_ts_1.splitArgs)(args);
113
- if (schema !== undefined && !(0, args_ts_1.isSchema)(schema)) {
108
+ const { path, tail: schema } = splitArgs(args);
109
+ if (schema !== undefined && !isSchema(schema)) {
114
110
  throw new TypeError('has: expected a Standard Schema as the trailing argument');
115
111
  }
116
112
  if (!schema)
117
113
  return native.has(path);
118
114
  if (!(await native.has(path)))
119
115
  return false;
120
- const result = await (0, validate_ts_1.validateItem)(schema, await native.get(path), path, 'skip');
116
+ const text = await native.get(path);
117
+ const value = text === undefined ? undefined : parseValue(text, path);
118
+ const result = await validateItem(schema, value, path, 'skip');
121
119
  return !('skip' in result);
122
120
  },
123
121
  async get(...args) {
124
122
  ensureOpen(state);
125
- const { path, tail: schema } = (0, args_ts_1.splitArgs)(args);
126
- if (schema !== undefined && !(0, args_ts_1.isSchema)(schema)) {
123
+ const { path, tail: schema } = splitArgs(args);
124
+ if (schema !== undefined && !isSchema(schema)) {
127
125
  throw new TypeError('get: expected a Standard Schema as the trailing argument');
128
126
  }
129
127
  let value;
130
128
  try {
131
- value = await native.get(path);
129
+ const text = await native.get(path);
130
+ value = text === undefined ? undefined : parseValue(text, path);
132
131
  }
133
132
  catch (err) {
134
- throw asPathError(err, path);
133
+ throw deserializeError(err, path);
135
134
  }
136
135
  if (!schema)
137
136
  return value;
138
- return (0, validate_ts_1.runStandardSchema)(schema, value, path);
137
+ return runStandardSchema(schema, value, path);
139
138
  },
140
139
  async count(...path) {
141
140
  ensureOpen(state);
142
- (0, path_ts_1.validatePath)(path);
141
+ validatePath(path);
143
142
  try {
144
143
  return await native.count(path);
145
144
  }
146
145
  catch (err) {
147
- throw asPathError(err, path);
146
+ throw deserializeError(err, path);
148
147
  }
149
148
  },
150
149
  iter(...args) {
151
150
  ensureOpen(state);
152
- const { path, tail } = (0, args_ts_1.splitArgs)(args);
153
- const { schema, select, batch, onInvalid, withIndex } = (0, args_ts_1.normalizeIterTail)(tail);
154
- if (batch !== undefined && (!Number.isInteger(batch) || batch <= 0 || batch > exports.MAX_ITER_BATCH)) {
155
- throw new RangeError(`iter: batch must be an integer in 1..=${exports.MAX_ITER_BATCH}, got ${batch}`);
151
+ const { path, tail } = splitArgs(args);
152
+ const { schema, select, batch, onInvalid, withIndex } = normalizeIterTail(tail);
153
+ if (batch !== undefined && (!Number.isInteger(batch) || batch <= 0 || batch > MAX_ITER_BATCH)) {
154
+ throw new RangeError(`iter: batch must be an integer in 1..=${MAX_ITER_BATCH}, got ${batch}`);
156
155
  }
157
156
  if (withIndex !== undefined && typeof withIndex !== 'boolean') {
158
157
  throw new TypeError(`iter: withIndex must be a boolean, got ${typeof withIndex}`);
@@ -160,18 +159,29 @@ function wrap(native, state) {
160
159
  if (onInvalid !== undefined && onInvalid !== 'throw' && onInvalid !== 'skip') {
161
160
  throw new RangeError(`iter: onInvalid must be "throw" or "skip", got ${JSON.stringify(onInvalid)}`);
162
161
  }
163
- const resolvedBatch = batch ?? exports.DEFAULT_ITER_BATCH;
164
- const selectIr = select !== undefined ? (0, args_ts_1.serializeSelect)(select) : undefined;
165
- const inner = native.iter(path, { selectIr, batch: resolvedBatch, withKey: withIndex });
162
+ const resolvedBatch = batch ?? DEFAULT_ITER_BATCH;
163
+ const selectIr = select !== undefined ? serializeSelect(select) : undefined;
164
+ const inner = native.iter(path, { selectIr, batch: resolvedBatch });
166
165
  if (!schema) {
167
166
  return {
168
167
  async *[Symbol.asyncIterator]() {
168
+ let i = 0;
169
169
  try {
170
- for await (const b of inner)
171
- yield b;
170
+ for await (const b of inner) {
171
+ const batch = parseValue(b, path);
172
+ if (!withIndex) {
173
+ yield batch;
174
+ continue;
175
+ }
176
+ const out = new Array(batch.length);
177
+ for (let j = 0; j < batch.length; j++) {
178
+ out[j] = [i++, batch[j]];
179
+ }
180
+ yield out;
181
+ }
172
182
  }
173
183
  catch (err) {
174
- throw asPathError(err, path);
184
+ throw deserializeError(err, path);
175
185
  }
176
186
  },
177
187
  };
@@ -183,25 +193,26 @@ function wrap(native, state) {
183
193
  try {
184
194
  for await (const b of inner) {
185
195
  const out = [];
186
- for (const v of b) {
187
- const value = withIndex ? v[1] : v;
188
- const result = await (0, validate_ts_1.validateItem)(schema, value, [...path, i++], policy);
189
- if ('skip' in result)
196
+ for (const v of parseValue(b, path)) {
197
+ const index = i++;
198
+ const result = await validateItem(schema, v, [...path, index], policy);
199
+ if ('skip' in result) {
190
200
  continue;
191
- out.push(withIndex ? [v[0], result.value] : result.value);
201
+ }
202
+ out.push(withIndex ? [index, result.value] : result.value);
192
203
  }
193
204
  yield out;
194
205
  }
195
206
  }
196
207
  catch (err) {
197
- throw asPathError(err, path);
208
+ throw deserializeError(err, path);
198
209
  }
199
210
  },
200
211
  };
201
212
  },
202
213
  walk(...path) {
203
214
  ensureOpen(state);
204
- (0, path_ts_1.validatePath)(path);
215
+ validatePath(path);
205
216
  return {
206
217
  async *[Symbol.asyncIterator]() {
207
218
  try {
@@ -210,7 +221,7 @@ function wrap(native, state) {
210
221
  }
211
222
  }
212
223
  catch (err) {
213
- throw asPathError(err, path);
224
+ throw deserializeError(err, path);
214
225
  }
215
226
  },
216
227
  };
@@ -218,3 +229,11 @@ function wrap(native, state) {
218
229
  };
219
230
  return cursor;
220
231
  }
232
+ function parseValue(text, path) {
233
+ try {
234
+ return JSON.parse(text);
235
+ }
236
+ catch {
237
+ throw new Error(`bote: malformed JSON value at ${formatPath(path)}`);
238
+ }
239
+ }
package/dist/path.js CHANGED
@@ -1,18 +1,14 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MAX_ARRAY_INDEX = void 0;
4
- exports.validatePath = validatePath;
5
1
  /** Upper bound on numeric segments (napi takes them as `u32`). 2^32 - 1
6
2
  * comfortably covers any in-memory JSON array. */
7
- exports.MAX_ARRAY_INDEX = 0xffffffff;
8
- function validatePath(path) {
3
+ export const MAX_ARRAY_INDEX = 0xffffffff;
4
+ export function validatePath(path) {
9
5
  for (let i = 0; i < path.length; i++) {
10
6
  const s = path[i];
11
7
  if (typeof s === 'string')
12
8
  continue;
13
- if (typeof s === 'number' && Number.isInteger(s) && s >= 0 && s <= exports.MAX_ARRAY_INDEX)
9
+ if (typeof s === 'number' && Number.isInteger(s) && s >= 0 && s <= MAX_ARRAY_INDEX)
14
10
  continue;
15
- throw new TypeError(`path segment ${i}: expected string or non-negative integer (<= ${exports.MAX_ARRAY_INDEX}), got ${describeBadSegment(s)}`);
11
+ throw new TypeError(`path segment ${i}: expected string or non-negative integer (<= ${MAX_ARRAY_INDEX}), got ${describeBadSegment(s)}`);
16
12
  }
17
13
  }
18
14
  function describeBadSegment(s) {
package/dist/sources.js CHANGED
@@ -1,16 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fromBuffer = fromBuffer;
4
- exports.fromFile = fromFile;
5
- exports.fromHttpRange = fromHttpRange;
6
- const promises_1 = require("node:fs/promises");
1
+ import { open as fsOpen } from 'node:fs/promises';
7
2
  /** Default chunk size, in bytes, for in-memory sources. */
8
3
  const DEFAULT_BUFFER_CHUNK_BYTES = 4 * 1024;
9
4
  /** Default chunk size, in bytes, for local files: matches typical filesystem readahead. */
10
5
  const DEFAULT_FILE_CHUNK_BYTES = 64 * 1024;
11
6
  /** Default chunk size, in bytes, for HTTP range reads: amortizes RTT across more data. */
12
7
  const DEFAULT_URL_CHUNK_BYTES = 256 * 1024;
13
- function fromBuffer(buf, options) {
8
+ export function fromBuffer(buf, options) {
14
9
  const view = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
15
10
  const chunkBytes = options?.chunkBytes ?? DEFAULT_BUFFER_CHUNK_BYTES;
16
11
  return {
@@ -21,11 +16,11 @@ function fromBuffer(buf, options) {
21
16
  }),
22
17
  };
23
18
  }
24
- function fromFile(path, options) {
19
+ export function fromFile(path, options) {
25
20
  const chunkBytes = options?.chunkBytes ?? DEFAULT_FILE_CHUNK_BYTES;
26
21
  return {
27
22
  open: async () => {
28
- const handle = await (0, promises_1.open)(path, 'r');
23
+ const handle = await fsOpen(path, 'r');
29
24
  const stat = await handle.stat();
30
25
  let closed = false;
31
26
  return {
@@ -52,7 +47,7 @@ function fromFile(path, options) {
52
47
  },
53
48
  };
54
49
  }
55
- function fromHttpRange(url, options) {
50
+ export function fromHttpRange(url, options) {
56
51
  const init = options?.init;
57
52
  const chunkBytes = options?.chunkBytes ?? DEFAULT_URL_CHUNK_BYTES;
58
53
  return {
@@ -1,5 +1,6 @@
1
1
  import type { StandardSchemaV1 } from '@standard-schema/spec';
2
- export type { StandardSchemaV1 };
2
+ import type { PathFaultCode } from '@botejs/native';
3
+ export type { StandardSchemaV1, PathFaultCode };
3
4
  export type Segment = string | number;
4
5
  export type Path = readonly Segment[];
5
6
  export declare class ValidationError extends Error {
@@ -9,7 +10,9 @@ export declare class ValidationError extends Error {
9
10
  }
10
11
  export declare class PathError extends Error {
11
12
  readonly path: Path;
12
- constructor(reason: string, path: Path);
13
+ /** The fault kind; stable across versions, safe to branch on. */
14
+ readonly code: PathFaultCode;
15
+ constructor(path: Path, code: PathFaultCode, segment?: number);
13
16
  }
14
17
  export declare function runStandardSchema<O>(schema: StandardSchemaV1<unknown, O>, value: unknown, path: Path): Promise<O>;
15
18
  export declare function validateItem<O>(schema: StandardSchemaV1<unknown, O>, value: unknown, path: Path, onInvalid: 'throw' | 'skip'): Promise<{
package/dist/validate.js CHANGED
@@ -1,10 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PathError = exports.ValidationError = void 0;
4
- exports.runStandardSchema = runStandardSchema;
5
- exports.validateItem = validateItem;
6
- exports.formatPath = formatPath;
7
- class ValidationError extends Error {
1
+ export class ValidationError extends Error {
8
2
  issues;
9
3
  path;
10
4
  constructor(issues, path) {
@@ -14,23 +8,35 @@ class ValidationError extends Error {
14
8
  this.path = path;
15
9
  }
16
10
  }
17
- exports.ValidationError = ValidationError;
18
- class PathError extends Error {
11
+ /** Human message per fault kind. The native layer ships only the code (and the
12
+ * offending `segment` where it matters), so this is the single source of the
13
+ * user-facing prose. Keyed by the Rust-generated [`PathFaultCode`]. */
14
+ const PATH_FAULT_MESSAGE = {
15
+ through_scalar: (segment) => `path traverses a non-container value at segment ${segment}`,
16
+ wrong_kind: (segment) => `path segment ${segment} does not match the container kind`,
17
+ scalar_target: () => 'target value is not a container',
18
+ iter_on_object: () => 'iter target is an object; use walk() to iterate object members',
19
+ walk_on_array: () => 'walk target is an array; use iter() to iterate array elements',
20
+ };
21
+ export class PathError extends Error {
19
22
  path;
20
- constructor(reason, path) {
23
+ /** The fault kind; stable across versions, safe to branch on. */
24
+ code;
25
+ constructor(path, code, segment) {
26
+ const reason = (PATH_FAULT_MESSAGE[code] ?? (() => code))(segment);
21
27
  super(`bote: cannot resolve ${formatPath(path)}: ${reason}`);
22
28
  this.name = 'PathError';
23
29
  this.path = path;
30
+ this.code = code;
24
31
  }
25
32
  }
26
- exports.PathError = PathError;
27
- async function runStandardSchema(schema, value, path) {
33
+ export async function runStandardSchema(schema, value, path) {
28
34
  const result = await schema['~standard'].validate(value);
29
35
  if (result.issues)
30
36
  throw new ValidationError(result.issues, path);
31
37
  return result.value;
32
38
  }
33
- async function validateItem(schema, value, path, onInvalid) {
39
+ export async function validateItem(schema, value, path, onInvalid) {
34
40
  const result = await schema['~standard'].validate(value);
35
41
  if (result.issues) {
36
42
  if (onInvalid === 'skip')
@@ -39,7 +45,7 @@ async function validateItem(schema, value, path, onInvalid) {
39
45
  }
40
46
  return { value: result.value };
41
47
  }
42
- function formatPath(path) {
48
+ export function formatPath(path) {
43
49
  if (path.length === 0)
44
50
  return '(root)';
45
51
  let out = '';
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@botejs/core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
+ "type": "module",
4
5
  "license": "MIT",
5
6
  "repository": {
6
7
  "type": "git",
7
8
  "url": "git+https://github.com/jankdc/bote.git",
8
9
  "directory": "packages/core"
9
10
  },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
10
17
  "main": "dist/index.js",
11
18
  "types": "dist/index.d.ts",
12
19
  "files": [
@@ -14,7 +21,7 @@
14
21
  "README.md"
15
22
  ],
16
23
  "engines": {
17
- "node": ">= 18.17.0 < 19 || >= 20.3.0 < 21 || >= 21.1.0"
24
+ "node": ">= 22.18.0"
18
25
  },
19
26
  "publishConfig": {
20
27
  "registry": "https://registry.npmjs.org/",
@@ -23,12 +30,12 @@
23
30
  "scripts": {
24
31
  "build": "tsc",
25
32
  "build:debug": "tsc --sourceMap",
26
- "test": "node --test --experimental-strip-types --no-warnings=ExperimentalWarning __test__/*.spec.ts",
33
+ "test": "node --test __test__/*.spec.ts",
27
34
  "lint": "oxlint src",
28
35
  "prepublishOnly": "cp ../../README.md ./README.md && tsc"
29
36
  },
30
37
  "dependencies": {
31
- "@botejs/native": "workspace:*"
38
+ "@botejs/native": "^0.4.0"
32
39
  },
33
40
  "devDependencies": {
34
41
  "@types/node": "^22.0.0",