@atproto/lex 0.0.8 → 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 +16 -0
- package/README.md +168 -11
- package/bin/lex +6 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
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
|
+
|
|
3
19
|
## 0.0.8
|
|
4
20
|
|
|
5
21
|
### 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
|
|
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
|
-
|
|
213
|
-
type
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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 (
|
|
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
|
|
@@ -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
|
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
package/dist/index.d.ts.map
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Lexicon tooling for AT",
|
|
6
6
|
"keywords": [
|
|
@@ -36,10 +36,12 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"tslib": "^2.8.1",
|
|
38
38
|
"yargs": "^17.0.0",
|
|
39
|
-
"@atproto/lex-builder": "0.0.
|
|
40
|
-
"@atproto/lex-client": "0.0.
|
|
41
|
-
"@atproto/lex-
|
|
42
|
-
"@atproto/lex-
|
|
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",
|