@atproto/lex-server 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/dist/errors.d.ts +94 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +94 -0
- package/dist/errors.js.map +1 -1
- package/dist/lex-server.d.ts +481 -2
- package/dist/lex-server.d.ts.map +1 -1
- package/dist/lex-server.js +103 -0
- package/dist/lex-server.js.map +1 -1
- package/dist/lib/www-authenticate.d.ts +66 -0
- package/dist/lib/www-authenticate.d.ts.map +1 -1
- package/dist/lib/www-authenticate.js +28 -0
- package/dist/lib/www-authenticate.js.map +1 -1
- package/dist/nodejs.d.ts +279 -0
- package/dist/nodejs.d.ts.map +1 -1
- package/dist/nodejs.js +184 -1
- package/dist/nodejs.js.map +1 -1
- package/dist/service-auth.d.ts +151 -9
- package/dist/service-auth.d.ts.map +1 -1
- package/dist/service-auth.js +41 -2
- package/dist/service-auth.js.map +1 -1
- package/package.json +11 -11
- package/src/errors.ts +94 -0
- package/src/lex-server.test.ts +3 -2
- package/src/lex-server.ts +482 -2
- package/src/lib/www-authenticate.ts +66 -0
- package/src/nodejs.ts +280 -2
- package/src/service-auth.ts +151 -9
package/src/errors.ts
CHANGED
|
@@ -6,11 +6,54 @@ import {
|
|
|
6
6
|
|
|
7
7
|
export type { WWWAuthenticate }
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Error class for authentication failures in XRPC server handlers.
|
|
11
|
+
*
|
|
12
|
+
* Extends {@link LexError} to include WWW-Authenticate header support,
|
|
13
|
+
* which is required by HTTP authentication standards (RFC 7235).
|
|
14
|
+
* The error automatically generates the appropriate 401 response with
|
|
15
|
+
* the WWW-Authenticate header when converted to a Response.
|
|
16
|
+
*
|
|
17
|
+
* @typeParam N - The Lexicon error code type
|
|
18
|
+
*
|
|
19
|
+
* @example Throwing an auth error
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { LexServerAuthError } from '@atproto/lex-server'
|
|
22
|
+
*
|
|
23
|
+
* throw new LexServerAuthError(
|
|
24
|
+
* 'AuthenticationRequired',
|
|
25
|
+
* 'Invalid or expired token',
|
|
26
|
+
* { Bearer: { error: 'InvalidToken', realm: 'api.example.com' } }
|
|
27
|
+
* )
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Converting from a LexError
|
|
31
|
+
* ```typescript
|
|
32
|
+
* try {
|
|
33
|
+
* await validateToken(token)
|
|
34
|
+
* } catch (error) {
|
|
35
|
+
* if (error instanceof LexError) {
|
|
36
|
+
* throw LexServerAuthError.from(error, {
|
|
37
|
+
* Bearer: { error: 'InvalidToken' }
|
|
38
|
+
* })
|
|
39
|
+
* }
|
|
40
|
+
* throw error
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
9
44
|
export class LexServerAuthError<
|
|
10
45
|
N extends LexErrorCode = LexErrorCode,
|
|
11
46
|
> extends LexError<N> {
|
|
12
47
|
name = 'LexServerAuthError'
|
|
13
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new authentication error.
|
|
51
|
+
*
|
|
52
|
+
* @param error - The Lexicon error code (e.g., 'AuthenticationRequired')
|
|
53
|
+
* @param message - Human-readable error message
|
|
54
|
+
* @param wwwAuthenticate - WWW-Authenticate header parameters
|
|
55
|
+
* @param options - Standard Error options including `cause`
|
|
56
|
+
*/
|
|
14
57
|
constructor(
|
|
15
58
|
error: N,
|
|
16
59
|
message: string,
|
|
@@ -20,15 +63,48 @@ export class LexServerAuthError<
|
|
|
20
63
|
super(error, message, options)
|
|
21
64
|
}
|
|
22
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Gets the formatted WWW-Authenticate header value.
|
|
68
|
+
*
|
|
69
|
+
* @returns The formatted header string for the 401 response
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const error = new LexServerAuthError('AuthenticationRequired', 'Token required', {
|
|
74
|
+
* Bearer: { realm: 'api.example.com', error: 'MissingToken' }
|
|
75
|
+
* })
|
|
76
|
+
* console.log(error.wwwAuthenticateHeader)
|
|
77
|
+
* // Output: 'Bearer realm="api.example.com", error="MissingToken"'
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
23
80
|
get wwwAuthenticateHeader(): string {
|
|
24
81
|
return formatWWWAuthenticateHeader(this.wwwAuthenticate)
|
|
25
82
|
}
|
|
26
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Converts the error to a JSON representation suitable for response bodies.
|
|
86
|
+
*
|
|
87
|
+
* If the error was created from another LexError (via `from()`), returns
|
|
88
|
+
* the original error's JSON representation.
|
|
89
|
+
*
|
|
90
|
+
* @returns JSON object with error code and message
|
|
91
|
+
*/
|
|
27
92
|
toJSON() {
|
|
28
93
|
const { cause } = this
|
|
29
94
|
return cause instanceof LexError ? cause.toJSON() : super.toJSON()
|
|
30
95
|
}
|
|
31
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Converts the error to an HTTP 401 Response with WWW-Authenticate header.
|
|
99
|
+
*
|
|
100
|
+
* The response includes:
|
|
101
|
+
* - Status code 401 (Unauthorized)
|
|
102
|
+
* - WWW-Authenticate header (if parameters were provided)
|
|
103
|
+
* - Access-Control-Expose-Headers for CORS compatibility
|
|
104
|
+
* - JSON body with error details
|
|
105
|
+
*
|
|
106
|
+
* @returns HTTP Response object ready to be sent to the client
|
|
107
|
+
*/
|
|
32
108
|
toResponse(): Response {
|
|
33
109
|
const { wwwAuthenticateHeader } = this
|
|
34
110
|
|
|
@@ -42,6 +118,24 @@ export class LexServerAuthError<
|
|
|
42
118
|
return Response.json(this.toJSON(), { status: 401, headers })
|
|
43
119
|
}
|
|
44
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Creates a LexServerAuthError from an existing LexError.
|
|
123
|
+
*
|
|
124
|
+
* If the input is already a LexServerAuthError, returns it unchanged.
|
|
125
|
+
* Otherwise, wraps the error with the provided WWW-Authenticate parameters.
|
|
126
|
+
*
|
|
127
|
+
* @param cause - The original LexError to wrap
|
|
128
|
+
* @param wwwAuthenticate - WWW-Authenticate header parameters
|
|
129
|
+
* @returns A LexServerAuthError instance
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const lexError = new LexError('AuthenticationRequired', 'Token expired')
|
|
134
|
+
* const authError = LexServerAuthError.from(lexError, {
|
|
135
|
+
* Bearer: { error: 'ExpiredToken' }
|
|
136
|
+
* })
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
45
139
|
static from(
|
|
46
140
|
cause: LexError,
|
|
47
141
|
wwwAuthenticate?: WWWAuthenticate,
|
package/src/lex-server.test.ts
CHANGED
|
@@ -1509,6 +1509,7 @@ describe('Subscription', () => {
|
|
|
1509
1509
|
|
|
1510
1510
|
it('handles subscriptions with cleanup', async () => {
|
|
1511
1511
|
let sentCount = 0
|
|
1512
|
+
const maxMessages = 10
|
|
1512
1513
|
|
|
1513
1514
|
const { resolve, promise: finallyPromise } = timeoutDeferred(5000)
|
|
1514
1515
|
|
|
@@ -1516,7 +1517,7 @@ describe('Subscription', () => {
|
|
|
1516
1517
|
io.example.subscribe,
|
|
1517
1518
|
async function* ({ params: { message }, signal }) {
|
|
1518
1519
|
try {
|
|
1519
|
-
for (; sentCount <
|
|
1520
|
+
for (; sentCount < maxMessages; ) {
|
|
1520
1521
|
await scheduler.wait(5, { signal })
|
|
1521
1522
|
yield { message, count: ++sentCount }
|
|
1522
1523
|
}
|
|
@@ -1558,7 +1559,7 @@ describe('Subscription', () => {
|
|
|
1558
1559
|
])
|
|
1559
1560
|
|
|
1560
1561
|
expect(sentCount).toBeGreaterThanOrEqual(3)
|
|
1561
|
-
expect(sentCount).toBeLessThan(
|
|
1562
|
+
expect(sentCount).toBeLessThan(maxMessages)
|
|
1562
1563
|
})
|
|
1563
1564
|
|
|
1564
1565
|
it('returns 405 for non-GET request', async () => {
|