@atproto/lex 0.1.2 → 0.1.3

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,17 @@
1
1
  # @atproto/lex
2
2
 
3
+ ## 0.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#5006](https://github.com/bluesky-social/atproto/pull/5006) [`60721e6`](https://github.com/bluesky-social/atproto/commit/60721e69c8db193eb817c4238ac447505ac855bc) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Fix README
8
+
9
+ - [#5006](https://github.com/bluesky-social/atproto/pull/5006) [`60721e6`](https://github.com/bluesky-social/atproto/commit/60721e69c8db193eb817c4238ac447505ac855bc) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update `yargs` depedency
10
+
11
+ - Updated dependencies [[`60721e6`](https://github.com/bluesky-social/atproto/commit/60721e69c8db193eb817c4238ac447505ac855bc), [`60721e6`](https://github.com/bluesky-social/atproto/commit/60721e69c8db193eb817c4238ac447505ac855bc)]:
12
+ - @atproto/lex-schema@0.1.2
13
+ - @atproto/lex-client@0.1.3
14
+
3
15
  ## 0.1.2
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -1,7 +1,3 @@
1
- > [!IMPORTANT]
2
- >
3
- > This package is currently in **preview**. The API and features are subject to change before the stable release. See the [Changelog](./CHANGELOG.md) for version history.
4
-
5
1
  Type-safe Lexicon tooling for AT Protocol data.
6
2
 
7
3
  - Fetch and manage Lexicon schemas, generate TypeScript validators
@@ -54,14 +50,16 @@ const posts = await client.list(app.bsky.feed.post, { limit: 10 })
54
50
  - [Type definitions](#type-definitions)
55
51
  - [Building data](#building-data)
56
52
  - [Validation Helpers](#validation-helpers)
57
- - [`$nsid` - Namespace Identifier](#nsid---namespace-identifier)
58
- - [`$type` - Type Identifier](#type---type-identifier)
59
- - [`$check(data)` - Type Guard](#checkdata---type-guard)
60
- - [`$parse(data)` - Parse and Validate](#parsedata---parse-and-validate)
61
- - [`$validate(data)` - Validate a value against the schema](#validatedata---validate-a-value-against-the-schema)
62
- - [`$safeParse(data, options?)` - Parse a value against a schema and get the resulting value](#safeparsedata-options---parse-a-value-against-a-schema-and-get-the-resulting-value)
63
- - [`$build(data)` - Build with Defaults](#builddata---build-with-defaults)
64
- - [`$isTypeOf(data)` - Type Discriminator](#istypeofdata---type-discriminator)
53
+ - [Record / typed-object helpers](#record--typed-object-helpers)
54
+ - [`$type` - Type Identifier](#type---type-identifier)
55
+ - [`$build(data)` - Build with Defaults](#builddata---build-with-defaults)
56
+ - [`$isTypeOf(data)` - Type Discriminator](#istypeofdata---type-discriminator)
57
+ - [Universal validation helpers](#universal-validation-helpers)
58
+ - [`$matches(data)` - Type Guard](#matchesdata---type-guard)
59
+ - [`$assert(data)` - Type-Narrowing Assertion](#assertdata---type-narrowing-assertion)
60
+ - [`$parse(data)` - Parse and Validate](#parsedata---parse-and-validate)
61
+ - [`$validate(data)` - Validate a value against the schema](#validatedata---validate-a-value-against-the-schema)
62
+ - [`$safeParse(data, options?)` - Parse a value against a schema and get the resulting value](#safeparsedata-options---parse-a-value-against-a-schema-and-get-the-resulting-value)
65
63
  - [Data Model](#data-model)
66
64
  - [Types](#types)
67
65
  - [JSON Encoding](#json-encoding)
@@ -120,6 +118,7 @@ const posts = await client.list(app.bsky.feed.post, { limit: 10 })
120
118
  - [Packaging Actions as a Library](#packaging-actions-as-a-library)
121
119
  - [Best Practices for Actions](#best-practices-for-actions)
122
120
  - [Standard Schema Compatibility](#standard-schema-compatibility)
121
+ - [Validating Generic Schemas with `$check`](#validating-generic-schemas-with-check)
123
122
  - [License](#license)
124
123
 
125
124
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -233,15 +232,16 @@ Options:
233
232
  - `--clear` - Clear output directory before generating
234
233
  - `--override` - Override existing files (has no effect with --clear)
235
234
  - `--no-pretty` - Don't run prettier on generated files (prettier is enabled by default)
236
- - `--ignore-errors` - How to handle errors when processing input files
237
- - `--pure-annotations` - Add `/*#__PURE__*/` annotations for tree-shaking tools. Set this to true if you are using generated lexicons in a library
235
+ - `--ignore-errors` - Skip files that fail to parse or compile instead of aborting the build
236
+ - `--ignore-invalid-lexicons` - Skip lexicon files that fail validation instead of exiting with an error
238
237
  - `--exclude <patterns...>` - List of strings or regex patterns to exclude lexicon documents by their IDs
239
238
  - `--include <patterns...>` - List of strings or regex patterns to include lexicon documents by their IDs
240
239
  - `--lib <package>` - Package name of the library to import the lex schema utility "l" from (default: `@atproto/lex`)
241
- - `--importExt <ext>` - File extension to use for import statements in generated files (default: `.js`). Use `--importExt ""` to generate extension-less imports
242
- - `--fileExt <ext>` - File extension to use for generated files (default: `.ts`)
243
- - `--indexFile` - Generate an "index" file that re-exports all root-level namespaces (disabled by default)
244
- - `--no-defaultExport` - Disable generation of a `default` export of the `main` schema in each schema's namespace file (default exports are enabled by default; see [Tree-Shaking](#tree-shaking))
240
+ - `--import-ext <ext>` - File extension to use for import statements in generated files (default: `.js`). Use `--import-ext ""` to generate extension-less imports
241
+ - `--file-ext <ext>` - File extension to use for generated files (default: `.ts`)
242
+ - `--index-file` - Generate an "index" file that re-exports all root-level namespaces (disabled by default)
243
+ - `--defs-export` - When some definitions conflict with child namespaces, export lexicon definitions under a separate `$defs` namespace (e.g. `com.example.foo.$defs`)
244
+ - `--no-default-export` - Disable generation of a `default` export of the `main` schema in each schema's namespace file (default exports are enabled by default; see [Tree-Shaking](#tree-shaking))
245
245
 
246
246
  ### Generated Schema Structure
247
247
 
@@ -286,11 +286,12 @@ app.bsky.feed.post.$validate(post)
286
286
 
287
287
  ### Validation Helpers
288
288
 
289
- Each schema provides multiple validation methods:
289
+ Generated namespaces expose a handful of `$`-prefixed helpers bound to the namespace's `main` schema. They come in two groups:
290
290
 
291
- #### `$nsid` - Namespace Identifier
291
+ - [**Universal validation helpers**](#universal-validation-helpers) are available on every schema's `main`: `$matches`, `$assert`, `$check`, `$parse`, `$safeParse`, `$validate`, `$safeValidate` (and `$cast` / `$ifMatches`). These work for records, typed objects, queries, procedures, and subscriptions.
292
+ - [**Record / typed-object helpers**](#record--typed-object-helpers) are only emitted for record and typed-object schemas: `$type`, `$build`, `$isTypeOf`.
292
293
 
293
- Returns the NSID of the schema:
294
+ In addition, every generated namespace file exports a top-level `$nsid` constant containing the NSID of the lexicon document:
294
295
 
295
296
  ```typescript
296
297
  import * as app from './lexicons/app.js'
@@ -298,9 +299,13 @@ import * as app from './lexicons/app.js'
298
299
  console.log(app.bsky.feed.defs.$nsid) // 'app.bsky.feed.defs'
299
300
  ```
300
301
 
301
- #### `$type` - Type Identifier
302
+ The Schema instance itself (for example `app.bsky.feed.post.main`) also exposes the underlying methods both with and without the `$` prefix (e.g. `main.parse()` and `main.$parse()`).
303
+
304
+ #### Record / typed-object helpers
302
305
 
303
- Returns the `$type` string of the schema (for record and object schemas):
306
+ ##### `$type` - Type Identifier
307
+
308
+ Returns the `$type` string of the schema (only available on record and typed-object schemas):
304
309
 
305
310
  ```typescript
306
311
  import * as app from './lexicons/app.js'
@@ -309,7 +314,52 @@ console.log(app.bsky.feed.post.$type) // 'app.bsky.feed.post'
309
314
  console.log(app.bsky.actor.defs.profileViewBasic.$type) // 'app.bsky.actor.defs#profileViewBasic'
310
315
  ```
311
316
 
312
- #### `$check(data)` - Type Guard
317
+ Prefer `$type` over hard-coding the equivalent string literal in your code. The constant is emitted exactly once per schema in the generated namespace file, so every reference reuses the same string instance. Inlining `'app.bsky.feed.post'` everywhere instead leaks the same string into every call site, increases bundle size, and creates a typo-prone source of drift between your code and the schema.
318
+
319
+ ##### `$build(data)` - Build with Defaults
320
+
321
+ Builds data by adding the `$type` property and properly types the result. This also allows to declare a variable with the correct type without having to explicitly specify it.
322
+
323
+ ```typescript
324
+ import { l } from '@atproto/lex'
325
+ import * as app from './lexicons/app.js'
326
+
327
+ // The type of the "like" variable will be "app.bsky.feed.like.Main" (no need to explicitly specify the type)
328
+ const like = app.bsky.feed.like.$build({
329
+ subject: {
330
+ uri: 'at://did:plc:abc/app.bsky.feed.post/123',
331
+ cid: 'bafyrei...',
332
+ },
333
+ createdAt: l.currentDatetimeString(),
334
+ })
335
+ ```
336
+
337
+ > [!NOTE]
338
+ >
339
+ > `$build()` does not perform validation, and expects properly typed input data - use `$parse()` if you need validation.
340
+
341
+ ##### `$isTypeOf(data)` - Type Discriminator
342
+
343
+ Discriminates (pre-validated) data based on its `$type` property, without re-validating. This is especially useful when working with union types:
344
+
345
+ ```typescript
346
+ import { l } from '@atproto/lex'
347
+ import * as app from './lexicons/app.js'
348
+
349
+ declare const data:
350
+ | app.bsky.feed.post.Main
351
+ | app.bsky.feed.like.Main
352
+ | l.Unknown$TypedObject
353
+
354
+ // Discriminate by $type without re-validating
355
+ if (app.bsky.feed.post.$isTypeOf(data)) {
356
+ // data is a post
357
+ }
358
+ ```
359
+
360
+ #### Universal validation helpers
361
+
362
+ ##### `$matches(data)` - Type Guard
313
363
 
314
364
  Returns `true` if data matches the schema, `false` otherwise. Acts as a TypeScript type guard:
315
365
 
@@ -317,19 +367,45 @@ Returns `true` if data matches the schema, `false` otherwise. Acts as a TypeScri
317
367
  import { l } from '@atproto/lex'
318
368
  import * as app from './lexicons/app.js'
319
369
 
320
- const data = {
370
+ const data: unknown = {
321
371
  $type: 'app.bsky.feed.post',
322
372
  text: 'Hello!',
323
373
  createdAt: l.currentDatetimeString(),
324
374
  }
325
375
 
326
- if (app.bsky.feed.post.$check(data)) {
376
+ if (app.bsky.feed.post.$matches(data)) {
327
377
  // TypeScript knows data is a Post here
328
378
  console.log(data.text)
329
379
  }
330
380
  ```
331
381
 
332
- #### `$parse(data)` - Parse and Validate
382
+ > [!NOTE]
383
+ >
384
+ > Performs validation so [`$isTypeOf`](#istypeofdata---type-discriminator) is preferred for pre-validated & properly typed data.
385
+
386
+ ##### `$assert(data)` - Type-Narrowing Assertion
387
+
388
+ Throws if `data` does not match the schema. When the schema is statically known (e.g. `app.bsky.feed.post`), TypeScript narrows the type of `data` after the call:
389
+
390
+ ```typescript
391
+ import { l } from '@atproto/lex'
392
+ import * as app from './lexicons/app.js'
393
+
394
+ const data: unknown = {
395
+ $type: 'app.bsky.feed.post',
396
+ text: 'Hello!',
397
+ createdAt: l.currentDatetimeString(),
398
+ }
399
+
400
+ app.bsky.feed.post.$assert(data)
401
+
402
+ // TypeScript now knows data is app.bsky.feed.post.Main
403
+ console.log(data.text)
404
+ ```
405
+
406
+ For library code that operates on a schema parameter whose type cannot be fully expressed, see [Validating Generic Schemas with `$check`](#validating-generic-schemas-with-check).
407
+
408
+ ##### `$parse(data)` - Parse and Validate
333
409
 
334
410
  Validates and returns typed data, throwing an error if validation fails:
335
411
 
@@ -338,11 +414,12 @@ import { l } from '@atproto/lex'
338
414
  import * as app from './lexicons/app.js'
339
415
 
340
416
  try {
341
- const post = app.bsky.feed.post.$main.$parse({
417
+ const post = app.bsky.feed.post.$parse({
342
418
  $type: 'app.bsky.feed.post',
343
419
  text: 'Hello!',
344
420
  createdAt: l.currentDatetimeString(),
345
421
  })
422
+
346
423
  // post is now typed and validated
347
424
  console.log(post.text)
348
425
  } catch (error) {
@@ -354,7 +431,7 @@ try {
354
431
  >
355
432
  > 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. Use `$validate()` for value validation.
356
433
 
357
- #### `$validate(data)` - Validate a value against the schema
434
+ ##### `$validate(data)` - Validate a value against the schema
358
435
 
359
436
  Validates an existing value against a schema, returning the value itself if, and only if, it already matches the schema (ie. without applying defaults or coercion).
360
437
 
@@ -374,7 +451,7 @@ const result = app.bsky.feed.post.$validate(value)
374
451
  value === result // true
375
452
  ```
376
453
 
377
- #### `$safeParse(data, options?)` - Parse a value against a schema and get the resulting value
454
+ ##### `$safeParse(data, options?)` - Parse a value against a schema and get the resulting value
378
455
 
379
456
  Returns a detailed validation result object without throwing:
380
457
 
@@ -405,43 +482,6 @@ app.bsky.feed.post.$safeParse(data) // { strict: true } is the default
405
482
  app.bsky.feed.post.$safeParse(data, { strict: false })
406
483
  ```
407
484
 
408
- #### `$build(data)` - Build with Defaults
409
-
410
- Builds data by adding the `$type` property and properly types the result. Note that `$build()` does not perform validation - use `$parse()` if you need validation:
411
-
412
- ```typescript
413
- import { l } from '@atproto/lex'
414
- import * as app from './lexicons/app.js'
415
-
416
- // The type of the "like" variable will be "app.bsky.feed.like.Main"
417
- const like = app.bsky.feed.like.$build({
418
- subject: {
419
- uri: 'at://did:plc:abc/app.bsky.feed.post/123',
420
- cid: 'bafyrei...',
421
- },
422
- createdAt: l.currentDatetimeString(),
423
- })
424
- ```
425
-
426
- #### `$isTypeOf(data)` - Type Discriminator
427
-
428
- Discriminates (pre-validated) data based on its `$type` property, without re-validating. This is especially useful when working with union types:
429
-
430
- ```typescript
431
- import { l } from '@atproto/lex'
432
- import * as app from './lexicons/app.js'
433
-
434
- declare const data:
435
- | app.bsky.feed.post.Main
436
- | app.bsky.feed.like.Main
437
- | l.Unknown$TypedObject
438
-
439
- // Discriminate by $type without re-validating
440
- if (app.bsky.feed.post.$isTypeOf(data)) {
441
- // data is a post
442
- }
443
- ```
444
-
445
485
  ## Data Model
446
486
 
447
487
  The AT Protocol uses a [data model](https://atproto.com/specs/data-model) that extends JSON with two additional data structures: **CIDs** (content-addressed links) and **bytes** (for raw data). This data model can be encoded either as JSON for XRPC (HTTP API) or as [CBOR](https://dasl.ing/drisl.html) for storage and authentication (see [`@atproto/lex-cbor`](../lex-cbor)).
@@ -710,7 +750,7 @@ console.log(result.cid)
710
750
  Options:
711
751
 
712
752
  - `rkey` - Custom record key (auto-generated if not provided)
713
- - `validate` - Asks the PDS to validate the record against schema when processing the request
753
+ - `validate` - Tri-state instruction to the PDS. `true` forces server-side schema validation, `false` explicitly disables it, and `undefined` (default) lets the PDS decide (it validates only collections whose schemas it knows)
714
754
  - `validateRequest` - Validate the record locally against schema before submitting the request
715
755
  - `swapCommit` - CID for optimistic concurrency control
716
756
 
@@ -752,8 +792,8 @@ await client.put(app.bsky.actor.profile, {
752
792
  Options:
753
793
 
754
794
  - `rkey` - Record key (required for non-literal keys)
755
- - `validate` - Validate record against schema before updating (falls back to `validateRequest` option if not specified)
756
- - `validateRequest` - Alternative way to enable validation (used if `validate` is not specified)
795
+ - `validate` - Tri-state instruction to the PDS. `true` forces server-side schema validation, `false` explicitly disables it, and `undefined` (default) lets the PDS decide (it validates only collections whose schemas it knows)
796
+ - `validateRequest` - Validate the record locally against schema before submitting the request
757
797
  - `swapCommit` - Expected repo commit CID
758
798
  - `swapRecord` - Expected record CID
759
799
 
@@ -785,6 +825,11 @@ for (const record of result.records) {
785
825
  console.log(record.uri, record.value.text)
786
826
  }
787
827
 
828
+ // Records that failed local schema validation are returned separately
829
+ for (const invalid of result.invalid) {
830
+ console.warn('Invalid record:', invalid)
831
+ }
832
+
788
833
  // Pagination
789
834
  if (result.cursor) {
790
835
  const nextPage = await client.list(app.bsky.feed.post, {
@@ -794,6 +839,12 @@ if (result.cursor) {
794
839
  }
795
840
  ```
796
841
 
842
+ The result includes:
843
+
844
+ - `records` - Records that successfully validated against the schema
845
+ - `invalid` - Records returned by the server that failed local schema validation (raw `LexMap` values)
846
+ - `cursor` - Pagination cursor (if more results are available)
847
+
797
848
  #### `client.applyWrites()`
798
849
 
799
850
  Perform an atomic batch of create, update, and delete operations in a single request.
@@ -830,7 +881,7 @@ for (const result of response.body.results) {
830
881
  Options:
831
882
 
832
883
  - `repo` - Repository identifier (defaults to authenticated user's DID)
833
- - `validate` - Asks the PDS to validate records against schema
884
+ - `validate` - Tri-state instruction to the PDS. `true` forces server-side schema validation, `false` explicitly disables it, and `undefined` (default) lets the PDS decide (it validates only collections whose schemas it knows)
834
885
  - `swapCommit` - CID for optimistic concurrency control
835
886
 
836
887
  > [!NOTE]
@@ -869,13 +920,23 @@ if (result.success) {
869
920
  // Handle success
870
921
  console.log(result.body)
871
922
  } else {
872
- // Handle failure - result is an XrpcFailure
923
+ // Handle failure - result is an XrpcFailure.
924
+ //
925
+ // All XrpcFailure subclasses inherit from XrpcError and share these members:
926
+ result.error // string error code (e.g. "HandleNotFound", "UpstreamFailure")
927
+ result.message // string
928
+ result.shouldRetry() // boolean - whether the error is transient
929
+
930
+ if (result.matchesSchemaErrors()) {
931
+ // Check if the error matches a declared error in the schema.
932
+ // TypeScript narrows `result.error` to one of the method's declared error codes.
933
+ result.error // "HandleNotFound"
934
+ }
935
+
936
+ // Branch on the specific error class to access additional members:
873
937
  if (result instanceof XrpcResponseError) {
874
938
  // The server responded with an error status code (4xx or 5xx).
875
939
  // This is used for all error responses, whether or not they have a valid XRPC error payload.
876
-
877
- result.error // string (e.g. "HandleNotFound", "AuthenticationRequired", "UpstreamFailure", etc.)
878
- result.message // string
879
940
  result.response.status // number
880
941
  result.response.headers // Headers
881
942
  result.payload // undefined | { body: unknown; encoding: string }
@@ -885,25 +946,11 @@ if (result.success) {
885
946
  } else if (result instanceof XrpcInvalidResponseError) {
886
947
  // The response was truly invalid (3xx redirect, malformed JSON, schema mismatch, etc.).
887
948
  // This is a more specific error for responses that are not processable.
888
-
889
- result.error // "UpstreamFailure"
890
- result.message // string
891
949
  result.response.status // number
892
950
  result.response.headers // Headers
893
951
  result.payload // undefined | { body: unknown; encoding: string }
894
952
  } else if (result instanceof XrpcInternalError) {
895
953
  // Something went wrong on the client side (network error, etc.)
896
- result.error // "InternalServerError"
897
- result.message // string
898
- }
899
-
900
- // All XrpcFailure types have these properties:
901
- result.shouldRetry() // boolean - whether the error is transient
902
-
903
- if (result.matchesSchemaErrors()) {
904
- // Check if the error matches a declared error in the schema.
905
- // TypeScript knows this is a declared error for the method.
906
- result.error // "HandleNotFound"
907
954
  }
908
955
  }
909
956
  ```
@@ -1041,9 +1088,9 @@ import {
1041
1088
  isLanguageString, // Validate language tags (e.g., 'en', 'pt-BR')
1042
1089
 
1043
1090
  // Low-level JSON encoding helpers
1044
- parseLexLink, // { $link: string } → Cid
1091
+ parseLexLink, // { $link: string } → Cid | undefined
1045
1092
  encodeLexLink, // Cid → { $link: string }
1046
- parseLexBytes, // { $bytes: string } → Uint8Array
1093
+ parseLexBytes, // { $bytes: string } → Uint8Array | undefined
1047
1094
  encodeLexBytes, // Uint8Array → { $bytes: string }
1048
1095
  } from '@atproto/lex'
1049
1096
 
@@ -1313,7 +1360,7 @@ An `Action` is a function with this signature:
1313
1360
  type Action<Input, Output> = (
1314
1361
  client: Client,
1315
1362
  input: Input,
1316
- options: CallOptions,
1363
+ options: ActionOptions,
1317
1364
  ) => Output | Promise<Output>
1318
1365
  ```
1319
1366
 
@@ -1321,7 +1368,7 @@ Actions receive:
1321
1368
 
1322
1369
  - `client` - The Client instance (to make XRPC calls)
1323
1370
  - `input` - The input data for the action
1324
- - `options` - Call options (signal)
1371
+ - `options` - `ActionOptions` (currently just `{ signal?: AbortSignal }`)
1325
1372
 
1326
1373
  #### Using Actions
1327
1374
 
@@ -1636,10 +1683,10 @@ export const updateProfile: Action<ProfileUpdate, void> = async (
1636
1683
  },
1637
1684
  })
1638
1685
 
1639
- const current = app.bsky.actor.profile.main.validate(res.body.record)
1686
+ const current = app.bsky.actor.profile.$safeValidate(res.body.record)
1640
1687
 
1641
1688
  // Merge updates with current profile (if valid)
1642
- const updated = app.bsky.actor.profile.main.build({
1689
+ const updated = app.bsky.actor.profile.$build({
1643
1690
  ...(current.success ? current.value : undefined),
1644
1691
  ...updates,
1645
1692
  })
@@ -1744,6 +1791,26 @@ if ('value' in result) {
1744
1791
 
1745
1792
  When validated through the Standard Schema interface, schemas operate in "parse" mode, meaning transformations like defaults and coercions are applied to the output.
1746
1793
 
1794
+ ### Validating Generic Schemas with `$check`
1795
+
1796
+ `$check(data)` is the non-narrowing counterpart to [`$assert(data)`](#assertdata---type-narrowing-assertion): both throw when `data` does not match the schema, but `$check` does not refine the static type of its argument.
1797
+
1798
+ `$check` is rarely needed in application code — prefer `$assert`. It is intended for library-style code that takes a schema as a generic parameter, where TypeScript cannot satisfy the assertion-signature requirement and `$assert` produces the following error:
1799
+
1800
+ > 'schema' needs an explicit type annotation.
1801
+ > Assertions require every name in the call target to be declared with an explicit type annotation. `ts(2775)`
1802
+
1803
+ In that situation, switch to `$check`:
1804
+
1805
+ ```typescript
1806
+ import type { Schema } from '@atproto/lex'
1807
+
1808
+ function ensureMatches<S extends Schema>(schema: S, data: unknown) {
1809
+ // schema.$assert(data) // ❌ ts(2775): needs an explicit type annotation
1810
+ schema.$check(data) // ✅ throws on invalid, no type narrowing
1811
+ }
1812
+ ```
1813
+
1747
1814
  ## License
1748
1815
 
1749
1816
  MIT or Apache2
package/bin/lex CHANGED
@@ -69,37 +69,37 @@ yargs(hideBin(process.argv))
69
69
  describe:
70
70
  'package name of the library to import the lex schema utility "l" from',
71
71
  },
72
- importExt: {
72
+ 'import-ext': {
73
73
  type: 'string',
74
74
  default: '.js',
75
75
  describe:
76
76
  'file extension to use for import statements in generated files (e.g. ".ts", ".mts", ".cts"). Use --import-ext "" to generate extension-less imports.',
77
77
  },
78
- fileExt: {
78
+ 'file-ext': {
79
79
  type: 'string',
80
80
  default: '.ts',
81
81
  describe:
82
82
  'file extension to use for generated files (e.g. ".ts", ".mts", ".cts")',
83
83
  },
84
- indexFile: {
84
+ 'index-file': {
85
85
  type: 'boolean',
86
86
  default: false,
87
87
  describe:
88
88
  'generate an "index.<fileExt>" file that exports all root-level namespaces',
89
89
  },
90
- defsExport: {
90
+ 'defs-export': {
91
91
  type: 'boolean',
92
92
  default: false,
93
93
  describe:
94
94
  'when some definitions conflict with child namespaces, this option allows to export lexicon definitions under a separate $defs namespace (e.g. com.example.foo.$defs)',
95
95
  },
96
- defaultExport: {
96
+ 'default-export': {
97
97
  type: 'boolean',
98
98
  default: true,
99
99
  describe:
100
100
  'whether to generate a default export for the "main" lexicon definition schema in the parent namespace file',
101
101
  },
102
- ignoreInvalidLexicons: {
102
+ 'ignore-invalid-lexicons': {
103
103
  type: 'boolean',
104
104
  default: false,
105
105
  describe:
@@ -159,4 +159,6 @@ yargs(hideBin(process.argv))
159
159
  })
160
160
  },
161
161
  )
162
+ .strictCommands()
163
+ .demandCommand(1)
162
164
  .parseAsync()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },
@@ -36,13 +36,13 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "tslib": "^2.8.1",
39
- "yargs": "^17.0.0",
39
+ "yargs": "^18.0.0",
40
40
  "@atproto/lex-builder": "^0.1.2",
41
- "@atproto/lex-client": "^0.1.2",
41
+ "@atproto/lex-client": "^0.1.3",
42
42
  "@atproto/lex-data": "^0.1.1",
43
43
  "@atproto/lex-json": "^0.1.0",
44
44
  "@atproto/lex-installer": "^0.1.0",
45
- "@atproto/lex-schema": "^0.1.1"
45
+ "@atproto/lex-schema": "^0.1.2"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/yargs": "^17.0.33",