@atproto/lex-client 0.1.5 → 0.2.1

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 (74) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/agent.d.ts +1 -1
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js.map +1 -1
  5. package/dist/client.d.ts +42 -21
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +97 -16
  8. package/dist/client.js.map +1 -1
  9. package/dist/errors.d.ts +6 -4
  10. package/dist/errors.d.ts.map +1 -1
  11. package/dist/errors.js +3 -3
  12. package/dist/errors.js.map +1 -1
  13. package/dist/response.d.ts +3 -2
  14. package/dist/response.d.ts.map +1 -1
  15. package/dist/response.js +2 -1
  16. package/dist/response.js.map +1 -1
  17. package/dist/types.d.ts +1 -1
  18. package/dist/types.d.ts.map +1 -1
  19. package/dist/types.js.map +1 -1
  20. package/dist/util.d.ts +6 -2
  21. package/dist/util.d.ts.map +1 -1
  22. package/dist/util.js +25 -0
  23. package/dist/util.js.map +1 -1
  24. package/dist/write-operation-builder.d.ts +3 -2
  25. package/dist/write-operation-builder.d.ts.map +1 -1
  26. package/dist/write-operation-builder.js +2 -2
  27. package/dist/write-operation-builder.js.map +1 -1
  28. package/dist/xrpc.d.ts +8 -6
  29. package/dist/xrpc.d.ts.map +1 -1
  30. package/dist/xrpc.js +1 -1
  31. package/dist/xrpc.js.map +1 -1
  32. package/package.json +11 -14
  33. package/src/agent.test.ts +0 -216
  34. package/src/agent.ts +0 -186
  35. package/src/client.ts +0 -1086
  36. package/src/errors.test.ts +0 -626
  37. package/src/errors.ts +0 -570
  38. package/src/index.ts +0 -6
  39. package/src/lexicons/com/atproto/repo/applyWrites.defs.ts +0 -201
  40. package/src/lexicons/com/atproto/repo/applyWrites.ts +0 -6
  41. package/src/lexicons/com/atproto/repo/createRecord.defs.ts +0 -58
  42. package/src/lexicons/com/atproto/repo/createRecord.ts +0 -6
  43. package/src/lexicons/com/atproto/repo/defs.defs.ts +0 -28
  44. package/src/lexicons/com/atproto/repo/defs.ts +0 -5
  45. package/src/lexicons/com/atproto/repo/deleteRecord.defs.ts +0 -52
  46. package/src/lexicons/com/atproto/repo/deleteRecord.ts +0 -6
  47. package/src/lexicons/com/atproto/repo/getRecord.defs.ts +0 -37
  48. package/src/lexicons/com/atproto/repo/getRecord.ts +0 -6
  49. package/src/lexicons/com/atproto/repo/listRecords.defs.ts +0 -65
  50. package/src/lexicons/com/atproto/repo/listRecords.ts +0 -6
  51. package/src/lexicons/com/atproto/repo/putRecord.defs.ts +0 -59
  52. package/src/lexicons/com/atproto/repo/putRecord.ts +0 -6
  53. package/src/lexicons/com/atproto/repo/uploadBlob.defs.ts +0 -35
  54. package/src/lexicons/com/atproto/repo/uploadBlob.ts +0 -6
  55. package/src/lexicons/com/atproto/repo.ts +0 -12
  56. package/src/lexicons/com/atproto/sync/getBlob.defs.ts +0 -37
  57. package/src/lexicons/com/atproto/sync/getBlob.ts +0 -6
  58. package/src/lexicons/com/atproto/sync.ts +0 -5
  59. package/src/lexicons/com/atproto.ts +0 -6
  60. package/src/lexicons/com.ts +0 -5
  61. package/src/lexicons/index.ts +0 -5
  62. package/src/response.bench.ts +0 -113
  63. package/src/response.ts +0 -366
  64. package/src/types.ts +0 -71
  65. package/src/util.test.ts +0 -333
  66. package/src/util.ts +0 -182
  67. package/src/write-operation-builder.ts +0 -110
  68. package/src/www-authenticate.test.ts +0 -227
  69. package/src/www-authenticate.ts +0 -101
  70. package/src/xrpc.test.ts +0 -1450
  71. package/src/xrpc.ts +0 -446
  72. package/tsconfig.build.json +0 -12
  73. package/tsconfig.json +0 -7
  74. package/tsconfig.tests.json +0 -8
@@ -1,227 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { parseWWWAuthenticateHeader } from './www-authenticate.js'
3
-
4
- describe(parseWWWAuthenticateHeader, () => {
5
- describe('auth-params', () => {
6
- it('parses single unquoted auth param', () => {
7
- expect(parseWWWAuthenticateHeader('Bearer realm=example.com')).toEqual({
8
- Bearer: { realm: 'example.com' },
9
- })
10
- })
11
-
12
- it('parses single quoted auth param', () => {
13
- expect(parseWWWAuthenticateHeader('Bearer realm="example.com"')).toEqual({
14
- Bearer: { realm: 'example.com' },
15
- })
16
- })
17
-
18
- it('parses quoted values with spaces', () => {
19
- expect(parseWWWAuthenticateHeader('Bearer realm="my realm"')).toEqual({
20
- Bearer: { realm: 'my realm' },
21
- })
22
- })
23
-
24
- it('parses quoted values with escaped double quotes', () => {
25
- expect(
26
- parseWWWAuthenticateHeader('Bearer realm="example\\"quoted\\""'),
27
- ).toEqual({
28
- Bearer: { realm: 'example"quoted"' },
29
- })
30
- })
31
-
32
- it('parses quoted values with escaped backslash', () => {
33
- expect(
34
- parseWWWAuthenticateHeader('Bearer realm="path\\\\to\\\\file"'),
35
- ).toEqual({
36
- Bearer: { realm: 'path\\to\\file' },
37
- })
38
- })
39
-
40
- it('parses param names with hyphens', () => {
41
- expect(
42
- parseWWWAuthenticateHeader('Bearer error-uri="https://example.com"'),
43
- ).toEqual({
44
- Bearer: { 'error-uri': 'https://example.com' },
45
- })
46
- })
47
-
48
- it('parses param names with underscores', () => {
49
- expect(
50
- parseWWWAuthenticateHeader('Bearer error_description="test"'),
51
- ).toEqual({
52
- Bearer: { error_description: 'test' },
53
- })
54
- })
55
-
56
- it('parses param with numeric value', () => {
57
- expect(parseWWWAuthenticateHeader('Bearer max-age=3600')).toEqual({
58
- Bearer: { 'max-age': '3600' },
59
- })
60
- })
61
-
62
- it('parses empty quoted value', () => {
63
- expect(parseWWWAuthenticateHeader('Bearer realm=""')).toEqual({
64
- Bearer: { realm: '' },
65
- })
66
- })
67
-
68
- it('parses Basic auth challenge', () => {
69
- expect(
70
- parseWWWAuthenticateHeader('Basic realm="Access to staging site"'),
71
- ).toEqual({
72
- Basic: { realm: 'Access to staging site' },
73
- })
74
- })
75
-
76
- it('parses Bearer with realm', () => {
77
- expect(
78
- parseWWWAuthenticateHeader('Bearer realm="https://auth.example.com"'),
79
- ).toEqual({
80
- Bearer: { realm: 'https://auth.example.com' },
81
- })
82
- })
83
-
84
- it('parses DPoP with algs param', () => {
85
- expect(parseWWWAuthenticateHeader('DPoP algs="ES256 RS256"')).toEqual({
86
- DPoP: { algs: 'ES256 RS256' },
87
- })
88
- })
89
-
90
- it('parses Digest auth challenge', () => {
91
- const result = parseWWWAuthenticateHeader(
92
- 'Digest realm="digest-realm", nonce="abc123"',
93
- )
94
- expect(result).toEqual({
95
- Digest: { realm: 'digest-realm', nonce: 'abc123' },
96
- })
97
- })
98
-
99
- it('handle empty unquoted params', () => {
100
- const result = parseWWWAuthenticateHeader('Bearer realm=')
101
- expect(result).toEqual({ Bearer: { realm: '' } })
102
- })
103
-
104
- it('handle empty params', () => {
105
- const result = parseWWWAuthenticateHeader('Bearer realm=""')
106
- expect(result).toEqual({ Bearer: { realm: '' } })
107
- })
108
-
109
- it('treats scheme-only header as scheme with itself as token68', () => {
110
- const result = parseWWWAuthenticateHeader('Basic')
111
- expect(result).toEqual({ Basic: {} })
112
- })
113
-
114
- it('parses multiple challenges with commas and escaped quotes', () => {
115
- const result = parseWWWAuthenticateHeader(
116
- `Newauth realm="apps", type=1,\n\t title="Login to \\"apps\\"", Basic realm="simple"`,
117
- )
118
- expect(result).toEqual({
119
- Newauth: {
120
- realm: 'apps',
121
- type: '1',
122
- title: 'Login to "apps"',
123
- },
124
- Basic: { realm: 'simple' },
125
- })
126
- })
127
-
128
- it('parses first challenge before comma', () => {
129
- const result = parseWWWAuthenticateHeader(
130
- 'Basic realm="foo", Bearer realm="bar"',
131
- )
132
- expect(result).toEqual({
133
- Basic: { realm: 'foo' },
134
- Bearer: { realm: 'bar' },
135
- })
136
- })
137
- })
138
-
139
- describe('edge cases', () => {
140
- it('handles empty string', () => {
141
- expect(parseWWWAuthenticateHeader('')).toEqual({})
142
- })
143
-
144
- it('handles whitespace-only string', () => {
145
- expect(parseWWWAuthenticateHeader(' ')).toEqual({})
146
- })
147
-
148
- it('trims whitespace from header', () => {
149
- expect(parseWWWAuthenticateHeader(' Bearer realm="test" ')).toEqual({
150
- Bearer: { realm: 'test' },
151
- })
152
- })
153
-
154
- it('handles commas as quoted param value', () => {
155
- expect(
156
- parseWWWAuthenticateHeader('Bearer realm="example, with, commas"'),
157
- ).toEqual({ Bearer: { realm: 'example, with, commas' } })
158
- })
159
-
160
- it('handles multiple challenges with varying whitespace', () => {
161
- expect(
162
- parseWWWAuthenticateHeader(
163
- ' Bearer realm="test" , Basic rr= ',
164
- ),
165
- ).toEqual({
166
- Bearer: { realm: 'test' },
167
- Basic: { rr: '' },
168
- })
169
- })
170
- })
171
-
172
- describe('invalid challenges', () => {
173
- it('parses single challenge with no comma correctly', () => {
174
- expect(
175
- parseWWWAuthenticateHeader('Bearer realm="oauth" error="invalid"'),
176
- ).toEqual(undefined)
177
- })
178
-
179
- it('ignores invalid challenges', () => {
180
- expect(parseWWWAuthenticateHeader('Bearer realm="unclosed')).toEqual(
181
- undefined,
182
- )
183
- })
184
-
185
- it('handles random text without equals sign as token68', () => {
186
- expect(parseWWWAuthenticateHeader('Bearer sometoken')).toEqual({
187
- Bearer: 'sometoken',
188
- })
189
- })
190
-
191
- it('ignores trailing whitespace after scheme', () => {
192
- expect(parseWWWAuthenticateHeader('Bearer ')).toEqual({ Bearer: {} })
193
- })
194
-
195
- it('handles duplicate params (last wins)', () => {
196
- expect(
197
- parseWWWAuthenticateHeader('Bearer realm="first", realm="second"'),
198
- ).toEqual({ Bearer: { realm: 'second' } })
199
- })
200
-
201
- it('extracts valid param after invalid characters', () => {
202
- expect(parseWWWAuthenticateHeader('Bearer realm@foo="bar"')).toEqual({
203
- Bearer: { 'realm@foo': 'bar' },
204
- })
205
- })
206
-
207
- it('ignores param with empty name', () => {
208
- expect(parseWWWAuthenticateHeader('Bearer ="value"')).toEqual(undefined)
209
- })
210
-
211
- it('handles completely malformed input gracefully', () => {
212
- expect(parseWWWAuthenticateHeader('!@#$%')).toEqual({ '!@#$%': {} })
213
- })
214
-
215
- it('handles duplicate schemes as invalid', () => {
216
- expect(
217
- parseWWWAuthenticateHeader('Basic realm="first", Basic realm="second"'),
218
- ).toEqual(undefined)
219
- })
220
-
221
- it('handles params without scheme as invalid', () => {
222
- expect(parseWWWAuthenticateHeader('Bearer, realm="foo"')).toEqual(
223
- undefined,
224
- )
225
- })
226
- })
227
- })
@@ -1,101 +0,0 @@
1
- type WWWAuthenticateParams = { [authParam in string]: string }
2
-
3
- /**
4
- * Parsed representation of a WWW-Authenticate HTTP header.
5
- *
6
- * Maps authentication scheme names to either:
7
- * - A token68 string (compact authentication data)
8
- * - A params object with key-value pairs
9
- *
10
- * @example Bearer with realm
11
- * ```typescript
12
- * // WWW-Authenticate: Bearer realm="example"
13
- * const parsed: WWWAuthenticate = {
14
- * Bearer: { realm: 'example' }
15
- * }
16
- * ```
17
- *
18
- * @example DPoP with error
19
- * ```typescript
20
- * // WWW-Authenticate: DPoP error="use_dpop_nonce", error_description="..."
21
- * const parsed: WWWAuthenticate = {
22
- * DPoP: { error: 'use_dpop_nonce', error_description: '...' }
23
- * }
24
- * ```
25
- */
26
- export type WWWAuthenticate = {
27
- [authScheme in string]:
28
- | string // token68
29
- | WWWAuthenticateParams
30
- }
31
-
32
- /**
33
- * Returns `undefined` if the header is malformed.
34
- */
35
- export function parseWWWAuthenticateHeader(
36
- header?: unknown,
37
- ): undefined | WWWAuthenticate {
38
- if (typeof header !== 'string') return undefined
39
-
40
- const wwwAuthenticate: WWWAuthenticate = {}
41
-
42
- // Split over commas, not within quoted strings
43
- const trimmedHeader = header.trim()
44
- if (!trimmedHeader) return wwwAuthenticate
45
-
46
- const parts = trimmedHeader.split(/,(?=(?:[^"]*"[^"]*")*[^"]*$)/)
47
-
48
- let currentParams: WWWAuthenticateParams | null = null
49
-
50
- for (let part of parts) {
51
- // Check if the part starts with an auth scheme
52
- const schemeMatch = part.trim().match(/^([^"=\s]+)(\s+.*)?$/)
53
- if (schemeMatch) {
54
- const scheme = schemeMatch[1]
55
-
56
- // Duplicate scheme
57
- if (Object.hasOwn(wwwAuthenticate, scheme)) return undefined
58
-
59
- const rest = schemeMatch[2]?.trim()
60
- if (!rest) {
61
- // Scheme only (no params or token68)
62
- currentParams = null
63
- wwwAuthenticate[scheme] = Object.create(null)
64
- continue
65
- }
66
-
67
- if (!rest.includes('=')) {
68
- // Scheme with token68
69
- currentParams = null
70
- wwwAuthenticate[scheme] = rest
71
- continue
72
- }
73
-
74
- // Scheme with params
75
-
76
- currentParams = Object.create(null) as WWWAuthenticateParams
77
- wwwAuthenticate[scheme] = currentParams
78
-
79
- // Fall through to parse params
80
- part = rest
81
- }
82
-
83
- // Invalid header
84
- if (!currentParams) return undefined
85
-
86
- const param = part.match(
87
- /^\s*([^"\s=]+)=(?:("[^"\\]*(?:\\.[^"\\]*)*")|([^\s,"]*))\s*$/,
88
- )
89
-
90
- // invalid param
91
- if (!param) return undefined
92
-
93
- const paramName = param[1]
94
- const paramValue =
95
- param[3] ?? param[2]!.slice(1, -1).replaceAll(/\\(.)/g, '$1')
96
-
97
- currentParams[paramName] = paramValue
98
- }
99
-
100
- return wwwAuthenticate
101
- }