@atproto/lex 0.0.7 → 0.0.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @atproto/lex
2
2
 
3
+ ## 0.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4501](https://github.com/bluesky-social/atproto/pull/4501) [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add an `indexFile` option that allows generating an "index.ts" file that re-exports every tld namespaces.
8
+
9
+ - [#4501](https://github.com/bluesky-social/atproto/pull/4501) [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Export everything from `@atproto/lex-data` and `@atproto/lex-json`
10
+
11
+ - Updated dependencies [[`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98), [`2f78893`](https://github.com/bluesky-social/atproto/commit/2f78893ace3bbf14d4bac36837820ddb46658c98)]:
12
+ - @atproto/lex-builder@0.0.9
13
+ - @atproto/lex-client@0.0.7
14
+ - @atproto/lex-data@0.0.6
15
+ - @atproto/lex-schema@0.0.7
16
+ - @atproto/lex-installer@0.0.9
17
+ - @atproto/lex-json@0.0.6
18
+
19
+ ## 0.0.8
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies [[`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c), [`9af7a2d`](https://github.com/bluesky-social/atproto/commit/9af7a2d12240e91248610ce4fe7d93387733c59c)]:
24
+ - @atproto/lex-schema@0.0.6
25
+ - @atproto/lex-builder@0.0.8
26
+ - @atproto/lex-client@0.0.6
27
+ - @atproto/lex-installer@0.0.8
28
+
3
29
  ## 0.0.7
4
30
 
5
31
  ### Patch Changes
package/README.md CHANGED
@@ -53,7 +53,12 @@ app.bsky.actor.profile.$validate({
53
53
  - [TypeScript Schemas](#typescript-schemas)
54
54
  - [Generated Schema Structure](#generated-schema-structure)
55
55
  - [Type definitions](#type-definitions)
56
+ - [Building data](#building-data)
56
57
  - [Validation Helpers](#validation-helpers)
58
+ - [Data Model](#data-model)
59
+ - [Types](#types)
60
+ - [JSON Encoding](#json-encoding)
61
+ - [DAG-CBOR Encoding](#dag-cbor-encoding)
57
62
  - [Client API](#client-api)
58
63
  - [Creating a Client](#creating-a-client)
59
64
  - [Core Methods](#core-methods)
@@ -61,6 +66,8 @@ app.bsky.actor.profile.$validate({
61
66
  - [Authentication Methods](#authentication-methods)
62
67
  - [Labeler Configuration](#labeler-configuration)
63
68
  - [Low-Level XRPC](#low-level-xrpc)
69
+ - [Blob references](#blob-references)
70
+ - [Utilities](#utilities)
64
71
  - [Advanced Usage](#advanced-usage)
65
72
  - [Workflow Integration](#workflow-integration)
66
73
  - [Tree-Shaking](#tree-shaking)
@@ -89,7 +96,7 @@ This creates:
89
96
 
90
97
  > [!NOTE]
91
98
  >
92
- > The `lex` command might conflict with other binaries intalled on your system.
99
+ > The `lex` command might conflict with other binaries installed on your system.
93
100
  > If that happens, you can also run the CLI using `ts-lex`, `pnpm exec lex` or
94
101
  > `npx @atproto/lex`.
95
102
 
@@ -193,6 +200,7 @@ Options:
193
200
  - `--allowLegacyBlobs` - Allow generating schemas that accept legacy blob references (disabled by default; enable this if you encounter issues while processing records created a long time ago)
194
201
  - `--importExt <ext>` - File extension to use for import statements in generated files (default: `.js`). Use `--importExt ""` to generate extension-less imports
195
202
  - `--fileExt <ext>` - File extension to use for generated files (default: `.ts`)
203
+ - `--indexFile` - Generate an "index" file that re-exports all root-level namespaces (disabled by default)
196
204
 
197
205
  ### Generated Schema Structure
198
206
 
@@ -209,15 +217,25 @@ You can extract TypeScript types from the generated schemas for use in you appli
209
217
  ```typescript
210
218
  import * as app from './lexicons/app.js'
211
219
 
212
- // Extract the type for a post record
213
- type Post = app.bsky.feed.post.Main
220
+ function renderPost(p: app.bsky.feed.post.Main) {
221
+ console.log(p.$type) // 'app.bsky.feed.post'
222
+ console.log(p.text)
223
+ }
224
+ ```
214
225
 
215
- // Use the extracted types
216
- const post: Post = {
217
- $type: 'app.bsky.feed.post',
218
- text: 'Hello, AT Protocol!',
226
+ ### Building data
227
+
228
+ It is recommended to use the generated builders to create data that conforms to the schema. This ensures that all required fields are present.
229
+
230
+ ```typescript
231
+ import * as app from './lexicons/app.js'
232
+
233
+ // variable type will be inferred as "app.bsky.feed.post.Main"
234
+ const post = app.bsky.feed.post.$build({
235
+ // No need to specify $type when using $build
236
+ text: 'Hello, world!',
219
237
  createdAt: new Date().toISOString(),
220
- }
238
+ })
221
239
  ```
222
240
 
223
241
  ### Validation Helpers
@@ -284,6 +302,10 @@ try {
284
302
  }
285
303
  ```
286
304
 
305
+ > [!NOTE]
306
+ >
307
+ > The `$parse` method will apply defaults defined in the schema for optional fields, as well as data coercion (e.g., CID strings to Cid types). This means that the returned value might be different from the input data if defaults were applied. Disable this behavior by passing `{ allowTransform: false }` as the second argument to `$parse()`.
308
+
287
309
  #### `$validate(data)` - Get Validation Result
288
310
 
289
311
  Returns a detailed validation result object without throwing:
@@ -304,14 +326,18 @@ if (result.success) {
304
326
  }
305
327
  ```
306
328
 
329
+ > [!NOTE]
330
+ >
331
+ > Like `$parse`, the `$validate` method will apply defaults and coercion. Disable this behavior by passing `{ allowTransform: false }` as the second argument to `$validate()`.
332
+
307
333
  #### `$build(data)` - Build with Defaults
308
334
 
309
- Creates a valid object by applying defaults for optional fields:
335
+ Builds data without needing to specify the `$type` property, and properly types the result:
310
336
 
311
337
  ```typescript
312
338
  import * as app from './lexicons/app.js'
313
339
 
314
- // Build a like record with defaults (and without needing to specify $type)
340
+ // The type of the "like" variable will be "app.bsky.feed.like.Main"
315
341
  const like = app.bsky.feed.like.$build({
316
342
  subject: {
317
343
  uri: 'at://did:plc:abc/app.bsky.feed.post/123',
@@ -323,7 +349,7 @@ const like = app.bsky.feed.like.$build({
323
349
 
324
350
  #### `$isTypeOf(data)` - Type Discriminator
325
351
 
326
- Discriminates (already validated) data by `$type`, without re-validating. This is especially useful when working with union types:
352
+ Discriminates (pre-validated) data based on its `$type` property, without re-validating. This is especially useful when working with union types:
327
353
 
328
354
  ```typescript
329
355
  import { l } from '@atproto/lex'
@@ -340,6 +366,66 @@ if (app.bsky.feed.post.$isTypeOf(data)) {
340
366
  }
341
367
  ```
342
368
 
369
+ ## Data Model
370
+
371
+ The AT Protocol uses a [data model](https://atproto.com/specs/data-model) that extends JSON with two additional types: **CIDs** (content-addressed links) and **bytes**. This data is encoded as JSON for XRPC (HTTP API) or as [DAG-CBOR](https://ipld.io/docs/codecs/known/dag-cbor/) for storage and authentication (see [`@atproto/lex-cbor`](../lex-cbor)).
372
+
373
+ ### Types
374
+
375
+ ```typescript
376
+ import type {
377
+ LexValue,
378
+ LexMap,
379
+ LexScalar,
380
+ TypedLexMap,
381
+ Cid,
382
+ } from '@atproto/lex'
383
+ import { isLexValue, isLexMap, isTypedLexMap, isCid } from '@atproto/lex'
384
+
385
+ // LexScalar: number | string | boolean | null | Cid | Uint8Array
386
+ // LexValue: LexScalar | LexValue[] | { [key: string]?: LexValue }
387
+ // LexMap: { [key: string]?: LexValue }
388
+ // TypedLexMap: LexMap & { $type: string }
389
+ // Cid: Content Identifier (link by hash)
390
+
391
+ if (isTypedLexMap(data)) {
392
+ console.log(data.$type) // some string
393
+ }
394
+ ```
395
+
396
+ ### JSON Encoding
397
+
398
+ In JSON, CIDs are represented as `{"$link": "bafyrei..."}` and bytes as `{"$bytes": "base64..."}`:
399
+
400
+ ```typescript
401
+ import { lexParse, lexStringify, jsonToLex, lexToJson } from '@atproto/lex'
402
+
403
+ // Parse JSON string → data model (decodes $link and $bytes)
404
+ const data = lexParse('{"ref": {"$link": "bafyrei..."}}')
405
+
406
+ // Data model → JSON string (encodes CIDs and bytes)
407
+ const json = lexStringify({ ref: someCid, data: someBytes })
408
+
409
+ // Convert between parsed JSON objects and data model values
410
+ const lex = jsonToLex(jsonObject)
411
+ const obj = lexToJson(lexValue)
412
+ ```
413
+
414
+ ### DAG-CBOR Encoding
415
+
416
+ Use `@atproto/lex-cbor` to encode/decode the data model to/from DAG-CBOR format for storage and authentication:
417
+
418
+ ```typescript
419
+ import { encode, decode } from '@atproto/lex-cbor'
420
+ import type { LexValue } from '@atproto/lex'
421
+
422
+ // Encode data model to DAG-CBOR bytes
423
+ const cborBytes = encode(someLexValue)
424
+
425
+ // Decode DAG-CBOR bytes to data model
426
+ const lexValue: LexValue = decode(cborBytes)
427
+ ```
428
+
343
429
  ## Client API
344
430
 
345
431
  ### Creating a Client
@@ -624,7 +710,7 @@ if (result.success) {
624
710
  if (result.error === 'Unknown') {
625
711
  // Unable to perform the request
626
712
  const { reason } = result
627
- if (reason instanceof XrpcResponseError) {
713
+ if (reason instanceof LexRpcResponseError) {
628
714
  // The server returned a syntactically valid XRPC error response, but
629
715
  // used an error code that is not declared for this method
630
716
  reason.error // string (e.g. "AuthenticationRequired", "RateLimitExceeded", etc.)
@@ -632,7 +718,7 @@ if (result.success) {
632
718
  reason.status // number
633
719
  reason.headers // Headers
634
720
  reason.payload // { body: { error: string, message?: string }; encoding: string }
635
- } else if (reason instanceof XrpcInvalidResponseError) {
721
+ } else if (reason instanceof LexRpcUpstreamError) {
636
722
  // The response was incomplete (e.g. connection dropped), or
637
723
  // invalid (e.g. malformed JSON, data does not match schema).
638
724
  reason.error // "InvalidResponse"
@@ -645,7 +731,7 @@ if (result.success) {
645
731
  }
646
732
  } else {
647
733
  // A declared error for that method
648
- result // XrpcResponseError<"HandleNotFound">
734
+ result // LexRpcResponseError<"HandleNotFound">
649
735
  result.error // "HandleNotFound"
650
736
  result.message // string
651
737
  }
@@ -654,38 +740,38 @@ if (result.success) {
654
740
 
655
741
  The `ResponseFailure<M>` type is a union with three possible error types:
656
742
 
657
- 1. **Declared errors** - Errors explicitly listed in the method's Lexicon schema will be represented as an `XrpcResponseError<N>` instance:
743
+ 1. **Declared errors** - Errors explicitly listed in the method's Lexicon schema will be represented as an `LexRpcResponseError<N>` instance:
658
744
 
659
745
  ```typescript
660
- // XrpcResponseError<N>
661
- type KnownXrpcResponseFailure<N extends string> = {
746
+ // LexRpcResponseError<N>
747
+ type KnownLexRpcResponseFailure<N extends string> = {
662
748
  success: false
663
749
  name: N
664
- error: XrpcResponseError<N>
750
+ error: LexRpcResponseError<N>
665
751
 
666
752
  // Additional response details
667
753
  status: number
668
754
  headers: Headers
669
755
  encoding: undefined | string
670
- body: XrpcErrorBody<N>
756
+ body: LexErrorData<N>
671
757
  }
672
758
  ```
673
759
 
674
760
  2. **Unknown errors** - Server errors not declared in the method's schema:
675
761
 
676
762
  ```typescript
677
- // XrpcResponseFailure<'Unexpected', XrpcResponseError>
678
- type UnknownXrpcResponseFailure = {
763
+ // LexRpcResponseFailure<'Unexpected', LexRpcResponseError>
764
+ type UnknownLexRpcResponseFailure = {
679
765
  success: false
680
766
  name: 'Unexpected'
681
- error: XrpcResponseError<string>
767
+ error: LexRpcResponseError<string>
682
768
  }
683
769
  ```
684
770
 
685
771
  3. **Unexpected errors** - Network errors, invalid responses, or other client-side errors:
686
772
  ```typescript
687
- // XrpcResponseFailure<'UnexpectedError', unknown>
688
- type UnexpectedXrpcResponseFailure = {
773
+ // LexRpcResponseFailure<'UnexpectedError', unknown>
774
+ type UnexpectedLexRpcResponseFailure = {
689
775
  success: false
690
776
  name: 'UnexpectedError'
691
777
  error: unknown // Could be anything (network error, parsing error, etc.)
@@ -767,6 +853,77 @@ console.log(response.headers)
767
853
  console.log(response.body)
768
854
  ```
769
855
 
856
+ ## Blob references
857
+
858
+ In AT Protocol, binary data (blobs) are referenced using `BlobRef`, which include metadata like MIME type and size. These references are what allow PDSs to determine which binary data ("files") is referenced by records.
859
+
860
+ ```typescript
861
+ import { BlobRef, isBlobRef } from '@atproto/lex'
862
+
863
+ const blobRef: BlobRef = {
864
+ $type: 'blob',
865
+ ref: parseCid('bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku'),
866
+ mimeType: 'image/png',
867
+ size: 12345,
868
+ }
869
+
870
+ if (isBlobRef(blobRef)) {
871
+ console.log('Valid BlobRef:', blobRef.mimeType, blobRef.size)
872
+ }
873
+ ```
874
+
875
+ > [!NOTE]
876
+ >
877
+ > Historically, references to blobs were represented as simple objects with the following structure:
878
+ >
879
+ > ```typescript
880
+ > type LegacyBlobRef = {
881
+ > ref: string
882
+ > mimeType: string
883
+ > }
884
+ > ```
885
+ >
886
+ > These should no longer be used for new records, but existing records using this format might still be encountered. To handle legacy blob references when validating data, enable the `--allowLegacyBlobs` flag when generating TypeScript schemas with `lex build`. You can use `isLegacyBlobRef()` from `@atproto/lex` to discriminate legacy blob references.
887
+
888
+ ## Utilities
889
+
890
+ Various utilities for working with CIDs, string lengths, language tags, and low-level JSON encoding are available:
891
+
892
+ ```typescript
893
+ import {
894
+ // CID utilities
895
+ parseCid, // Parse CID string (throws on invalid)
896
+ asCid, // Coerce to Cid or null
897
+ isCid, // Type guard for Cid values
898
+
899
+ // Blob references
900
+ BlobRef, // { $type: 'blob', ref: Cid, mimeType: string, size: number }
901
+ isBlobRef, // Type guard for BlobRef objects
902
+
903
+ // Equality
904
+ lexEquals, // Deep equality (handles CIDs and bytes)
905
+
906
+ // String length for Lexicon validation
907
+ graphemeLen, // Count user-perceived characters
908
+ utf8Len, // Count UTF-8 bytes
909
+
910
+ // Language tag validation (BCP-47)
911
+ isLanguageString, // Validate language tags (e.g., 'en', 'pt-BR')
912
+
913
+ // Low-level JSON encoding helpers
914
+ parseLexLink, // { $link: string } → Cid
915
+ encodeLexLink, // Cid → { $link: string }
916
+ parseLexBytes, // { $bytes: string } → Uint8Array
917
+ encodeLexBytes, // Uint8Array → { $bytes: string }
918
+ } from '@atproto/lex'
919
+
920
+ // Examples
921
+ const cid = parseCid('bafyreiabc...')
922
+ graphemeLen('👨‍👩‍👧‍👦') // 1
923
+ utf8Len('👨‍👩‍👧‍👦') // 25
924
+ isLanguageString('en-US') // true
925
+ ```
926
+
770
927
  ## Advanced Usage
771
928
 
772
929
  ### Workflow Integration
@@ -1216,7 +1373,7 @@ await client.call(unfollow, { followUri: uri })
1216
1373
  #### Updating Profile with Retry Logic
1217
1374
 
1218
1375
  ```typescript
1219
- import { Action, XrpcResponseError } from '@atproto/lex'
1376
+ import { Action, LexRpcResponseError } from '@atproto/lex'
1220
1377
  import * as app from './lexicons/app.js'
1221
1378
  import * as com from './lexicons/com.js'
1222
1379
 
@@ -1258,7 +1415,7 @@ export const updateProfile: Action<ProfileUpdate, void> = async (
1258
1415
  } catch (error) {
1259
1416
  // Retry on swap/concurrent modification errors
1260
1417
  if (
1261
- error instanceof XrpcResponseError &&
1418
+ error instanceof LexRpcResponseError &&
1262
1419
  error.name === 'SwapError' &&
1263
1420
  attempt < maxRetries - 1
1264
1421
  ) {
package/bin/lex CHANGED
@@ -94,6 +94,12 @@ yargs(hideBin(process.argv))
94
94
  describe:
95
95
  'file extension to use for generated files (e.g. ".ts", ".mts", ".cts")',
96
96
  },
97
+ indexFile: {
98
+ type: 'boolean',
99
+ default: false,
100
+ describe:
101
+ 'generate an "index.<fileExt>" file that exports all root-level namespaces',
102
+ },
97
103
  ignoreInvalidLexicons: {
98
104
  type: 'boolean',
99
105
  default: false,
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export * from '@atproto/lex-data';
2
+ export * from '@atproto/lex-json';
1
3
  export * from '@atproto/lex-schema';
2
4
  export * from '@atproto/lex-client';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("@atproto/lex-data"), exports);
5
+ tslib_1.__exportStar(require("@atproto/lex-json"), exports);
4
6
  tslib_1.__exportStar(require("@atproto/lex-schema"), exports);
5
7
  tslib_1.__exportStar(require("@atproto/lex-client"), exports);
6
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,8DAAmC;AACnC,8DAAmC","sourcesContent":["export * from '@atproto/lex-schema'\nexport * from '@atproto/lex-client'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4DAAiC;AACjC,4DAAiC;AACjC,8DAAmC;AACnC,8DAAmC","sourcesContent":["export * from '@atproto/lex-data'\nexport * from '@atproto/lex-json'\nexport * from '@atproto/lex-schema'\nexport * from '@atproto/lex-client'\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "license": "MIT",
5
5
  "description": "Lexicon tooling for AT",
6
6
  "keywords": [
@@ -36,18 +36,20 @@
36
36
  "dependencies": {
37
37
  "tslib": "^2.8.1",
38
38
  "yargs": "^17.0.0",
39
- "@atproto/lex-builder": "0.0.7",
40
- "@atproto/lex-client": "0.0.5",
41
- "@atproto/lex-installer": "0.0.7",
42
- "@atproto/lex-schema": "0.0.5"
39
+ "@atproto/lex-builder": "0.0.9",
40
+ "@atproto/lex-client": "0.0.7",
41
+ "@atproto/lex-data": "0.0.6",
42
+ "@atproto/lex-json": "0.0.6",
43
+ "@atproto/lex-installer": "0.0.9",
44
+ "@atproto/lex-schema": "0.0.7"
43
45
  },
44
46
  "devDependencies": {
45
47
  "@types/yargs": "^17.0.33",
46
- "jest": "^28.1.2"
48
+ "vitest": "^4.0.16"
47
49
  },
48
50
  "scripts": {
49
51
  "prebuild": "./bin/lex build --clear --lexicons ./lexicons --out ./tests/lexicons --lib @atproto/lex-schema -- ignore additional npm args",
50
52
  "build": "tsc --build tsconfig.build.json",
51
- "test": "jest"
53
+ "test": "vitest run"
52
54
  }
53
55
  }