@atproto/lex-data 0.0.15 → 0.1.0-next.0

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/blob.js +16 -26
  3. package/dist/blob.js.map +1 -1
  4. package/dist/cid.d.ts.map +1 -1
  5. package/dist/cid.js +75 -79
  6. package/dist/cid.js.map +1 -1
  7. package/dist/index.js +8 -11
  8. package/dist/index.js.map +1 -1
  9. package/dist/lex-equals.js +9 -12
  10. package/dist/lex-equals.js.map +1 -1
  11. package/dist/lex-error.js +2 -7
  12. package/dist/lex-error.js.map +1 -1
  13. package/dist/lex.js +10 -17
  14. package/dist/lex.js.map +1 -1
  15. package/dist/lib/nodejs-buffer.d.ts +3 -0
  16. package/dist/lib/nodejs-buffer.d.ts.map +1 -1
  17. package/dist/lib/nodejs-buffer.js +1 -4
  18. package/dist/lib/nodejs-buffer.js.map +1 -1
  19. package/dist/lib/util.js +2 -6
  20. package/dist/lib/util.js.map +1 -1
  21. package/dist/object.js +3 -8
  22. package/dist/object.js.map +1 -1
  23. package/dist/uint8array-base64.js +1 -2
  24. package/dist/uint8array-concat.d.ts +2 -2
  25. package/dist/uint8array-concat.d.ts.map +1 -1
  26. package/dist/uint8array-concat.js +4 -8
  27. package/dist/uint8array-concat.js.map +1 -1
  28. package/dist/uint8array-from-base64.js +7 -11
  29. package/dist/uint8array-from-base64.js.map +1 -1
  30. package/dist/uint8array-to-base64.js +7 -11
  31. package/dist/uint8array-to-base64.js.map +1 -1
  32. package/dist/uint8array.d.ts +1 -1
  33. package/dist/uint8array.d.ts.map +1 -1
  34. package/dist/uint8array.js +17 -23
  35. package/dist/uint8array.js.map +1 -1
  36. package/dist/utf8-from-base64.js +6 -10
  37. package/dist/utf8-from-base64.js.map +1 -1
  38. package/dist/utf8-from-bytes.js +4 -8
  39. package/dist/utf8-from-bytes.js.map +1 -1
  40. package/dist/utf8-grapheme-len.js +4 -8
  41. package/dist/utf8-grapheme-len.js.map +1 -1
  42. package/dist/utf8-len.js +4 -8
  43. package/dist/utf8-len.js.map +1 -1
  44. package/dist/utf8-to-base64.js +8 -12
  45. package/dist/utf8-to-base64.js.map +1 -1
  46. package/dist/utf8.js +15 -18
  47. package/dist/utf8.js.map +1 -1
  48. package/package.json +7 -8
  49. package/src/cid-implementation.test.ts +3 -3
  50. package/src/cid.ts +1 -0
  51. package/src/core-js.d.ts +2 -0
  52. package/src/lib/nodejs-buffer.ts +5 -0
  53. package/src/uint8array-concat.ts +7 -3
  54. package/src/uint8array-from-base64.test.ts +2 -2
  55. package/src/uint8array-to-base64.test.ts +2 -2
  56. package/src/uint8array.test.ts +2 -2
  57. package/tsconfig.tests.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atproto/lex-data
2
2
 
3
+ ## 0.1.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#4929](https://github.com/bluesky-social/atproto/pull/4929) [`bb7491c`](https://github.com/bluesky-social/atproto/commit/bb7491c29e06181e1d2f8cf6eb454f9bb8ab961b) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Drop support for Node.js 18 and 20. Node.js 22 is now the minimum supported version. Docker images now use Node.js 24.
8
+
9
+ - [#4943](https://github.com/bluesky-social/atproto/pull/4943) [`07ae5d4`](https://github.com/bluesky-social/atproto/commit/07ae5d4452df51e045e0239da7a04cf0bc154028) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Convert to pure ESM. All packages now ship `"type": "module"` with ES module output and Node16 module resolution.
10
+
11
+ Node.js 22's `require()` compatibility layer can still load these packages in CommonJS code.
12
+
13
+ - [#4930](https://github.com/bluesky-social/atproto/pull/4930) [`042df15`](https://github.com/bluesky-social/atproto/commit/042df15087c0e62cd1e715fcbf58852fab875af9) Thanks [@devinivy](https://github.com/devinivy)! - Build with TypeScript 6.0. Emitted `.d.ts` files now use TypeScript 6's stricter `Uint8Array<ArrayBuffer>` typing in places where Web/Node APIs require buffer-backed (not shared-memory) byte arrays. Consumers compiling against these types on older TypeScript should see no runtime impact, but may need to widen or cast in spots that previously relied on `Uint8Array` defaulting to `<ArrayBufferLike>`.
14
+
15
+ Internal: tsconfig `moduleResolution: "node"` is silenced via `ignoreDeprecations: "6.0"` for now; the proper migration to `node16`/`bundler` resolution is deferred.
16
+
3
17
  ## 0.0.15
4
18
 
5
19
  ### Patch Changes
package/dist/blob.js CHANGED
@@ -1,15 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isBlobRef = isBlobRef;
4
- exports.getBlobMime = getBlobMime;
5
- exports.getBlobSize = getBlobSize;
6
- exports.getBlobCid = getBlobCid;
7
- exports.getBlobCidString = getBlobCidString;
8
- exports.isTypedBlobRef = isTypedBlobRef;
9
- exports.isLegacyBlobRef = isLegacyBlobRef;
10
- exports.enumBlobRefs = enumBlobRefs;
11
- const cid_js_1 = require("./cid.js");
12
- const object_js_1 = require("./object.js");
1
+ import { ifCid, parseCid, validateCidString, } from './cid.js';
2
+ import { isPlainObject, isPlainProto } from './object.js';
13
3
  /**
14
4
  * Options to use with {@link ifCid}, {@link validateCidString}, and related CID
15
5
  * validation functions when validating CIDs in BlobRefs, in strict mode. This
@@ -21,12 +11,12 @@ const STRICT_CID_CHECK_OPTIONS = { flavor: 'raw' };
21
11
  // Number.isSafeInteger is actually safe to use with non-number values, so we
22
12
  // can use it as a type guard.
23
13
  const isSafeInteger = Number.isSafeInteger;
24
- function isBlobRef(input, options) {
14
+ export function isBlobRef(input, options) {
25
15
  return input?.$type === 'blob'
26
16
  ? isTypedBlobRef(input, options)
27
17
  : isLegacyBlobRef(input, options);
28
18
  }
29
- function getBlobMime(blob) {
19
+ export function getBlobMime(blob) {
30
20
  return blob?.mimeType;
31
21
  }
32
22
  /**
@@ -51,24 +41,24 @@ function getBlobMime(blob) {
51
41
  * }
52
42
  * ```
53
43
  */
54
- function getBlobSize(blob) {
44
+ export function getBlobSize(blob) {
55
45
  if ('$type' in blob && blob.size >= 0)
56
46
  return blob.size;
57
47
  // LegacyBlobRef doesn't have size information
58
48
  return undefined;
59
49
  }
60
- function getBlobCid(blob) {
50
+ export function getBlobCid(blob) {
61
51
  if (!blob)
62
52
  return undefined;
63
- return '$type' in blob ? blob.ref : (0, cid_js_1.parseCid)(blob.cid);
53
+ return '$type' in blob ? blob.ref : parseCid(blob.cid);
64
54
  }
65
- function getBlobCidString(blob) {
55
+ export function getBlobCidString(blob) {
66
56
  if (!blob)
67
57
  return undefined;
68
58
  return '$type' in blob ? blob.ref.toString() : blob.cid;
69
59
  }
70
- function isTypedBlobRef(input, options) {
71
- if (!(0, object_js_1.isPlainObject)(input)) {
60
+ export function isTypedBlobRef(input, options) {
61
+ if (!isPlainObject(input)) {
72
62
  return false;
73
63
  }
74
64
  if (input?.$type !== 'blob') {
@@ -97,7 +87,7 @@ function isTypedBlobRef(input, options) {
97
87
  return false;
98
88
  }
99
89
  }
100
- const cid = (0, cid_js_1.ifCid)(ref,
90
+ const cid = ifCid(ref,
101
91
  // Strict unless explicitly disabled
102
92
  options?.strict === false ? undefined : STRICT_CID_CHECK_OPTIONS);
103
93
  if (!cid) {
@@ -125,8 +115,8 @@ function isTypedBlobRef(input, options) {
125
115
  *
126
116
  * @see {@link isTypedBlobRef} for checking the current blob reference format
127
117
  */
128
- function isLegacyBlobRef(input, options) {
129
- if (!(0, object_js_1.isPlainObject)(input)) {
118
+ export function isLegacyBlobRef(input, options) {
119
+ if (!isPlainObject(input)) {
130
120
  return false;
131
121
  }
132
122
  const { cid, mimeType } = input;
@@ -141,12 +131,12 @@ function isLegacyBlobRef(input, options) {
141
131
  return false;
142
132
  }
143
133
  }
144
- if (!(0, cid_js_1.validateCidString)(cid, options?.strict === false ? undefined : STRICT_CID_CHECK_OPTIONS)) {
134
+ if (!validateCidString(cid, options?.strict === false ? undefined : STRICT_CID_CHECK_OPTIONS)) {
145
135
  return false;
146
136
  }
147
137
  return true;
148
138
  }
149
- function* enumBlobRefs(input, options) {
139
+ export function* enumBlobRefs(input, options) {
150
140
  // LegacyBlobRef not included by default
151
141
  const includeLegacy = options?.allowLegacy === true;
152
142
  // Using a stack to avoid recursion depth issues.
@@ -164,7 +154,7 @@ function* enumBlobRefs(input, options) {
164
154
  visited.add(value);
165
155
  stack.push(...value);
166
156
  }
167
- else if ((0, object_js_1.isPlainProto)(value)) {
157
+ else if (isPlainProto(value)) {
168
158
  if (visited.has(value))
169
159
  continue;
170
160
  visited.add(value);
package/dist/blob.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"blob.js","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CheckCidOptions,\n Cid,\n RawCid,\n ifCid,\n parseCid,\n validateCidString,\n} from './cid.js'\nimport { LexValue } from './lex.js'\nimport { isPlainObject, isPlainProto } from './object.js'\n\n/**\n * Options to use with {@link ifCid}, {@link validateCidString}, and related CID\n * validation functions when validating CIDs in BlobRefs, in strict mode. This\n * ensures that the CID is a {@link RawCid} (CID v1, raw multicodec, sha256\n * multihash), which is the expected format for blob references in the AT\n * Protocol data model.\n */\nconst STRICT_CID_CHECK_OPTIONS: CheckCidOptions = { flavor: 'raw' }\n\n// Number.isSafeInteger is actually safe to use with non-number values, so we\n// can use it as a type guard.\nconst isSafeInteger = Number.isSafeInteger as (v: unknown) => v is number\n\n/**\n * Reference to binary data (like images, videos, etc.) in the AT Protocol data\n * model.\n *\n * This type represents a reference to a blob of binary data, identified by its\n * content hash (CID) and accompanied by metadata such as MIME type and size.\n *\n * The {@link BlobRef} type is a union of the current {@link TypedBlobRef}\n * format and the legacy {@link LegacyBlobRef} format.\n */\nexport type BlobRef<Ref extends Cid = Cid> = TypedBlobRef<Ref> | LegacyBlobRef\n\n/**\n * Options for validating a {@link BlobRef}.\n */\nexport type BlobRefCheckOptions = {\n /**\n * If `false`, skips strict CID validation of {@link BlobRef.ref}, allowing\n * any valid CID. Otherwise, validates that the CID is v1, uses the raw\n * multicodec, and has a sha256 multihash.\n *\n * @default true\n */\n strict?: boolean\n}\n\n/**\n * Type guard to check if a value is a valid {@link BlobRef}, which can be\n * either a {@link TypedBlobRef} or a {@link LegacyBlobRef}. By default, strict\n * CID validation is applied to ensure that the CID in the blob reference is in\n * the expected format for the AT Protocol, but this can be relaxed with the\n * `strict: false` option.\n */\nexport function isBlobRef(input: unknown): input is BlobRef<RawCid>\nexport function isBlobRef<TOptions extends BlobRefCheckOptions>(\n input: unknown,\n options: TOptions,\n): input is LegacyBlobRef | InferTypedBlobRef<TOptions>\nexport function isBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is BlobRef<RawCid>\nexport function isBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is BlobRef {\n return (input as any)?.$type === 'blob'\n ? isTypedBlobRef(input, options)\n : isLegacyBlobRef(input, options)\n}\n\n/**\n * Extracts the MIME type from a {@link BlobRef}.\n *\n * @example\n * ```ts\n * const mimeType = getBlobMime(blobRef)\n * console.log(mimeType) // e.g., 'image/jpeg'\n * ```\n */\nexport function getBlobMime(blob: BlobRef): string\nexport function getBlobMime(blob?: BlobRef): string | undefined\nexport function getBlobMime(blob?: BlobRef): string | undefined {\n return blob?.mimeType\n}\n\n/**\n * Extracts the size (in bytes) from a {@link TypedBlobRef}. For\n * {@link LegacyBlobRef}, size information is not available, so this function\n * returns `undefined` for legacy refs.\n *\n * @note The size property, in blob refs, cannot be 100% trusted since the PDS\n * might not have a local copy of the blob (to check the size against) and might\n * just be passing through the blob ref from the client without validating it.\n * So, while this function can be useful for getting size information when\n * available, it should not be solely relied upon for critical functionality\n * without additional validation.\n *\n * @example\n * ```ts\n * const size = getBlobSize(blobRef)\n * if (size !== undefined) {\n * console.log(`Blob size: ${size} bytes`)\n * } else {\n * console.log('Size information not available for legacy blob ref')\n * }\n * ```\n */\nexport function getBlobSize(blob: BlobRef): number | undefined {\n if ('$type' in blob && blob.size >= 0) return blob.size\n // LegacyBlobRef doesn't have size information\n return undefined\n}\n\n/**\n * Extracts the {@link Cid} from a {@link BlobRef}.\n *\n * @throws If the input input is a {@link LegacyBlobRef} with an invalid CID string\n * @example\n * ```ts\n * const cid = getBlobCid(blobRef)\n * console.log(cid.bytes)\n * ```\n */\nexport function getBlobCid(blob: BlobRef): Cid\nexport function getBlobCid(blob?: BlobRef): Cid | undefined\nexport function getBlobCid(blob?: BlobRef): Cid | undefined {\n if (!blob) return undefined\n return '$type' in blob ? blob.ref : parseCid(blob.cid)\n}\n\n/**\n * Extracts the CID string from a {@link BlobRef}.\n *\n * This is similar to `getBlobCid(blob).toString()` but is more optimized since\n * the CID string is already available in the legacy format and we can avoid\n * parsing it into a CID object just to convert it back to a string.\n *\n * @example\n * ```ts\n * const cidString = getBlobCidString(blobRef)\n * console.log(cidString)\n * ```\n */\nexport function getBlobCidString(blob: BlobRef): string\nexport function getBlobCidString(blob?: BlobRef): string | undefined\nexport function getBlobCidString(blob?: BlobRef): string | undefined {\n if (!blob) return undefined\n return '$type' in blob ? blob.ref.toString() : blob.cid\n}\n\n/**\n * Reference to binary data (like images, videos, etc.) in the AT Protocol data model.\n *\n * A {@link TypedBlobRef} is a {@link LexMap} with a specific structure that\n * identifies binary content by its content hash (CID), along with metadata\n * about the content type and size.\n *\n * @typeParam Ref - The type of CID reference, defaults to any {@link Cid}\n *\n * @example\n * ```typescript\n * import type { TypedBlobRef } from '@atproto/lex-data'\n *\n * const imageRef: TypedBlobRef = {\n * $type: 'blob',\n * mimeType: 'image/jpeg',\n * ref: cid, // CID of the blob content\n * size: 12345\n * }\n * ```\n *\n * @see {@link isTypedBlobRef} to check if a value is a valid {@link TypedBlobRef}\n * @see {@link LegacyBlobRef} for the older blob reference format\n */\nexport type TypedBlobRef<Ref extends Cid = Cid> = {\n $type: 'blob'\n mimeType: string\n ref: Ref\n size: number\n}\n\n/**\n * Infers the BlobRef type based on the check options.\n *\n * @typeParam TOptions - The options used for checking\n */\nexport type InferTypedBlobRef<TOptions extends BlobRefCheckOptions> =\n TOptions extends { strict: false }\n ? TypedBlobRef\n : { strict: boolean } extends TOptions\n ? TypedBlobRef\n : TypedBlobRef<RawCid>\n\n/**\n * Type guard to check if a value is a valid {@link BlobRef}.\n *\n * Validates the structure of the input including:\n * - `$type` must be `'blob'`\n * - `mimeType` must be a valid MIME type string (containing '/')\n * - `size` must be a non-negative safe integer\n * - `ref` must be a valid CID (strict validation by default)\n *\n * @param input - The value to check\n * @param options - Optional validation options\n * @returns `true` if the input is a valid BlobRef\n *\n * @example\n * ```typescript\n * import { isTypedBlobRef } from '@atproto/lex-data'\n *\n * if (isTypedBlobRef(data)) {\n * console.log(data.mimeType) // e.g., 'image/jpeg'\n * console.log(data.size) // e.g., 12345\n * }\n *\n * // Allow any valid CID (not just raw CIDs)\n * if (isTypedBlobRef(data, { strict: false })) {\n * // ...\n * }\n * ```\n */\nexport function isTypedBlobRef(input: unknown): input is TypedBlobRef<RawCid>\nexport function isTypedBlobRef<TOptions extends BlobRefCheckOptions>(\n input: unknown,\n options: TOptions,\n): input is InferTypedBlobRef<TOptions>\nexport function isTypedBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is TypedBlobRef<RawCid>\nexport function isTypedBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is TypedBlobRef {\n if (!isPlainObject(input)) {\n return false\n }\n\n if (input?.$type !== 'blob') {\n return false\n }\n\n const { mimeType, size, ref } = input\n // @NOTE Very basic mime validation\n if (typeof mimeType !== 'string' || !mimeType.includes('/')) {\n return false\n }\n\n if (size === -1 && options?.strict === false) {\n // In non-strict mode, allow size to be -1 to accommodate legacy blob refs\n // that don't include size information.\n } else if (!isSafeInteger(size) || size < 0) {\n return false\n }\n\n if (typeof ref !== 'object' || ref === null) {\n return false\n }\n\n for (const key in input) {\n if (\n key !== '$type' &&\n key !== 'mimeType' &&\n key !== 'ref' &&\n key !== 'size'\n ) {\n return false\n }\n }\n\n const cid = ifCid(\n ref,\n // Strict unless explicitly disabled\n options?.strict === false ? undefined : STRICT_CID_CHECK_OPTIONS,\n )\n if (!cid) {\n return false\n }\n\n return true\n}\n\n/**\n * Legacy format for blob references used in older AT Protocol data.\n *\n * This is the older format that stores the CID as a string rather than\n * as a structured CID object. New code should use {@link BlobRef} instead.\n *\n * @example\n * ```typescript\n * import type { LegacyBlobRef } from '@atproto/lex-data'\n *\n * const legacyRef: LegacyBlobRef = {\n * cid: 'bafyreib...',\n * mimeType: 'image/jpeg'\n * }\n * ```\n *\n * @see {@link isLegacyBlobRef} to check if a value is a LegacyBlobRef\n * @see {@link BlobRef} for the current blob reference format\n * @deprecated Use {@link BlobRef} for new code\n */\nexport type LegacyBlobRef = {\n cid: string\n mimeType: string\n}\n\n/**\n * Type guard to check if a value is a valid {@link LegacyBlobRef}.\n *\n * Validates the structure of the input:\n * - `cid` must be a valid CID string\n * - `mimeType` must be a non-empty string\n * - No additional properties allowed\n *\n * @example\n * ```typescript\n * import { isLegacyBlobRef } from '@atproto/lex-data'\n *\n * if (isLegacyBlobRef(data)) {\n * console.log(data.cid) // CID as string\n * console.log(data.mimeType) // e.g., 'image/jpeg'\n * }\n * ```\n *\n * @see {@link isTypedBlobRef} for checking the current blob reference format\n */\nexport function isLegacyBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is LegacyBlobRef {\n if (!isPlainObject(input)) {\n return false\n }\n\n const { cid, mimeType } = input\n if (typeof cid !== 'string') {\n return false\n }\n\n if (typeof mimeType !== 'string' || mimeType.length === 0) {\n return false\n }\n\n for (const key in input) {\n if (key !== 'cid' && key !== 'mimeType') {\n return false\n }\n }\n\n if (\n !validateCidString(\n cid,\n options?.strict === false ? undefined : STRICT_CID_CHECK_OPTIONS,\n )\n ) {\n return false\n }\n\n return true\n}\n\n/**\n * Options for enumerating blob references within a {@link LexValue}.\n */\nexport type EnumBlobRefsOptions = BlobRefCheckOptions & {\n /**\n * If `true`, also yields {@link LegacyBlobRef} objects in addition to\n * {@link BlobRef} objects.\n *\n * @default false\n */\n allowLegacy?: boolean\n}\n\n/**\n * Infers the yielded type of {@link enumBlobRefs} based on options.\n *\n * @typeParam TOptions - The options used for enumeration\n */\nexport type InferEnumBlobRefs<TOptions extends EnumBlobRefsOptions> =\n TOptions extends { allowLegacy: true }\n ? InferTypedBlobRef<TOptions> | LegacyBlobRef\n : { allowLegacy: boolean } extends TOptions\n ? InferTypedBlobRef<TOptions> | LegacyBlobRef\n : InferTypedBlobRef<TOptions>\n\n/**\n * Generator that enumerates all {@link BlobRef}s (and, optionally,\n * {@link LegacyBlobRef}s) found within a {@link LexValue}.\n *\n * Performs a deep traversal of the input value, yielding any blob references\n * found. This is useful for extracting all media references from a record.\n *\n * @param input - The LexValue to search for blob references\n * @param options - Optional configuration for the enumeration\n * @yields Each blob reference found in the input\n *\n * @example\n * ```typescript\n * import { enumBlobRefs } from '@atproto/lex-data'\n *\n * const record = {\n * text: 'Hello',\n * images: [\n * { $type: 'blob', mimeType: 'image/jpeg', ref: cid1, size: 1000 },\n * { $type: 'blob', mimeType: 'image/png', ref: cid2, size: 2000 }\n * ]\n * }\n *\n * for (const blobRef of enumBlobRefs(record)) {\n * console.log(blobRef.mimeType, blobRef.size)\n * }\n *\n * // Include legacy blob references\n * for (const ref of enumBlobRefs(record, { allowLegacy: true, strict: false })) {\n * // ref may be BlobRef or LegacyBlobRef, with relaxed CID validation\n * }\n * ```\n */\nexport function enumBlobRefs(\n input: LexValue,\n): Generator<BlobRef<RawCid>, void, unknown>\nexport function enumBlobRefs<TOptions extends EnumBlobRefsOptions>(\n input: LexValue,\n options: TOptions,\n): Generator<InferEnumBlobRefs<TOptions>, void, unknown>\nexport function enumBlobRefs(\n input: LexValue,\n options?: EnumBlobRefsOptions,\n): Generator<BlobRef, void, unknown>\nexport function* enumBlobRefs(\n input: LexValue,\n options?: EnumBlobRefsOptions,\n): Generator<BlobRef, void, unknown> {\n // LegacyBlobRef not included by default\n const includeLegacy = options?.allowLegacy === true\n\n // Using a stack to avoid recursion depth issues.\n const stack: LexValue[] = [input]\n\n // Since we are using a stack, we could end-up in an infinite loop with cyclic\n // structures. Cyclic structures are not valid LexValues and should, thus,\n // never occur, but let's be safe.\n const visited = new Set<object>()\n\n do {\n const value = stack.pop()!\n\n if (value != null && typeof value === 'object') {\n if (Array.isArray(value)) {\n if (visited.has(value)) continue\n visited.add(value)\n stack.push(...value)\n } else if (isPlainProto(value)) {\n if (visited.has(value)) continue\n visited.add(value)\n if (isTypedBlobRef(value, options)) {\n yield value\n } else if (includeLegacy && isLegacyBlobRef(value, options)) {\n yield value\n } else {\n for (const v of Object.values(value)) {\n if (v != null) stack.push(v)\n }\n }\n }\n }\n } while (stack.length > 0)\n\n // Optimization: ease GC's work\n visited.clear()\n}\n"]}
1
+ {"version":3,"file":"blob.js","sourceRoot":"","sources":["../src/blob.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CheckCidOptions,\n Cid,\n RawCid,\n ifCid,\n parseCid,\n validateCidString,\n} from './cid.js'\nimport { LexValue } from './lex.js'\nimport { isPlainObject, isPlainProto } from './object.js'\n\n/**\n * Options to use with {@link ifCid}, {@link validateCidString}, and related CID\n * validation functions when validating CIDs in BlobRefs, in strict mode. This\n * ensures that the CID is a {@link RawCid} (CID v1, raw multicodec, sha256\n * multihash), which is the expected format for blob references in the AT\n * Protocol data model.\n */\nconst STRICT_CID_CHECK_OPTIONS: CheckCidOptions = { flavor: 'raw' }\n\n// Number.isSafeInteger is actually safe to use with non-number values, so we\n// can use it as a type guard.\nconst isSafeInteger = Number.isSafeInteger as (v: unknown) => v is number\n\n/**\n * Reference to binary data (like images, videos, etc.) in the AT Protocol data\n * model.\n *\n * This type represents a reference to a blob of binary data, identified by its\n * content hash (CID) and accompanied by metadata such as MIME type and size.\n *\n * The {@link BlobRef} type is a union of the current {@link TypedBlobRef}\n * format and the legacy {@link LegacyBlobRef} format.\n */\nexport type BlobRef<Ref extends Cid = Cid> = TypedBlobRef<Ref> | LegacyBlobRef\n\n/**\n * Options for validating a {@link BlobRef}.\n */\nexport type BlobRefCheckOptions = {\n /**\n * If `false`, skips strict CID validation of {@link BlobRef.ref}, allowing\n * any valid CID. Otherwise, validates that the CID is v1, uses the raw\n * multicodec, and has a sha256 multihash.\n *\n * @default true\n */\n strict?: boolean\n}\n\n/**\n * Type guard to check if a value is a valid {@link BlobRef}, which can be\n * either a {@link TypedBlobRef} or a {@link LegacyBlobRef}. By default, strict\n * CID validation is applied to ensure that the CID in the blob reference is in\n * the expected format for the AT Protocol, but this can be relaxed with the\n * `strict: false` option.\n */\nexport function isBlobRef(input: unknown): input is BlobRef<RawCid>\nexport function isBlobRef<TOptions extends BlobRefCheckOptions>(\n input: unknown,\n options: TOptions,\n): input is LegacyBlobRef | InferTypedBlobRef<TOptions>\nexport function isBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is BlobRef<RawCid>\nexport function isBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is BlobRef {\n return (input as any)?.$type === 'blob'\n ? isTypedBlobRef(input, options)\n : isLegacyBlobRef(input, options)\n}\n\n/**\n * Extracts the MIME type from a {@link BlobRef}.\n *\n * @example\n * ```ts\n * const mimeType = getBlobMime(blobRef)\n * console.log(mimeType) // e.g., 'image/jpeg'\n * ```\n */\nexport function getBlobMime(blob: BlobRef): string\nexport function getBlobMime(blob?: BlobRef): string | undefined\nexport function getBlobMime(blob?: BlobRef): string | undefined {\n return blob?.mimeType\n}\n\n/**\n * Extracts the size (in bytes) from a {@link TypedBlobRef}. For\n * {@link LegacyBlobRef}, size information is not available, so this function\n * returns `undefined` for legacy refs.\n *\n * @note The size property, in blob refs, cannot be 100% trusted since the PDS\n * might not have a local copy of the blob (to check the size against) and might\n * just be passing through the blob ref from the client without validating it.\n * So, while this function can be useful for getting size information when\n * available, it should not be solely relied upon for critical functionality\n * without additional validation.\n *\n * @example\n * ```ts\n * const size = getBlobSize(blobRef)\n * if (size !== undefined) {\n * console.log(`Blob size: ${size} bytes`)\n * } else {\n * console.log('Size information not available for legacy blob ref')\n * }\n * ```\n */\nexport function getBlobSize(blob: BlobRef): number | undefined {\n if ('$type' in blob && blob.size >= 0) return blob.size\n // LegacyBlobRef doesn't have size information\n return undefined\n}\n\n/**\n * Extracts the {@link Cid} from a {@link BlobRef}.\n *\n * @throws If the input input is a {@link LegacyBlobRef} with an invalid CID string\n * @example\n * ```ts\n * const cid = getBlobCid(blobRef)\n * console.log(cid.bytes)\n * ```\n */\nexport function getBlobCid(blob: BlobRef): Cid\nexport function getBlobCid(blob?: BlobRef): Cid | undefined\nexport function getBlobCid(blob?: BlobRef): Cid | undefined {\n if (!blob) return undefined\n return '$type' in blob ? blob.ref : parseCid(blob.cid)\n}\n\n/**\n * Extracts the CID string from a {@link BlobRef}.\n *\n * This is similar to `getBlobCid(blob).toString()` but is more optimized since\n * the CID string is already available in the legacy format and we can avoid\n * parsing it into a CID object just to convert it back to a string.\n *\n * @example\n * ```ts\n * const cidString = getBlobCidString(blobRef)\n * console.log(cidString)\n * ```\n */\nexport function getBlobCidString(blob: BlobRef): string\nexport function getBlobCidString(blob?: BlobRef): string | undefined\nexport function getBlobCidString(blob?: BlobRef): string | undefined {\n if (!blob) return undefined\n return '$type' in blob ? blob.ref.toString() : blob.cid\n}\n\n/**\n * Reference to binary data (like images, videos, etc.) in the AT Protocol data model.\n *\n * A {@link TypedBlobRef} is a {@link LexMap} with a specific structure that\n * identifies binary content by its content hash (CID), along with metadata\n * about the content type and size.\n *\n * @typeParam Ref - The type of CID reference, defaults to any {@link Cid}\n *\n * @example\n * ```typescript\n * import type { TypedBlobRef } from '@atproto/lex-data'\n *\n * const imageRef: TypedBlobRef = {\n * $type: 'blob',\n * mimeType: 'image/jpeg',\n * ref: cid, // CID of the blob content\n * size: 12345\n * }\n * ```\n *\n * @see {@link isTypedBlobRef} to check if a value is a valid {@link TypedBlobRef}\n * @see {@link LegacyBlobRef} for the older blob reference format\n */\nexport type TypedBlobRef<Ref extends Cid = Cid> = {\n $type: 'blob'\n mimeType: string\n ref: Ref\n size: number\n}\n\n/**\n * Infers the BlobRef type based on the check options.\n *\n * @typeParam TOptions - The options used for checking\n */\nexport type InferTypedBlobRef<TOptions extends BlobRefCheckOptions> =\n TOptions extends { strict: false }\n ? TypedBlobRef\n : { strict: boolean } extends TOptions\n ? TypedBlobRef\n : TypedBlobRef<RawCid>\n\n/**\n * Type guard to check if a value is a valid {@link BlobRef}.\n *\n * Validates the structure of the input including:\n * - `$type` must be `'blob'`\n * - `mimeType` must be a valid MIME type string (containing '/')\n * - `size` must be a non-negative safe integer\n * - `ref` must be a valid CID (strict validation by default)\n *\n * @param input - The value to check\n * @param options - Optional validation options\n * @returns `true` if the input is a valid BlobRef\n *\n * @example\n * ```typescript\n * import { isTypedBlobRef } from '@atproto/lex-data'\n *\n * if (isTypedBlobRef(data)) {\n * console.log(data.mimeType) // e.g., 'image/jpeg'\n * console.log(data.size) // e.g., 12345\n * }\n *\n * // Allow any valid CID (not just raw CIDs)\n * if (isTypedBlobRef(data, { strict: false })) {\n * // ...\n * }\n * ```\n */\nexport function isTypedBlobRef(input: unknown): input is TypedBlobRef<RawCid>\nexport function isTypedBlobRef<TOptions extends BlobRefCheckOptions>(\n input: unknown,\n options: TOptions,\n): input is InferTypedBlobRef<TOptions>\nexport function isTypedBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is TypedBlobRef<RawCid>\nexport function isTypedBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is TypedBlobRef {\n if (!isPlainObject(input)) {\n return false\n }\n\n if (input?.$type !== 'blob') {\n return false\n }\n\n const { mimeType, size, ref } = input\n // @NOTE Very basic mime validation\n if (typeof mimeType !== 'string' || !mimeType.includes('/')) {\n return false\n }\n\n if (size === -1 && options?.strict === false) {\n // In non-strict mode, allow size to be -1 to accommodate legacy blob refs\n // that don't include size information.\n } else if (!isSafeInteger(size) || size < 0) {\n return false\n }\n\n if (typeof ref !== 'object' || ref === null) {\n return false\n }\n\n for (const key in input) {\n if (\n key !== '$type' &&\n key !== 'mimeType' &&\n key !== 'ref' &&\n key !== 'size'\n ) {\n return false\n }\n }\n\n const cid = ifCid(\n ref,\n // Strict unless explicitly disabled\n options?.strict === false ? undefined : STRICT_CID_CHECK_OPTIONS,\n )\n if (!cid) {\n return false\n }\n\n return true\n}\n\n/**\n * Legacy format for blob references used in older AT Protocol data.\n *\n * This is the older format that stores the CID as a string rather than\n * as a structured CID object. New code should use {@link BlobRef} instead.\n *\n * @example\n * ```typescript\n * import type { LegacyBlobRef } from '@atproto/lex-data'\n *\n * const legacyRef: LegacyBlobRef = {\n * cid: 'bafyreib...',\n * mimeType: 'image/jpeg'\n * }\n * ```\n *\n * @see {@link isLegacyBlobRef} to check if a value is a LegacyBlobRef\n * @see {@link BlobRef} for the current blob reference format\n * @deprecated Use {@link BlobRef} for new code\n */\nexport type LegacyBlobRef = {\n cid: string\n mimeType: string\n}\n\n/**\n * Type guard to check if a value is a valid {@link LegacyBlobRef}.\n *\n * Validates the structure of the input:\n * - `cid` must be a valid CID string\n * - `mimeType` must be a non-empty string\n * - No additional properties allowed\n *\n * @example\n * ```typescript\n * import { isLegacyBlobRef } from '@atproto/lex-data'\n *\n * if (isLegacyBlobRef(data)) {\n * console.log(data.cid) // CID as string\n * console.log(data.mimeType) // e.g., 'image/jpeg'\n * }\n * ```\n *\n * @see {@link isTypedBlobRef} for checking the current blob reference format\n */\nexport function isLegacyBlobRef(\n input: unknown,\n options?: BlobRefCheckOptions,\n): input is LegacyBlobRef {\n if (!isPlainObject(input)) {\n return false\n }\n\n const { cid, mimeType } = input\n if (typeof cid !== 'string') {\n return false\n }\n\n if (typeof mimeType !== 'string' || mimeType.length === 0) {\n return false\n }\n\n for (const key in input) {\n if (key !== 'cid' && key !== 'mimeType') {\n return false\n }\n }\n\n if (\n !validateCidString(\n cid,\n options?.strict === false ? undefined : STRICT_CID_CHECK_OPTIONS,\n )\n ) {\n return false\n }\n\n return true\n}\n\n/**\n * Options for enumerating blob references within a {@link LexValue}.\n */\nexport type EnumBlobRefsOptions = BlobRefCheckOptions & {\n /**\n * If `true`, also yields {@link LegacyBlobRef} objects in addition to\n * {@link BlobRef} objects.\n *\n * @default false\n */\n allowLegacy?: boolean\n}\n\n/**\n * Infers the yielded type of {@link enumBlobRefs} based on options.\n *\n * @typeParam TOptions - The options used for enumeration\n */\nexport type InferEnumBlobRefs<TOptions extends EnumBlobRefsOptions> =\n TOptions extends { allowLegacy: true }\n ? InferTypedBlobRef<TOptions> | LegacyBlobRef\n : { allowLegacy: boolean } extends TOptions\n ? InferTypedBlobRef<TOptions> | LegacyBlobRef\n : InferTypedBlobRef<TOptions>\n\n/**\n * Generator that enumerates all {@link BlobRef}s (and, optionally,\n * {@link LegacyBlobRef}s) found within a {@link LexValue}.\n *\n * Performs a deep traversal of the input value, yielding any blob references\n * found. This is useful for extracting all media references from a record.\n *\n * @param input - The LexValue to search for blob references\n * @param options - Optional configuration for the enumeration\n * @yields Each blob reference found in the input\n *\n * @example\n * ```typescript\n * import { enumBlobRefs } from '@atproto/lex-data'\n *\n * const record = {\n * text: 'Hello',\n * images: [\n * { $type: 'blob', mimeType: 'image/jpeg', ref: cid1, size: 1000 },\n * { $type: 'blob', mimeType: 'image/png', ref: cid2, size: 2000 }\n * ]\n * }\n *\n * for (const blobRef of enumBlobRefs(record)) {\n * console.log(blobRef.mimeType, blobRef.size)\n * }\n *\n * // Include legacy blob references\n * for (const ref of enumBlobRefs(record, { allowLegacy: true, strict: false })) {\n * // ref may be BlobRef or LegacyBlobRef, with relaxed CID validation\n * }\n * ```\n */\nexport function enumBlobRefs(\n input: LexValue,\n): Generator<BlobRef<RawCid>, void, unknown>\nexport function enumBlobRefs<TOptions extends EnumBlobRefsOptions>(\n input: LexValue,\n options: TOptions,\n): Generator<InferEnumBlobRefs<TOptions>, void, unknown>\nexport function enumBlobRefs(\n input: LexValue,\n options?: EnumBlobRefsOptions,\n): Generator<BlobRef, void, unknown>\nexport function* enumBlobRefs(\n input: LexValue,\n options?: EnumBlobRefsOptions,\n): Generator<BlobRef, void, unknown> {\n // LegacyBlobRef not included by default\n const includeLegacy = options?.allowLegacy === true\n\n // Using a stack to avoid recursion depth issues.\n const stack: LexValue[] = [input]\n\n // Since we are using a stack, we could end-up in an infinite loop with cyclic\n // structures. Cyclic structures are not valid LexValues and should, thus,\n // never occur, but let's be safe.\n const visited = new Set<object>()\n\n do {\n const value = stack.pop()!\n\n if (value != null && typeof value === 'object') {\n if (Array.isArray(value)) {\n if (visited.has(value)) continue\n visited.add(value)\n stack.push(...value)\n } else if (isPlainProto(value)) {\n if (visited.has(value)) continue\n visited.add(value)\n if (isTypedBlobRef(value, options)) {\n yield value\n } else if (includeLegacy && isLegacyBlobRef(value, options)) {\n yield value\n } else {\n for (const v of Object.values(value)) {\n if (v != null) stack.push(v)\n }\n }\n }\n }\n } while (stack.length > 0)\n\n // Optimization: ease GC's work\n visited.clear()\n}\n"]}
package/dist/cid.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../src/cid.ts"],"names":[],"mappings":"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"}
package/dist/cid.js CHANGED
@@ -1,32 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CID = exports.SHA512_HASH_CODE = exports.SHA256_HASH_CODE = exports.RAW_DATA_CODEC = exports.CBOR_DATA_CODEC = void 0;
4
- exports.multihashEquals = multihashEquals;
5
- exports.asMultiformatsCID = asMultiformatsCID;
6
- exports.isRawCid = isRawCid;
7
- exports.isDaslCid = isDaslCid;
8
- exports.isCborCid = isCborCid;
9
- exports.checkCid = checkCid;
10
- exports.isCid = isCid;
11
- exports.ifCid = ifCid;
12
- exports.asCid = asCid;
13
- exports.decodeCid = decodeCid;
14
- exports.parseCid = parseCid;
15
- exports.validateCidString = validateCidString;
16
- exports.parseCidSafe = parseCidSafe;
17
- exports.ensureValidCidString = ensureValidCidString;
18
- exports.isCidForBytes = isCidForBytes;
19
- exports.createCid = createCid;
20
- exports.cidForCbor = cidForCbor;
21
- exports.cidForRawBytes = cidForRawBytes;
22
- exports.cidForRawHash = cidForRawHash;
23
- const cid_1 = require("multiformats/cid");
24
- Object.defineProperty(exports, "CID", { enumerable: true, get: function () { return cid_1.CID; } });
25
- const digest_1 = require("multiformats/hashes/digest");
26
- const sha2_1 = require("multiformats/hashes/sha2");
27
- const util_js_1 = require("./lib/util.js");
28
- const object_js_1 = require("./object.js");
29
- const uint8array_js_1 = require("./uint8array.js");
1
+ import { CID } from 'multiformats/cid';
2
+ import { create as createDigest } from 'multiformats/hashes/digest';
3
+ import { sha256, sha512 } from 'multiformats/hashes/sha2';
4
+ import { isUint8, toHexString } from './lib/util.js';
5
+ import { isObject } from './object.js';
6
+ import { ui8Equals } from './uint8array.js';
30
7
  /**
31
8
  * Codec code that indicates the CID references a CBOR-encoded data structure.
32
9
  *
@@ -34,7 +11,7 @@ const uint8array_js_1 = require("./uint8array.js");
34
11
  *
35
12
  * @see {@link https://dasl.ing/cid.html Content IDs (DASL)}
36
13
  */
37
- exports.CBOR_DATA_CODEC = 0x71;
14
+ export const CBOR_DATA_CODEC = 0x71;
38
15
  /**
39
16
  * Codec code that indicates the CID references raw binary data (like media blobs).
40
17
  *
@@ -42,15 +19,15 @@ exports.CBOR_DATA_CODEC = 0x71;
42
19
  *
43
20
  * @see {@link https://dasl.ing/cid.html Content IDs (DASL)}
44
21
  */
45
- exports.RAW_DATA_CODEC = 0x55;
22
+ export const RAW_DATA_CODEC = 0x55;
46
23
  /**
47
24
  * Hash code that indicates that a CID uses SHA-256.
48
25
  */
49
- exports.SHA256_HASH_CODE = sha2_1.sha256.code;
26
+ export const SHA256_HASH_CODE = sha256.code;
50
27
  /**
51
28
  * Hash code that indicates that a CID uses SHA-512.
52
29
  */
53
- exports.SHA512_HASH_CODE = sha2_1.sha512.code;
30
+ export const SHA512_HASH_CODE = sha512.code;
54
31
  /**
55
32
  * Compares two {@link Multihash} for equality.
56
33
  *
@@ -58,11 +35,30 @@ exports.SHA512_HASH_CODE = sha2_1.sha512.code;
58
35
  * @param b - Second {@link Multihash}
59
36
  * @returns `true` if both multihashes have the same code and digest
60
37
  */
61
- function multihashEquals(a, b) {
38
+ export function multihashEquals(a, b) {
62
39
  if (a === b)
63
40
  return true;
64
- return a.code === b.code && (0, uint8array_js_1.ui8Equals)(a.digest, b.digest);
41
+ return a.code === b.code && ui8Equals(a.digest, b.digest);
65
42
  }
43
+ // multiformats' CID class is not very portable because:
44
+ //
45
+ // - In dependent packages that use "moduleResolution" set to "node16",
46
+ // "nodenext" or "bundler", TypeScript fails to properly resolve the
47
+ // multiformats package when importing CID from @atproto/lex-data. This causes
48
+ // type errors in those packages. This is caused by the fact that the
49
+ // multiformats version <10 (which is the last version that supports CommonJS)
50
+ // uses "exports" field in package.json, which do not contain "types"
51
+ // entrypoints.
52
+ // https://www.npmjs.com/package/multiformats/v/9.9.0?activeTab=code
53
+ // - By defining our own interface and helper functions, we can have more
54
+ // control over the public API exposed by this package.
55
+ // - It allow us to have a stable interface in case we need to swap out, or
56
+ // eventually update multiformats (should we choose to drop CommonJS support)
57
+ // in the future.
58
+ // @NOTE Even though it is not portable, we still re-export CID here so that
59
+ // dependent packages where it can be used, have access to it (instead of
60
+ // importing directly from "multiformats" or "multiformats/cid").
61
+ export { /** @deprecated */ CID };
66
62
  /**
67
63
  * Converts a {@link Cid} to a multiformats {@link CID} instance.
68
64
  *
@@ -71,12 +67,12 @@ function multihashEquals(a, b) {
71
67
  * implementation directly. This is to avoid compatibility issues, and in order
72
68
  * to allow better portability, compatibility and future updates.
73
69
  */
74
- function asMultiformatsCID(input) {
70
+ export function asMultiformatsCID(input) {
75
71
  const cid =
76
72
  // Already a multiformats CID instance
77
- cid_1.CID.asCID(input) ??
73
+ CID.asCID(input) ??
78
74
  // Create a new multiformats CID instance
79
- cid_1.CID.create(input.version, input.code, (0, digest_1.create)(input.multihash.code, input.multihash.digest));
75
+ CID.create(input.version, input.code, createDigest(input.multihash.code, input.multihash.digest));
80
76
  // @NOTE: the "satisfies" operator is used here to ensure that the Cid
81
77
  // interface is indeed compatible with multiformats' CID implementation, which
82
78
  // allows us to safely rely on multiformats' CID implementation where Cid are
@@ -89,8 +85,8 @@ function asMultiformatsCID(input) {
89
85
  * @param cid - The CID to check
90
86
  * @returns `true` if the CID is a version 1 CID with raw multicodec
91
87
  */
92
- function isRawCid(cid) {
93
- return cid.version === 1 && cid.code === exports.RAW_DATA_CODEC;
88
+ export function isRawCid(cid) {
89
+ return cid.version === 1 && cid.code === RAW_DATA_CODEC;
94
90
  }
95
91
  /**
96
92
  * Type guard to check if a CID is DASL compliant.
@@ -98,10 +94,10 @@ function isRawCid(cid) {
98
94
  * @param cid - The CID to check
99
95
  * @returns `true` if the CID is DASL compliant (v1, raw/dag-cbor, sha256)
100
96
  */
101
- function isDaslCid(cid) {
97
+ export function isDaslCid(cid) {
102
98
  return (cid.version === 1 &&
103
- (cid.code === exports.RAW_DATA_CODEC || cid.code === exports.CBOR_DATA_CODEC) &&
104
- cid.multihash.code === exports.SHA256_HASH_CODE &&
99
+ (cid.code === RAW_DATA_CODEC || cid.code === CBOR_DATA_CODEC) &&
100
+ cid.multihash.code === SHA256_HASH_CODE &&
105
101
  cid.multihash.digest.byteLength === 0x20 // Should always be 32 bytes (256 bits) for SHA-256, but double-checking anyways
106
102
  );
107
103
  }
@@ -111,10 +107,10 @@ function isDaslCid(cid) {
111
107
  * @param cid - The CID to check
112
108
  * @returns `true` if the CID is a DAG-CBOR CID (v1, dag-cbor, sha256)
113
109
  */
114
- function isCborCid(cid) {
115
- return cid.code === exports.CBOR_DATA_CODEC && isDaslCid(cid);
110
+ export function isCborCid(cid) {
111
+ return cid.code === CBOR_DATA_CODEC && isDaslCid(cid);
116
112
  }
117
- function checkCid(cid, options) {
113
+ export function checkCid(cid, options) {
118
114
  switch (options?.flavor) {
119
115
  case undefined:
120
116
  return true;
@@ -128,25 +124,25 @@ function checkCid(cid, options) {
128
124
  throw new TypeError(`Unknown CID flavor: ${options?.flavor}`);
129
125
  }
130
126
  }
131
- function isCid(value, options) {
127
+ export function isCid(value, options) {
132
128
  return isCidImplementation(value) && checkCid(value, options);
133
129
  }
134
- function ifCid(value, options) {
130
+ export function ifCid(value, options) {
135
131
  if (isCid(value, options))
136
132
  return value;
137
133
  return null;
138
134
  }
139
- function asCid(value, options) {
135
+ export function asCid(value, options) {
140
136
  if (isCid(value, options))
141
137
  return value;
142
138
  throw new Error(`Invalid ${options?.flavor ? `${options.flavor} CID` : 'CID'} "${value}"`);
143
139
  }
144
- function decodeCid(cidBytes, options) {
145
- const cid = cid_1.CID.decode(cidBytes);
140
+ export function decodeCid(cidBytes, options) {
141
+ const cid = CID.decode(cidBytes);
146
142
  return asCid(cid, options);
147
143
  }
148
- function parseCid(input, options) {
149
- const cid = cid_1.CID.parse(input);
144
+ export function parseCid(input, options) {
145
+ const cid = CID.parse(input);
150
146
  return asCid(cid, options);
151
147
  }
152
148
  /**
@@ -159,10 +155,10 @@ function parseCid(input, options) {
159
155
  * @param options - Optional flavor constraints
160
156
  * @returns `true` if the string is a valid CID
161
157
  */
162
- function validateCidString(input, options) {
158
+ export function validateCidString(input, options) {
163
159
  return parseCidSafe(input, options)?.toString() === input;
164
160
  }
165
- function parseCidSafe(input, options) {
161
+ export function parseCidSafe(input, options) {
166
162
  try {
167
163
  return parseCid(input, options);
168
164
  }
@@ -177,7 +173,7 @@ function parseCidSafe(input, options) {
177
173
  * @param options - Optional flavor constraints
178
174
  * @throws If the string is not a valid CID
179
175
  */
180
- function ensureValidCidString(input, options) {
176
+ export function ensureValidCidString(input, options) {
181
177
  if (!validateCidString(input, options)) {
182
178
  throw new Error(`Invalid CID string "${input}"`);
183
179
  }
@@ -188,17 +184,17 @@ function ensureValidCidString(input, options) {
188
184
  * @params bytes The bytes to verify.
189
185
  * @returns true if the CID matches the bytes, false otherwise.
190
186
  */
191
- async function isCidForBytes(cid, bytes) {
192
- if (cid.multihash.code === sha2_1.sha256.code) {
193
- const multihash = await sha2_1.sha256.digest(bytes);
187
+ export async function isCidForBytes(cid, bytes) {
188
+ if (cid.multihash.code === sha256.code) {
189
+ const multihash = await sha256.digest(bytes);
194
190
  return multihashEquals(multihash, cid.multihash);
195
191
  }
196
- if (cid.multihash.code === sha2_1.sha512.code) {
197
- const multihash = await sha2_1.sha512.digest(bytes);
192
+ if (cid.multihash.code === sha512.code) {
193
+ const multihash = await sha512.digest(bytes);
198
194
  return multihashEquals(multihash, cid.multihash);
199
195
  }
200
196
  // Don't know how to verify other multihash codes
201
- throw new Error(`Unsupported CID multihash code: ${(0, util_js_1.toHexString)(cid.multihash.code)}`);
197
+ throw new Error(`Unsupported CID multihash code: ${toHexString(cid.multihash.code)}`);
202
198
  }
203
199
  /**
204
200
  * Creates a CID from a multicodec, multihash code, and digest.
@@ -215,8 +211,8 @@ async function isCidForBytes(cid, bytes) {
215
211
  * const cid = createCid(RAW_DATA_CODEC, SHA256_HASH_CODE, hashDigest)
216
212
  * ```
217
213
  */
218
- function createCid(code, multihashCode, digest) {
219
- const cid = cid_1.CID.createV1(code, (0, digest_1.create)(multihashCode, digest));
214
+ export function createCid(code, multihashCode, digest) {
215
+ const cid = CID.createV1(code, createDigest(multihashCode, digest));
220
216
  return cid;
221
217
  }
222
218
  /**
@@ -227,9 +223,9 @@ function createCid(code, multihashCode, digest) {
227
223
  * @param bytes - The CBOR-encoded bytes to hash
228
224
  * @returns A promise that resolves to the CborCid
229
225
  */
230
- async function cidForCbor(bytes) {
231
- const multihash = await sha2_1.sha256.digest(bytes);
232
- return cid_1.CID.createV1(exports.CBOR_DATA_CODEC, multihash);
226
+ export async function cidForCbor(bytes) {
227
+ const multihash = await sha256.digest(bytes);
228
+ return CID.createV1(CBOR_DATA_CODEC, multihash);
233
229
  }
234
230
  /**
235
231
  * Creates a raw CID for the given binary bytes.
@@ -239,9 +235,9 @@ async function cidForCbor(bytes) {
239
235
  * @param bytes - The raw binary bytes to hash
240
236
  * @returns A promise that resolves to the RawCid
241
237
  */
242
- async function cidForRawBytes(bytes) {
243
- const multihash = await sha2_1.sha256.digest(bytes);
244
- return cid_1.CID.createV1(exports.RAW_DATA_CODEC, multihash);
238
+ export async function cidForRawBytes(bytes) {
239
+ const multihash = await sha256.digest(bytes);
240
+ return CID.createV1(RAW_DATA_CODEC, multihash);
245
241
  }
246
242
  /**
247
243
  * Creates a raw CID from an existing SHA-256 hash digest.
@@ -250,15 +246,15 @@ async function cidForRawBytes(bytes) {
250
246
  * @returns A RawCid with the given digest
251
247
  * @throws If the digest is not a valid SHA-256 hash (not 32 bytes)
252
248
  */
253
- function cidForRawHash(digest) {
249
+ export function cidForRawHash(digest) {
254
250
  // Fool-proofing
255
251
  if (digest.length !== 0x20) {
256
- throw new Error(`Invalid SHA-256 hash length: ${(0, util_js_1.toHexString)(digest.length)}`);
252
+ throw new Error(`Invalid SHA-256 hash length: ${toHexString(digest.length)}`);
257
253
  }
258
- return createCid(exports.RAW_DATA_CODEC, sha2_1.sha256.code, digest);
254
+ return createCid(RAW_DATA_CODEC, sha256.code, digest);
259
255
  }
260
256
  function isCidImplementation(value) {
261
- if (cid_1.CID.asCID(value)) {
257
+ if (CID.asCID(value)) {
262
258
  // CIDs created using older multiformats versions did not have a "bytes"
263
259
  // property.
264
260
  return value.bytes != null;
@@ -266,17 +262,17 @@ function isCidImplementation(value) {
266
262
  else {
267
263
  // Unknown implementation, do a structural check
268
264
  try {
269
- if (!(0, object_js_1.isObject)(value))
265
+ if (!isObject(value))
270
266
  return false;
271
267
  const val = value;
272
268
  if (val.version !== 0 && val.version !== 1)
273
269
  return false;
274
- if (!(0, util_js_1.isUint8)(val.code))
270
+ if (!isUint8(val.code))
275
271
  return false;
276
- if (!(0, object_js_1.isObject)(val.multihash))
272
+ if (!isObject(val.multihash))
277
273
  return false;
278
274
  const mh = val.multihash;
279
- if (!(0, util_js_1.isUint8)(mh.code))
275
+ if (!isUint8(mh.code))
280
276
  return false;
281
277
  if (!(mh.digest instanceof Uint8Array))
282
278
  return false;
@@ -293,7 +289,7 @@ function isCidImplementation(value) {
293
289
  return false;
294
290
  if (val.bytes.length !== 4 + mh.digest.length)
295
291
  return false;
296
- if (!(0, uint8array_js_1.ui8Equals)(val.bytes.subarray(4), mh.digest))
292
+ if (!ui8Equals(val.bytes.subarray(4), mh.digest))
297
293
  return false;
298
294
  if (typeof val.equals !== 'function')
299
295
  return false;