@atproto/common 0.8.8 → 0.8.10
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 +17 -0
- package/dist/obfuscate.d.ts +11 -0
- package/dist/obfuscate.d.ts.map +1 -1
- package/dist/obfuscate.js +19 -5
- package/dist/obfuscate.js.map +1 -1
- package/dist/obfuscate.test.d.ts +2 -0
- package/dist/obfuscate.test.d.ts.map +1 -0
- package/dist/obfuscate.test.js +55 -0
- package/dist/obfuscate.test.js.map +1 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atproto/common
|
|
2
2
|
|
|
3
|
+
## 0.8.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5762](https://github.com/bluesky-social/atproto/pull/5762) [`7a46712`](https://github.com/bluesky-social/atproto/commit/7a467120982d9ff1559afeb3a26989dad5877d17) Thanks [@haileyok](https://github.com/haileyok)! - Redact cookie and set-cookie headers in HTTP request and response logs.
|
|
8
|
+
- Updated dependencies [[`ac78dcf`](https://github.com/bluesky-social/atproto/commit/ac78dcf2cba6505f822b6db093a14d489eee1c49)]:
|
|
9
|
+
- @atproto/lex-cbor@0.1.10
|
|
10
|
+
|
|
11
|
+
## 0.8.9
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`8c841f6`](https://github.com/bluesky-social/atproto/commit/8c841f6e73c8365c2dfe816c0613aa9c50490361), [`8c841f6`](https://github.com/bluesky-social/atproto/commit/8c841f6e73c8365c2dfe816c0613aa9c50490361), [`8c841f6`](https://github.com/bluesky-social/atproto/commit/8c841f6e73c8365c2dfe816c0613aa9c50490361), [`8c841f6`](https://github.com/bluesky-social/atproto/commit/8c841f6e73c8365c2dfe816c0613aa9c50490361)]:
|
|
16
|
+
- @atproto/lex-data@0.1.10
|
|
17
|
+
- @atproto/lex-cbor@0.1.9
|
|
18
|
+
- @atproto/common-web@0.5.17
|
|
19
|
+
|
|
3
20
|
## 0.8.8
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/dist/obfuscate.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
export declare function obfuscateEmail(email: string): string;
|
|
2
2
|
export declare function obfuscateWord(word: string): string;
|
|
3
|
+
type HeaderValue = string | string[] | number | undefined;
|
|
3
4
|
export declare function obfuscateHeaders(headers: Record<string, string>): Record<string, string>;
|
|
5
|
+
export declare function obfuscateHeaders(headers: Record<string, HeaderValue>): Record<string, HeaderValue>;
|
|
6
|
+
/** Redact headers on the serialized response passed by pino-http. */
|
|
7
|
+
export declare function obfuscateResSerializer(res: {
|
|
8
|
+
statusCode?: number | null;
|
|
9
|
+
headers?: Record<string, HeaderValue>;
|
|
10
|
+
}): {
|
|
11
|
+
statusCode: number | null;
|
|
12
|
+
headers: Record<string, HeaderValue> | undefined;
|
|
13
|
+
};
|
|
4
14
|
export declare function obfuscateAuthHeader(authHeader: string): string;
|
|
5
15
|
export declare function obfuscateBasic(token: string): null | string;
|
|
6
16
|
export declare function obfuscateBearer(token: string): string;
|
|
7
17
|
export declare function obfuscateToken(token: string): string;
|
|
8
18
|
export declare function obfuscateJwt(token: string): null | string;
|
|
19
|
+
export {};
|
|
9
20
|
//# sourceMappingURL=obfuscate.d.ts.map
|
package/dist/obfuscate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obfuscate.d.ts","sourceRoot":"","sources":["../src/obfuscate.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,UAG3C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,UAEzC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"obfuscate.d.ts","sourceRoot":"","sources":["../src/obfuscate.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,UAG3C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,UAEzC;AAED,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAA;AAEzD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AACzB,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACnC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;AAqB9B,qEAAqE;AACrE,wBAAgB,sBAAsB,CAAC,GAAG,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;CACtC;IAEG,UAAU;IACV,OAAO;EAEV;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAgB9D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAS3D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAuBzD"}
|
package/dist/obfuscate.js
CHANGED
|
@@ -8,18 +8,32 @@ export function obfuscateWord(word) {
|
|
|
8
8
|
export function obfuscateHeaders(headers) {
|
|
9
9
|
const obfuscatedHeaders = {};
|
|
10
10
|
for (const key in headers) {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const name = key.toLowerCase();
|
|
12
|
+
const value = headers[key];
|
|
13
|
+
if (name === 'cookie' || name === 'set-cookie') {
|
|
14
|
+
obfuscatedHeaders[key] = '[Redacted]';
|
|
13
15
|
}
|
|
14
|
-
else if (
|
|
15
|
-
obfuscatedHeaders[key] =
|
|
16
|
+
else if (name === 'authorization') {
|
|
17
|
+
obfuscatedHeaders[key] =
|
|
18
|
+
typeof value === 'string' ? obfuscateAuthHeader(value) : 'Invalid';
|
|
19
|
+
}
|
|
20
|
+
else if (name === 'dpop') {
|
|
21
|
+
obfuscatedHeaders[key] =
|
|
22
|
+
typeof value === 'string' ? obfuscateJwt(value) || 'Invalid' : 'Invalid';
|
|
16
23
|
}
|
|
17
24
|
else {
|
|
18
|
-
obfuscatedHeaders[key] =
|
|
25
|
+
obfuscatedHeaders[key] = value;
|
|
19
26
|
}
|
|
20
27
|
}
|
|
21
28
|
return obfuscatedHeaders;
|
|
22
29
|
}
|
|
30
|
+
/** Redact headers on the serialized response passed by pino-http. */
|
|
31
|
+
export function obfuscateResSerializer(res) {
|
|
32
|
+
return {
|
|
33
|
+
statusCode: res.statusCode ?? null,
|
|
34
|
+
headers: res.headers ? obfuscateHeaders(res.headers) : res.headers,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
23
37
|
export function obfuscateAuthHeader(authHeader) {
|
|
24
38
|
// This is a hot path (runs on every request). Avoid using split() or regex.
|
|
25
39
|
const spaceIdx = authHeader.indexOf(' ');
|
package/dist/obfuscate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obfuscate.js","sourceRoot":"","sources":["../src/obfuscate.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACxC,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAA;AAC9D,CAAC;
|
|
1
|
+
{"version":3,"file":"obfuscate.js","sourceRoot":"","sources":["../src/obfuscate.ts"],"names":[],"mappings":"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","sourcesContent":["export function obfuscateEmail(email: string) {\n const [local, domain] = email.split('@')\n return `${obfuscateWord(local)}@${obfuscateWord(domain)}`\n}\n\nexport function obfuscateWord(word: string) {\n return `${word.charAt(0)}***${word.charAt(word.length - 1)}`\n}\n\ntype HeaderValue = string | string[] | number | undefined\n\nexport function obfuscateHeaders(\n headers: Record<string, string>,\n): Record<string, string>\nexport function obfuscateHeaders(\n headers: Record<string, HeaderValue>,\n): Record<string, HeaderValue>\nexport function obfuscateHeaders(headers: Record<string, HeaderValue>) {\n const obfuscatedHeaders: Record<string, HeaderValue> = {}\n for (const key in headers) {\n const name = key.toLowerCase()\n const value = headers[key]\n if (name === 'cookie' || name === 'set-cookie') {\n obfuscatedHeaders[key] = '[Redacted]'\n } else if (name === 'authorization') {\n obfuscatedHeaders[key] =\n typeof value === 'string' ? obfuscateAuthHeader(value) : 'Invalid'\n } else if (name === 'dpop') {\n obfuscatedHeaders[key] =\n typeof value === 'string' ? obfuscateJwt(value) || 'Invalid' : 'Invalid'\n } else {\n obfuscatedHeaders[key] = value\n }\n }\n return obfuscatedHeaders\n}\n\n/** Redact headers on the serialized response passed by pino-http. */\nexport function obfuscateResSerializer(res: {\n statusCode?: number | null\n headers?: Record<string, HeaderValue>\n}) {\n return {\n statusCode: res.statusCode ?? null,\n headers: res.headers ? obfuscateHeaders(res.headers) : res.headers,\n }\n}\n\nexport function obfuscateAuthHeader(authHeader: string): string {\n // This is a hot path (runs on every request). Avoid using split() or regex.\n\n const spaceIdx = authHeader.indexOf(' ')\n if (spaceIdx === -1) return 'Invalid'\n\n const type = authHeader.slice(0, spaceIdx)\n switch (type.toLowerCase()) {\n case 'bearer':\n case 'dpop':\n return `${type} ${obfuscateBearer(authHeader.slice(spaceIdx + 1))}`\n case 'basic':\n return `${type} ${obfuscateBasic(authHeader.slice(spaceIdx + 1)) || 'Invalid'}`\n default:\n return `Invalid`\n }\n}\n\nexport function obfuscateBasic(token: string): null | string {\n if (!token) return null\n const buffer = Buffer.from(token, 'base64')\n if (!buffer.length) return null // Buffer.from will silently ignore invalid base64 chars\n const authHeader = buffer.toString('utf8')\n const colIdx = authHeader.indexOf(':')\n if (colIdx === -1) return null\n const username = authHeader.slice(0, colIdx)\n return `${username}:***`\n}\n\nexport function obfuscateBearer(token: string): string {\n return obfuscateJwt(token) || obfuscateToken(token)\n}\n\nexport function obfuscateToken(token: string): string {\n if (token.length >= 12) return obfuscateWord(token)\n return token ? '***' : ''\n}\n\nexport function obfuscateJwt(token: string): null | string {\n const firstDot = token.indexOf('.')\n if (firstDot === -1) return null\n\n const secondDot = token.indexOf('.', firstDot + 1)\n if (secondDot === -1) return null\n\n // Expected to be missing\n const thirdDot = token.indexOf('.', secondDot + 1)\n if (thirdDot !== -1) return null\n\n try {\n const payloadEnc = token.slice(firstDot + 1, secondDot)\n const payloadJson = Buffer.from(payloadEnc, 'base64').toString('utf8')\n const payload = JSON.parse(payloadJson)\n if (typeof payload.sub === 'string') return payload.sub\n } catch {\n // Invalid JWT\n return null\n }\n\n // Strip the signature\n return token.slice(0, secondDot) + '.obfuscated'\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obfuscate.test.d.ts","sourceRoot":"","sources":["../src/obfuscate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { obfuscateHeaders, obfuscateResSerializer } from './obfuscate.js';
|
|
3
|
+
describe(obfuscateHeaders, () => {
|
|
4
|
+
it('redacts cookies case-insensitively without modifying the input', () => {
|
|
5
|
+
const headers = {
|
|
6
|
+
Cookie: 'session=secret',
|
|
7
|
+
'Set-Cookie': ['session=secret; HttpOnly', 'csrf=secret'],
|
|
8
|
+
accept: 'application/json',
|
|
9
|
+
'content-length': 42,
|
|
10
|
+
};
|
|
11
|
+
expect(obfuscateHeaders(headers)).toEqual({
|
|
12
|
+
Cookie: '[Redacted]',
|
|
13
|
+
'Set-Cookie': '[Redacted]',
|
|
14
|
+
accept: 'application/json',
|
|
15
|
+
'content-length': 42,
|
|
16
|
+
});
|
|
17
|
+
expect(headers.Cookie).toBe('session=secret');
|
|
18
|
+
expect(headers['Set-Cookie']).toHaveLength(2);
|
|
19
|
+
});
|
|
20
|
+
it('preserves existing authorization and DPoP obfuscation', () => {
|
|
21
|
+
expect(obfuscateHeaders({
|
|
22
|
+
Authorization: 'Bearer some-long-secret',
|
|
23
|
+
DPoP: 'not-a-jwt',
|
|
24
|
+
accept: '*/*',
|
|
25
|
+
})).toEqual({
|
|
26
|
+
Authorization: 'Bearer s***t',
|
|
27
|
+
DPoP: 'Invalid',
|
|
28
|
+
accept: '*/*',
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
it('does not throw or expose unexpected non-string credentials', () => {
|
|
32
|
+
expect(obfuscateHeaders({ authorization: ['secret'], dpop: undefined })).toEqual({ authorization: 'Invalid', dpop: 'Invalid' });
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe(obfuscateResSerializer, () => {
|
|
36
|
+
it('redacts response cookies and preserves the status and other headers', () => {
|
|
37
|
+
expect(obfuscateResSerializer({
|
|
38
|
+
statusCode: 201,
|
|
39
|
+
headers: {
|
|
40
|
+
'set-cookie': ['session=secret; HttpOnly'],
|
|
41
|
+
'content-length': 42,
|
|
42
|
+
},
|
|
43
|
+
})).toEqual({
|
|
44
|
+
statusCode: 201,
|
|
45
|
+
headers: { 'set-cookie': '[Redacted]', 'content-length': 42 },
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
it('preserves an unavailable status and missing headers', () => {
|
|
49
|
+
expect(obfuscateResSerializer({})).toEqual({
|
|
50
|
+
statusCode: null,
|
|
51
|
+
headers: undefined,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=obfuscate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obfuscate.test.js","sourceRoot":"","sources":["../src/obfuscate.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAEzE,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,gBAAgB;YACxB,YAAY,EAAE,CAAC,0BAA0B,EAAE,aAAa,CAAC;YACzD,MAAM,EAAE,kBAAkB;YAC1B,gBAAgB,EAAE,EAAE;SACrB,CAAA;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YACxC,MAAM,EAAE,YAAY;YACpB,YAAY,EAAE,YAAY;YAC1B,MAAM,EAAE,kBAAkB;YAC1B,gBAAgB,EAAE,EAAE;SACrB,CAAC,CAAA;QACF,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAC7C,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CACJ,gBAAgB,CAAC;YACf,aAAa,EAAE,yBAAyB;YACxC,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,KAAK;SACd,CAAC,CACH,CAAC,OAAO,CAAC;YACR,aAAa,EAAE,cAAc;YAC7B,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,KAAK;SACd,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,CACJ,gBAAgB,CAAC,EAAE,aAAa,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CACjE,CAAC,OAAO,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,CACJ,sBAAsB,CAAC;YACrB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE;gBACP,YAAY,EAAE,CAAC,0BAA0B,CAAC;gBAC1C,gBAAgB,EAAE,EAAE;aACrB;SACF,CAAC,CACH,CAAC,OAAO,CAAC;YACR,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,EAAE,EAAE;SAC9D,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YACzC,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,SAAS;SACnB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import { describe, expect, it } from 'vitest'\nimport { obfuscateHeaders, obfuscateResSerializer } from './obfuscate.js'\n\ndescribe(obfuscateHeaders, () => {\n it('redacts cookies case-insensitively without modifying the input', () => {\n const headers = {\n Cookie: 'session=secret',\n 'Set-Cookie': ['session=secret; HttpOnly', 'csrf=secret'],\n accept: 'application/json',\n 'content-length': 42,\n }\n expect(obfuscateHeaders(headers)).toEqual({\n Cookie: '[Redacted]',\n 'Set-Cookie': '[Redacted]',\n accept: 'application/json',\n 'content-length': 42,\n })\n expect(headers.Cookie).toBe('session=secret')\n expect(headers['Set-Cookie']).toHaveLength(2)\n })\n\n it('preserves existing authorization and DPoP obfuscation', () => {\n expect(\n obfuscateHeaders({\n Authorization: 'Bearer some-long-secret',\n DPoP: 'not-a-jwt',\n accept: '*/*',\n }),\n ).toEqual({\n Authorization: 'Bearer s***t',\n DPoP: 'Invalid',\n accept: '*/*',\n })\n })\n\n it('does not throw or expose unexpected non-string credentials', () => {\n expect(\n obfuscateHeaders({ authorization: ['secret'], dpop: undefined }),\n ).toEqual({ authorization: 'Invalid', dpop: 'Invalid' })\n })\n})\n\ndescribe(obfuscateResSerializer, () => {\n it('redacts response cookies and preserves the status and other headers', () => {\n expect(\n obfuscateResSerializer({\n statusCode: 201,\n headers: {\n 'set-cookie': ['session=secret; HttpOnly'],\n 'content-length': 42,\n },\n }),\n ).toEqual({\n statusCode: 201,\n headers: { 'set-cookie': '[Redacted]', 'content-length': 42 },\n })\n })\n\n it('preserves an unavailable status and missing headers', () => {\n expect(obfuscateResSerializer({})).toEqual({\n statusCode: null,\n headers: undefined,\n })\n })\n})\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/common",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Shared web-platform-friendly code for atproto libraries",
|
|
6
6
|
"keywords": [
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"node": ">=22"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@atproto/common-web": "^0.5.
|
|
32
|
-
"@atproto/lex-cbor": "^0.1.
|
|
33
|
-
"@atproto/lex-data": "^0.1.
|
|
31
|
+
"@atproto/common-web": "^0.5.17",
|
|
32
|
+
"@atproto/lex-cbor": "^0.1.10",
|
|
33
|
+
"@atproto/lex-data": "^0.1.10",
|
|
34
34
|
"multiformats": "^13.0.0",
|
|
35
35
|
"pino": "^10.3.1"
|
|
36
36
|
},
|