@atproto/lex 0.0.23 → 0.0.24

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,21 @@
1
1
  # @atproto/lex
2
2
 
3
+ ## 0.0.24
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4828](https://github.com/bluesky-social/atproto/pull/4828) [`c62651d`](https://github.com/bluesky-social/atproto/commit/c62651dd69f1e18bd854b66e499b91fee9eaa856) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Accept legacy blob references in non-strict mode. Legacy blob references (objects with `cid` and `mimeType` properties) are now accepted when `strict: false`, which is the default behavior when `strictResponseProcessing` is disabled on the Client.
8
+
9
+ BREAKING: The `allowLegacy` option has been removed from the blob schema builder, and legacy blobs are now handled automatically based on the strictness mode: in strict mode they are rejected, and in non-strict mode they are accepted. Consumers should stop passing `allowLegacy` and rely on strictness configuration instead. Likewise, CLI consumers should stop using the removed `--allowLegacyBlobs` flag and use the default strict/non-strict behavior.
10
+
11
+ - Updated dependencies [[`c62651d`](https://github.com/bluesky-social/atproto/commit/c62651dd69f1e18bd854b66e499b91fee9eaa856), [`f6f100c`](https://github.com/bluesky-social/atproto/commit/f6f100c33700a7ff58a1458109cc7420131feed0), [`b6b231f`](https://github.com/bluesky-social/atproto/commit/b6b231f9c05cf90239d4a29aa0ae2592ea5ce928), [`c62651d`](https://github.com/bluesky-social/atproto/commit/c62651dd69f1e18bd854b66e499b91fee9eaa856), [`c62651d`](https://github.com/bluesky-social/atproto/commit/c62651dd69f1e18bd854b66e499b91fee9eaa856), [`f6f100c`](https://github.com/bluesky-social/atproto/commit/f6f100c33700a7ff58a1458109cc7420131feed0), [`f6f100c`](https://github.com/bluesky-social/atproto/commit/f6f100c33700a7ff58a1458109cc7420131feed0)]:
12
+ - @atproto/lex-data@0.0.15
13
+ - @atproto/lex-client@0.0.19
14
+ - @atproto/lex-schema@0.0.18
15
+ - @atproto/lex-json@0.0.15
16
+ - @atproto/lex-installer@0.0.24
17
+ - @atproto/lex-builder@0.0.21
18
+
3
19
  ## 0.0.23
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -194,7 +194,6 @@ Options:
194
194
  - `--exclude <patterns...>` - List of strings or regex patterns to exclude lexicon documents by their IDs
195
195
  - `--include <patterns...>` - List of strings or regex patterns to include lexicon documents by their IDs
196
196
  - `--lib <package>` - Package name of the library to import the lex schema utility "l" from (default: `@atproto/lex`)
197
- - `--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)
198
197
  - `--importExt <ext>` - File extension to use for import statements in generated files (default: `.js`). Use `--importExt ""` to generate extension-less imports
199
198
  - `--fileExt <ext>` - File extension to use for generated files (default: `.ts`)
200
199
  - `--indexFile` - Generate an "index" file that re-exports all root-level namespaces (disabled by default)
@@ -351,7 +350,7 @@ if (result.success) {
351
350
  }
352
351
  ```
353
352
 
354
- All schema methods that perform validation (`$parse`, `$safeParse`, `$validate`, `$safeValidate`) accept an optional `{ strict }` option. When `strict` is `false`, validation becomes more lenient: datetime string format checks are relaxed (e.g. datetimes without timezones are accepted; other string formats remain strict), blob MIME type and size constraints are not enforced, and non-raw CIDs are allowed in blob references. This is primarily used internally by the XRPC client when `strictResponseProcessing` is disabled, but can also be used directly:
353
+ All schema methods that perform validation (`$parse`, `$safeParse`, `$validate`, `$safeValidate`) accept an optional `{ strict }` option. When `strict` is `false`, validation becomes more lenient: datetime string format checks are relaxed (e.g. datetimes without timezones are accepted; other string formats remain strict), blob MIME type and size constraints are not enforced, non-raw CIDs are allowed in blob references, and legacy blob reference format (objects with `cid` and `mimeType` properties) is accepted. This is primarily used internally by the XRPC client when `strictResponseProcessing` is disabled, but can also be used directly:
355
354
 
356
355
  ```typescript
357
356
  // Strict mode (default) - rejects datetime without timezone
@@ -611,7 +610,7 @@ const client = new Client(session, {
611
610
 
612
611
  - **`validateRequest`** — When `true`, outgoing request bodies are validated against the Lexicon input schema before sending. Useful in development to catch errors early. Default: `false`.
613
612
  - **`validateResponse`** — When `true`, incoming response bodies are validated against the Lexicon output schema. Disabling this can improve performance when you trust the upstream service. Default: `true`.
614
- - **`strictResponseProcessing`** — When `true` (default), the client will strictly process responses according to Lex encoding rules, rejecting responses containing invalid Lex data (e.g. floating-point numbers, malformed `$bytes` or `$link` objects). When `false`, the client accepts such responses in a lenient mode: invalid values are returned as-is rather than being rejected or converted, `datetime` string format checks become more lenient (e.g. datetimes without timezones are accepted) while other string formats remain strict, blob MIME type and size constraints are not enforced, and legacy blob references are coerced into standard `BlobRef` objects. Default: `true`.
613
+ - **`strictResponseProcessing`** — When `true` (default), the client will strictly process responses according to Lex encoding rules, rejecting responses containing invalid Lex data (e.g. floating-point numbers, malformed `$bytes` or `$link` objects). When `false`, the client accepts such responses in a lenient mode: invalid values are returned as-is rather than being rejected or converted, `datetime` string format checks become more lenient (e.g. datetimes without timezones are accepted) while other string formats remain strict, blob MIME type and size constraints are not enforced, and legacy blob reference format (objects with `cid` and `mimeType` properties) is accepted. Default: `true`.
615
614
 
616
615
  ### Core Methods
617
616
 
@@ -932,8 +931,16 @@ import {
932
931
  ifDatetimeString, // Returns DatetimeString or undefined
933
932
 
934
933
  // Blob references
935
- BlobRef, // { $type: 'blob', ref: Cid, mimeType: string, size: number }
936
- isBlobRef, // Type guard for BlobRef objects
934
+ BlobRef, // TypedBlobRef | LegacyBlobRef
935
+ LegacyBlobRef, // { cid: string, mimeType: string }
936
+ TypedBlobRef, // { $type: 'blob', ref: Cid, mimeType: string, size: number }
937
+ isBlobRef, // Type guard for BlobRef (accepts both TypedBlobRef and LegacyBlobRef)
938
+ isLegacyBlobRef, // Type guard for LegacyBlobRef objects
939
+ isTypedBlobRef, // Type guard for TypedBlobRef objects
940
+ getBlobCid, // Extract Cid from BlobRef or LegacyBlobRef
941
+ getBlobCidString, // Extract CID string from BlobRef or LegacyBlobRef
942
+ getBlobMime, // Extract MIME type from BlobRef or LegacyBlobRef
943
+ getBlobSize, // Extract size from BlobRef (returns undefined for LegacyBlobRef)
937
944
 
938
945
  // Equality
939
946
  lexEquals, // Deep equality (handles CIDs and bytes)
@@ -1035,37 +1042,96 @@ This will make the generated code more easily tree-shakeable from places that im
1035
1042
 
1036
1043
  ### Blob references
1037
1044
 
1038
- 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.
1045
+ In AT Protocol, binary data (blobs) are referenced using blob references, which include metadata like MIME type and size. These references allow PDSs to determine which binary data ("files") is referenced by records.
1046
+
1047
+ #### TypedBlobRef: The Current Standard
1048
+
1049
+ The current standard format for blob references is `TypedBlobRef`:
1039
1050
 
1040
1051
  ```typescript
1041
- import { BlobRef, isBlobRef } from '@atproto/lex'
1052
+ import { TypedBlobRef } from '@atproto/lex'
1042
1053
 
1043
- const blobRef: BlobRef = {
1054
+ const blobRef: TypedBlobRef = {
1044
1055
  $type: 'blob',
1045
1056
  ref: parseCid('bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku'),
1046
1057
  mimeType: 'image/png',
1047
1058
  size: 12345,
1048
1059
  }
1060
+ ```
1061
+
1062
+ **When creating new blobs**, always use the `TypedBlobRef` format. This is the format returned by `client.uploadBlob()` and expected by PDS endpoints.
1063
+
1064
+ #### LegacyBlobRef: Historical Format
1049
1065
 
1050
- if (isBlobRef(blobRef)) {
1051
- console.log('Valid BlobRef:', blobRef.mimeType, blobRef.size)
1066
+ Historically, blob references used a simpler format without the `$type` property:
1067
+
1068
+ ```typescript
1069
+ type LegacyBlobRef = {
1070
+ cid: string // CID as a string (not a Cid object)
1071
+ mimeType: string // No size property
1052
1072
  }
1053
1073
  ```
1054
1074
 
1055
- > [!NOTE]
1075
+ **Legacy blob references still exist in the AT Protocol network** in older records created before the format migration. While new blobs should always be created as `TypedBlobRef`, your code must be prepared to handle both formats when reading existing data.
1076
+
1077
+ #### Working with Both Formats
1078
+
1079
+ The `BlobRef` type is a union that accepts both formats:
1080
+
1081
+ ```typescript
1082
+ import {
1083
+ BlobRef,
1084
+ isBlobRef,
1085
+ isTypedBlobRef,
1086
+ isLegacyBlobRef,
1087
+ } from '@atproto/lex'
1088
+
1089
+ // When reading data, always use BlobRef to handle both formats
1090
+ function processBlobRef(blob: BlobRef) {
1091
+ if (isTypedBlobRef(blob)) {
1092
+ console.log('Modern blob:', blob.ref, blob.mimeType, blob.size)
1093
+ } else if (isLegacyBlobRef(blob)) {
1094
+ console.log('Legacy blob:', blob.cid, blob.mimeType)
1095
+ }
1096
+ }
1097
+
1098
+ // Or use the isBlobRef type guard which accepts both
1099
+ if (isBlobRef(value)) {
1100
+ // value is BlobRef (either TypedBlobRef or LegacyBlobRef)
1101
+ }
1102
+ ```
1103
+
1104
+ Helper functions work with both formats:
1105
+
1106
+ ```typescript
1107
+ import {
1108
+ getBlobCid,
1109
+ getBlobCidString,
1110
+ getBlobMime,
1111
+ getBlobSize,
1112
+ } from '@atproto/lex'
1113
+
1114
+ // These utilities work with both TypedBlobRef and LegacyBlobRef
1115
+ const cid = getBlobCid(blobRef) // Returns Cid object
1116
+ const cidStr = getBlobCidString(blobRef) // Returns string (optimized)
1117
+ const mime = getBlobMime(blobRef) // Returns mimeType
1118
+ const size = getBlobSize(blobRef) // Returns number | undefined (legacy refs lack size)
1119
+ ```
1120
+
1121
+ > [!IMPORTANT]
1056
1122
  >
1057
- > Historically, references to blobs were represented as simple objects with the following structure:
1123
+ > **Validation behavior with legacy blobs:**
1058
1124
  >
1059
- > ```typescript
1060
- > type LegacyBlobRef = {
1061
- > cid: string
1062
- > mimeType: string
1063
- > }
1064
- > ```
1125
+ > - In **strict mode** (`strict: true`, the default): Legacy blob references are rejected during validation. Use this mode when you control the data source and expect only modern blobs.
1126
+ > - In **non-strict mode** (`strict: false`): Legacy blob references are accepted. This mode is used automatically when `strictResponseProcessing: false` is set on the Client, allowing your application to handle older records from the network gracefully.
1065
1127
  >
1066
- > 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.
1128
+ > ```typescript
1129
+ > // Strict mode (default) - rejects legacy blobs
1130
+ > schema.$safeParse(data) // { strict: true }
1067
1131
  >
1068
- > When using non-strict validation (e.g. `$safeParse(data, { strict: false })`), legacy blob references are automatically coerced into standard `BlobRef` objects with `size: -1`, even without `--allowLegacyBlobs`.
1132
+ > // Non-strict mode - accepts legacy blobs
1133
+ > schema.$safeParse(data, { strict: false })
1134
+ > ```
1069
1135
 
1070
1136
  ### Actions
1071
1137
 
package/bin/lex CHANGED
@@ -76,12 +76,6 @@ yargs(hideBin(process.argv))
76
76
  describe:
77
77
  'package name of the library to import the lex schema utility "l" from',
78
78
  },
79
- allowLegacyBlobs: {
80
- type: 'boolean',
81
- default: false,
82
- describe:
83
- 'generate schemas that accept legacy blob references (disabled by default; enable this if you encounter issues while processing records created a long time ago)',
84
- },
85
79
  importExt: {
86
80
  type: 'string',
87
81
  default: '.js',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "license": "MIT",
5
5
  "description": "Lexicon tooling for AT",
6
6
  "keywords": [
@@ -38,12 +38,12 @@
38
38
  "dependencies": {
39
39
  "tslib": "^2.8.1",
40
40
  "yargs": "^17.0.0",
41
- "@atproto/lex-builder": "^0.0.20",
42
- "@atproto/lex-client": "^0.0.18",
43
- "@atproto/lex-data": "^0.0.14",
44
- "@atproto/lex-json": "^0.0.14",
45
- "@atproto/lex-installer": "^0.0.23",
46
- "@atproto/lex-schema": "^0.0.17"
41
+ "@atproto/lex-builder": "^0.0.21",
42
+ "@atproto/lex-client": "^0.0.19",
43
+ "@atproto/lex-data": "^0.0.15",
44
+ "@atproto/lex-json": "^0.0.15",
45
+ "@atproto/lex-installer": "^0.0.24",
46
+ "@atproto/lex-schema": "^0.0.18"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/yargs": "^17.0.33",