@atproto/lex 0.1.1 → 0.1.2

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,19 @@
1
1
  # @atproto/lex
2
2
 
3
+ ## 0.1.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4984](https://github.com/bluesky-social/atproto/pull/4984) [`5bdb4ad`](https://github.com/bluesky-social/atproto/commit/5bdb4addd6a3798bf6c8c391c74044b3e251008a) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Add `default` export of "main" schema in the namespace file
8
+
9
+ - [#4979](https://github.com/bluesky-social/atproto/pull/4979) [`314df62`](https://github.com/bluesky-social/atproto/commit/314df62537bb519231aa375dd3a38360afc79ce0) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Always add `#__PURE__` annotations to function calls
10
+
11
+ - [#4983](https://github.com/bluesky-social/atproto/pull/4983) [`1259646`](https://github.com/bluesky-social/atproto/commit/125964673962a86282a05bf22f410fad8ad06b41) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Make the generation of the `$defs` namespace optional by default
12
+
13
+ - Updated dependencies [[`3aae4fe`](https://github.com/bluesky-social/atproto/commit/3aae4fe43448dca860fc6c4a24d18bfa64de084b), [`5bdb4ad`](https://github.com/bluesky-social/atproto/commit/5bdb4addd6a3798bf6c8c391c74044b3e251008a), [`3aae4fe`](https://github.com/bluesky-social/atproto/commit/3aae4fe43448dca860fc6c4a24d18bfa64de084b), [`314df62`](https://github.com/bluesky-social/atproto/commit/314df62537bb519231aa375dd3a38360afc79ce0), [`1259646`](https://github.com/bluesky-social/atproto/commit/125964673962a86282a05bf22f410fad8ad06b41), [`482767c`](https://github.com/bluesky-social/atproto/commit/482767c4bcce95aa390b2992b028fd8e27d162b2)]:
14
+ - @atproto/lex-builder@0.1.2
15
+ - @atproto/lex-client@0.1.2
16
+
3
17
  ## 0.1.1
4
18
 
5
19
  ### Patch Changes
package/README.md CHANGED
@@ -54,6 +54,14 @@ const posts = await client.list(app.bsky.feed.post, { limit: 10 })
54
54
  - [Type definitions](#type-definitions)
55
55
  - [Building data](#building-data)
56
56
  - [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)
57
65
  - [Data Model](#data-model)
58
66
  - [Types](#types)
59
67
  - [JSON Encoding](#json-encoding)
@@ -61,20 +69,56 @@ const posts = await client.list(app.bsky.feed.post, { limit: 10 })
61
69
  - [Making simple XRPC Requests](#making-simple-xrpc-requests)
62
70
  - [Client API](#client-api)
63
71
  - [Creating a Client](#creating-a-client)
72
+ - [Unauthenticated Client](#unauthenticated-client)
73
+ - [Authenticated Client with OAuth](#authenticated-client-with-oauth)
74
+ - [Authenticated Client with Password](#authenticated-client-with-password)
75
+ - [Client with Service Proxy (authenticated only)](#client-with-service-proxy-authenticated-only)
76
+ - [Validation and Strictness Options](#validation-and-strictness-options)
64
77
  - [Core Methods](#core-methods)
78
+ - [`client.call()`](#clientcall)
79
+ - [`client.create()`](#clientcreate)
80
+ - [`client.get()`](#clientget)
81
+ - [`client.put()`](#clientput)
82
+ - [`client.delete()`](#clientdelete)
83
+ - [`client.list()`](#clientlist)
84
+ - [`client.applyWrites()`](#clientapplywrites)
65
85
  - [Error Handling](#error-handling)
86
+ - [Safe Methods](#safe-methods)
87
+ - [XrpcFailure Type](#xrpcfailure-type)
66
88
  - [Authentication Methods](#authentication-methods)
89
+ - [`client.did`](#clientdid)
90
+ - [`client.assertAuthenticated()`](#clientassertauthenticated)
91
+ - [`client.assertDid`](#clientassertdid)
67
92
  - [Labeler Configuration](#labeler-configuration)
68
93
  - [Low-Level XRPC](#low-level-xrpc)
69
94
  - [Utilities](#utilities)
70
95
  - [Datetime Strings](#datetime-strings)
71
96
  - [Advanced Usage](#advanced-usage)
72
97
  - [Workflow Integration](#workflow-integration)
98
+ - [Development Workflow](#development-workflow)
73
99
  - [Tree-Shaking](#tree-shaking)
100
+ - [Namespace notation](#namespace-notation)
101
+ - [Explicit `.main` reference](#explicit-main-reference)
102
+ - [Direct named import from the schema file](#direct-named-import-from-the-schema-file)
103
+ - [Default import (recommended)](#default-import-recommended)
104
+ - [Drawbacks of the default export](#drawbacks-of-the-default-export)
105
+ - [Summary](#summary)
74
106
  - [Blob references](#blob-references)
107
+ - [TypedBlobRef: The Current Standard](#typedblobref-the-current-standard)
108
+ - [LegacyBlobRef: Historical Format](#legacyblobref-historical-format)
109
+ - [Working with Both Formats](#working-with-both-formats)
75
110
  - [Actions](#actions)
111
+ - [What are Actions?](#what-are-actions)
112
+ - [Using Actions](#using-actions)
113
+ - [Composing Multiple Operations](#composing-multiple-operations)
114
+ - [Higher-Order Actions](#higher-order-actions)
76
115
  - [Creating a Client from Another Client](#creating-a-client-from-another-client)
77
116
  - [Building Library-Style APIs with Actions](#building-library-style-apis-with-actions)
117
+ - [Creating Posts](#creating-posts)
118
+ - [Following Users](#following-users)
119
+ - [Updating Profile with Retry Logic](#updating-profile-with-retry-logic)
120
+ - [Packaging Actions as a Library](#packaging-actions-as-a-library)
121
+ - [Best Practices for Actions](#best-practices-for-actions)
78
122
  - [Standard Schema Compatibility](#standard-schema-compatibility)
79
123
  - [License](#license)
80
124
 
@@ -197,6 +241,7 @@ Options:
197
241
  - `--importExt <ext>` - File extension to use for import statements in generated files (default: `.js`). Use `--importExt ""` to generate extension-less imports
198
242
  - `--fileExt <ext>` - File extension to use for generated files (default: `.ts`)
199
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))
200
245
 
201
246
  ### Generated Schema Structure
202
247
 
@@ -1064,24 +1109,104 @@ This ensures that:
1064
1109
 
1065
1110
  ### Tree-Shaking
1066
1111
 
1067
- The generated TypeScript is optimized for tree-shaking. Import only what you need:
1112
+ The generated TypeScript code is structured to be tree-shakeable, but the way you reference schemas has a meaningful impact on the final bundle size. There are several ways to refer to a generated schema, and each comes with different trade-offs.
1113
+
1114
+ #### Namespace notation
1115
+
1116
+ The most ergonomic style is to use a namespace import and reference schemas through dotted paths:
1068
1117
 
1069
1118
  ```typescript
1070
- // Import specific methods
1071
- import { post } from './lexicons/app/bsky/feed/post.js'
1072
- import { getProfile } from './lexicons/app/bsky/actor/getProfile.js'
1119
+ import * as com from './lexicons/com.js'
1073
1120
 
1074
- // Or use namespace imports (still tree-shakeable)
1075
- import * as app from './lexicons/app.js'
1121
+ await client.call(com.atproto.repo.getRecord, {
1122
+ /* ... */
1123
+ })
1124
+ ```
1125
+
1126
+ This style is convenient and reads naturally as it mirrors the NSID of the schema. However, it produces the largest bundles. From the bundler's point of view, `com.atproto.repo.getRecord` is the whole schema namespace (which contains the `main` schema as well as helpers, and any other definitions). The bundler cannot know that `client.call()` only consumes the `main` schema, so it has to keep the rest of the namespace alive in the bundle.
1127
+
1128
+ #### Explicit `.main` reference
1129
+
1130
+ You can mitigate the bundle-size cost by explicitly naming the `main` definition:
1131
+
1132
+ ```typescript
1133
+ import * as com from './lexicons/com.js'
1134
+
1135
+ await client.call(com.atproto.repo.getRecord.main, {
1136
+ /* ... */
1137
+ })
1138
+ ```
1139
+
1140
+ This lets the bundler drop the sibling definitions inside `getRecord` that aren't referenced. The drawback is that it leaks an implementation detail: the `main` segment of the path. In Lexicon, `main` is typically implicit:
1141
+
1142
+ - Records use a `$type` of `app.bsky.feed.post` (no `#main`)
1143
+ - XRPC endpoints are exposed as `/xrpc/com.atproto.repo.getRecord` (no `main`)
1144
+
1145
+ So writing `.main` in application code feels verbose compared to how Lexicons are normally referred to.
1146
+
1147
+ #### Direct named import from the schema file
1148
+
1149
+ You can also import the `main` schema directly from the file that defines it:
1150
+
1151
+ ```typescript
1152
+ import { main as getRecord } from './lexicons/com/atproto/repo/getRecord.js'
1153
+
1154
+ await client.call(getRecord, {
1155
+ /* ... */
1156
+ })
1157
+ ```
1158
+
1159
+ This produces equally small bundles as the explicit `.main` reference, but it still surfaces the `main` identifier: you have to know to import `main` and likely rename it.
1160
+
1161
+ #### Default import (recommended)
1162
+
1163
+ To make the small-bundle path also the ergonomic path, every namespace file generated by `lex build` re-exports the `main` schema as its `default` export:
1164
+
1165
+ ```typescript
1166
+ // generated file: ./lexicons/com/atproto/repo/getRecord.js
1167
+ export * from './getRecord.defs.js'
1168
+ export { main as default } from './getRecord.defs.js'
1169
+ ```
1170
+
1171
+ This means you can write:
1172
+
1173
+ ```typescript
1174
+ import getRecord from './lexicons/com/atproto/repo/getRecord.js'
1175
+ import post from './lexicons/app/bsky/feed/post.js'
1176
+
1177
+ await client.call(getRecord, {
1178
+ /* ... */
1179
+ })
1180
+ await client.create(post, {
1181
+ /* ... */
1182
+ })
1076
1183
  ```
1077
1184
 
1078
- For library authors, use `--pure-annotations` when building:
1185
+ This is the most bundle-friendly style: the bundler only pulls in the `main` schema, and the import name doesn't have to mention `main` at all. This helps keeping application code aligned with how Lexicons are usually identified.
1186
+
1187
+ #### Drawbacks of the default export
1188
+
1189
+ The `default` re-export is enabled by default but has two minor drawbacks:
1190
+
1191
+ 1. It is one additional property on the namespace module, which can very slightly increase bundle size if you also use the namespace in some places.
1192
+ 2. Any Lexicon document whose path segment is literally `default` (for example a hypothetical `com.example.records.default`) would conflict with the generated `default` export.
1193
+
1194
+ If either of these matters for your use case, you can disable the generation of `default` exports with the `--no-defaultExport` flag:
1079
1195
 
1080
1196
  ```bash
1081
- lex build --pure-annotations
1197
+ lex build --no-defaultExport
1082
1198
  ```
1083
1199
 
1084
- This will make the generated code more easily tree-shakeable from places that import your library.
1200
+ #### Summary
1201
+
1202
+ | Style | Bundle size | Ergonomics |
1203
+ | ------------------------------------------------------ | ----------- | ---------------------------- |
1204
+ | `com.atproto.repo.getRecord` (namespace) | Largest | Best: matches the NSID |
1205
+ | `com.atproto.repo.getRecord.main` | Small | Leaks the `main` identifier |
1206
+ | `import { main as getRecord } from '.../getRecord.js'` | Small | Verbose, leaks `main` |
1207
+ | `import getRecord from '.../getRecord.js'` | Small | Concise, no `main` in source |
1208
+
1209
+ For libraries and applications where bundle size matters (typically anything shipped to a browser), prefer the default-import style. For scripts, tests, and server-side code where the bundle size of generated schemas is not a concern, the namespace style is perfectly fine.
1085
1210
 
1086
1211
  ### Blob references
1087
1212
 
package/bin/lex CHANGED
@@ -51,12 +51,6 @@ yargs(hideBin(process.argv))
51
51
  default: false,
52
52
  describe: 'how to handle errors when processing input files',
53
53
  },
54
- 'pure-annotations': {
55
- type: 'boolean',
56
- default: false,
57
- describe:
58
- 'adds `/*#__PURE__*/` annotations for tree-shaking tools. Set this to true if you are using generated lexicons in a library.',
59
- },
60
54
  exclude: {
61
55
  array: true,
62
56
  type: 'string',
@@ -93,6 +87,18 @@ yargs(hideBin(process.argv))
93
87
  describe:
94
88
  'generate an "index.<fileExt>" file that exports all root-level namespaces',
95
89
  },
90
+ defsExport: {
91
+ type: 'boolean',
92
+ default: false,
93
+ describe:
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
+ },
96
+ defaultExport: {
97
+ type: 'boolean',
98
+ default: true,
99
+ describe:
100
+ 'whether to generate a default export for the "main" lexicon definition schema in the parent namespace file',
101
+ },
96
102
  ignoreInvalidLexicons: {
97
103
  type: 'boolean',
98
104
  default: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },
@@ -37,8 +37,8 @@
37
37
  "dependencies": {
38
38
  "tslib": "^2.8.1",
39
39
  "yargs": "^17.0.0",
40
- "@atproto/lex-builder": "^0.1.1",
41
- "@atproto/lex-client": "^0.1.1",
40
+ "@atproto/lex-builder": "^0.1.2",
41
+ "@atproto/lex-client": "^0.1.2",
42
42
  "@atproto/lex-data": "^0.1.1",
43
43
  "@atproto/lex-json": "^0.1.0",
44
44
  "@atproto/lex-installer": "^0.1.0",