@atproto/lex-schema 0.0.10 → 0.0.12
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 +26 -0
- package/dist/core/$type.d.ts +149 -0
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js +44 -0
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +44 -0
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js +30 -0
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/result.d.ts +85 -4
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +60 -4
- package/dist/core/result.js.map +1 -1
- package/dist/core/schema.d.ts +229 -2
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +197 -4
- package/dist/core/schema.js.map +1 -1
- package/dist/core/string-format.d.ts +244 -11
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +150 -0
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/types.d.ts +90 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/validation-error.d.ts +61 -1
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +60 -0
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validation-issue.d.ts +61 -0
- package/dist/core/validation-issue.d.ts.map +1 -1
- package/dist/core/validation-issue.js +51 -0
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.d.ts +347 -10
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +184 -3
- package/dist/core/validator.js.map +1 -1
- package/dist/helpers.d.ts +13 -25
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -2
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +45 -0
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +14 -0
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +46 -0
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +39 -0
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.d.ts +28 -0
- package/dist/schema/boolean.d.ts.map +1 -1
- package/dist/schema/boolean.js +28 -0
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.d.ts +38 -0
- package/dist/schema/bytes.d.ts.map +1 -1
- package/dist/schema/bytes.js +32 -0
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +38 -0
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +33 -0
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.d.ts +66 -1
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js +54 -0
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +44 -0
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +44 -0
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +58 -0
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +45 -0
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.d.ts +48 -0
- package/dist/schema/enum.d.ts.map +1 -1
- package/dist/schema/enum.js +48 -0
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.d.ts +42 -0
- package/dist/schema/integer.d.ts.map +1 -1
- package/dist/schema/integer.js +36 -0
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +54 -0
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +49 -0
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/literal.d.ts +44 -0
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +44 -0
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.d.ts +42 -0
- package/dist/schema/never.d.ts.map +1 -1
- package/dist/schema/never.js +42 -0
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.d.ts +29 -0
- package/dist/schema/null.d.ts.map +1 -1
- package/dist/schema/null.js +29 -0
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +41 -0
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +41 -0
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +56 -0
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +51 -0
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +42 -0
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +42 -0
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +89 -7
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +84 -10
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +111 -15
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +70 -0
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +58 -0
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +50 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +42 -0
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js +39 -0
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +64 -0
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +64 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +55 -0
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +55 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +63 -8
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +20 -0
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +50 -0
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +17 -0
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +58 -9
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.d.ts +44 -0
- package/dist/schema/regexp.d.ts.map +1 -1
- package/dist/schema/regexp.js +44 -0
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +50 -0
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +41 -0
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +72 -2
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +59 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +47 -0
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +47 -0
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +62 -8
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +18 -0
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +53 -0
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +15 -0
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +50 -1
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +50 -1
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +45 -0
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +40 -0
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown-object.d.ts +34 -0
- package/dist/schema/unknown-object.d.ts.map +1 -1
- package/dist/schema/unknown-object.js +31 -0
- package/dist/schema/unknown-object.js.map +1 -1
- package/dist/schema/unknown.d.ts +33 -0
- package/dist/schema/unknown.d.ts.map +1 -1
- package/dist/schema/unknown.js +33 -0
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +44 -0
- package/dist/schema/with-default.d.ts.map +1 -1
- package/dist/schema/with-default.js +44 -0
- package/dist/schema/with-default.js.map +1 -1
- package/package.json +4 -4
- package/src/core/$type.ts +150 -18
- package/src/core/record-key.ts +44 -0
- package/src/core/result.ts +86 -4
- package/src/core/schema.ts +236 -7
- package/src/core/string-format.ts +259 -13
- package/src/core/types.ts +91 -3
- package/src/core/validation-error.ts +60 -0
- package/src/core/validation-issue.ts +65 -0
- package/src/core/validator.ts +351 -10
- package/src/helpers.test.ts +110 -29
- package/src/helpers.ts +14 -14
- package/src/schema/array.test.ts +94 -79
- package/src/schema/array.ts +45 -0
- package/src/schema/blob.ts +46 -0
- package/src/schema/boolean.ts +28 -0
- package/src/schema/bytes.ts +38 -0
- package/src/schema/cid.ts +38 -0
- package/src/schema/custom.ts +66 -1
- package/src/schema/dict.ts +44 -0
- package/src/schema/discriminated-union.ts +58 -0
- package/src/schema/enum.ts +48 -0
- package/src/schema/integer.ts +42 -0
- package/src/schema/intersection.ts +54 -0
- package/src/schema/literal.ts +44 -0
- package/src/schema/never.ts +42 -0
- package/src/schema/null.ts +29 -0
- package/src/schema/nullable.ts +41 -0
- package/src/schema/object.ts +56 -0
- package/src/schema/optional.ts +42 -0
- package/src/schema/params.test.ts +58 -2
- package/src/schema/params.ts +124 -16
- package/src/schema/payload.test.ts +3 -3
- package/src/schema/payload.ts +142 -38
- package/src/schema/permission-set.ts +58 -0
- package/src/schema/permission.ts +42 -0
- package/src/schema/procedure.ts +64 -0
- package/src/schema/query.ts +55 -0
- package/src/schema/record.ts +63 -8
- package/src/schema/ref.ts +50 -0
- package/src/schema/refine.ts +58 -9
- package/src/schema/regexp.ts +44 -0
- package/src/schema/string.ts +50 -0
- package/src/schema/subscription.ts +72 -2
- package/src/schema/token.ts +47 -0
- package/src/schema/typed-object.ts +62 -8
- package/src/schema/typed-ref.ts +53 -0
- package/src/schema/typed-union.ts +55 -2
- package/src/schema/union.ts +45 -0
- package/src/schema/unknown-object.ts +34 -0
- package/src/schema/unknown.ts +33 -0
- package/src/schema/with-default.ts +44 -0
|
@@ -3,7 +3,7 @@ import { integer } from './integer.js'
|
|
|
3
3
|
import { object } from './object.js'
|
|
4
4
|
import { payload } from './payload.js'
|
|
5
5
|
import { string } from './string.js'
|
|
6
|
-
import {
|
|
6
|
+
import { unknownObject } from './unknown-object.js'
|
|
7
7
|
|
|
8
8
|
describe('Payload', () => {
|
|
9
9
|
describe('basic construction', () => {
|
|
@@ -113,7 +113,7 @@ describe('Payload', () => {
|
|
|
113
113
|
})
|
|
114
114
|
|
|
115
115
|
it('creates payload with unknown schema', () => {
|
|
116
|
-
const schema =
|
|
116
|
+
const schema = object({})
|
|
117
117
|
const def = payload('application/json', schema)
|
|
118
118
|
expect(def.encoding).toBe('application/json')
|
|
119
119
|
expect(def.schema).toBe(schema)
|
|
@@ -224,7 +224,7 @@ describe('Payload', () => {
|
|
|
224
224
|
'application/json',
|
|
225
225
|
object({
|
|
226
226
|
success: string(),
|
|
227
|
-
data:
|
|
227
|
+
data: unknownObject(),
|
|
228
228
|
}),
|
|
229
229
|
)
|
|
230
230
|
expect(def.encoding).toBe('application/json')
|
package/src/schema/payload.ts
CHANGED
|
@@ -1,50 +1,101 @@
|
|
|
1
1
|
import { LexValue } from '@atproto/lex-data'
|
|
2
|
-
import { Infer, Schema } from '../core.js'
|
|
3
|
-
import { ObjectSchema,
|
|
4
|
-
|
|
5
|
-
export type
|
|
6
|
-
TPayload extends Payload,
|
|
7
|
-
TBody,
|
|
8
|
-
> = TPayload['encoding'] extends infer E extends string
|
|
9
|
-
? {
|
|
10
|
-
encoding: SchemaEncodingToDataEncoding<E>
|
|
11
|
-
body: InferPayloadBody<TPayload, TBody>
|
|
12
|
-
}
|
|
13
|
-
: void | undefined
|
|
2
|
+
import { Infer, Schema, Validator } from '../core.js'
|
|
3
|
+
import { ObjectSchema, object } from './object.js'
|
|
4
|
+
|
|
5
|
+
export type { LexValue }
|
|
14
6
|
|
|
15
|
-
|
|
7
|
+
type ToBodyMime<TEncoding extends string> = TEncoding extends '*/*'
|
|
16
8
|
? `${string}/${string}`
|
|
17
|
-
:
|
|
9
|
+
: TEncoding extends `${infer T extends string}/*`
|
|
18
10
|
? `${T}/${string}`
|
|
19
|
-
:
|
|
11
|
+
: TEncoding
|
|
12
|
+
|
|
13
|
+
type ToBodyType<
|
|
14
|
+
TEncoding extends string,
|
|
15
|
+
TSchema,
|
|
16
|
+
TBinary,
|
|
17
|
+
> = TSchema extends Schema
|
|
18
|
+
? Infer<TSchema>
|
|
19
|
+
: TEncoding extends `application/json`
|
|
20
|
+
? LexValue
|
|
21
|
+
: TBinary
|
|
20
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Infers the type of a Payload's encoding and body.
|
|
25
|
+
*
|
|
26
|
+
* @template TPayload - The Payload type
|
|
27
|
+
* @template TBody - Fallback body type for non-JSON encodings
|
|
28
|
+
*/
|
|
29
|
+
export type InferPayload<TPayload extends Payload, TBinary> =
|
|
30
|
+
TPayload extends Payload<infer TEncoding, infer TSchema>
|
|
31
|
+
? TEncoding extends string
|
|
32
|
+
? {
|
|
33
|
+
encoding: ToBodyMime<TEncoding>
|
|
34
|
+
body: ToBodyType<TEncoding, TSchema, TBinary>
|
|
35
|
+
}
|
|
36
|
+
: undefined
|
|
37
|
+
: never
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Converts schema encoding patterns to data encoding types.
|
|
41
|
+
*
|
|
42
|
+
* Handles wildcards like '*\/*' and 'image/*' in MIME types.
|
|
43
|
+
*
|
|
44
|
+
* @template TPayload - The Payload type
|
|
45
|
+
*/
|
|
21
46
|
export type InferPayloadEncoding<TPayload extends Payload> =
|
|
22
|
-
TPayload
|
|
23
|
-
?
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
TPayload extends Payload<infer TEncoding, any>
|
|
48
|
+
? TEncoding extends string
|
|
49
|
+
? ToBodyMime<TEncoding>
|
|
50
|
+
: undefined
|
|
51
|
+
: never
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Infers the body type from a Payload and fallback type.
|
|
55
|
+
*
|
|
56
|
+
* @template TPayload - The Payload type
|
|
57
|
+
* @template TBody - Fallback body type for non-JSON encodings without schema
|
|
58
|
+
*/
|
|
59
|
+
export type InferPayloadBody<TPayload extends Payload, TBinary> =
|
|
60
|
+
TPayload extends Payload<infer TEncoding, infer TSchema>
|
|
61
|
+
? TEncoding extends string
|
|
62
|
+
? ToBodyType<TEncoding, TSchema, TBinary>
|
|
63
|
+
: undefined
|
|
64
|
+
: never
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Determines valid schema type based on encoding presence.
|
|
68
|
+
*
|
|
69
|
+
* @template E - The encoding string type, or undefined
|
|
70
|
+
*/
|
|
71
|
+
export type PayloadSchema<E extends string | undefined> = E extends undefined
|
|
38
72
|
? undefined
|
|
39
|
-
: Schema | undefined
|
|
73
|
+
: Schema<LexValue> | undefined
|
|
40
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Represents a payload definition for Lexicon endpoints.
|
|
77
|
+
*
|
|
78
|
+
* Payloads define the body format for HTTP requests and responses.
|
|
79
|
+
* They consist of an encoding (MIME type) and an optional schema
|
|
80
|
+
* for validating the body content.
|
|
81
|
+
*
|
|
82
|
+
* @template TEncoding - The MIME type string, or undefined for no body
|
|
83
|
+
* @template TPayload - The schema type for body validation
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const jsonPayload = new Payload('application/json', l.object({ data: l.string() }))
|
|
88
|
+
* const binaryPayload = new Payload('image/*', undefined)
|
|
89
|
+
* const noPayload = new Payload(undefined, undefined)
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
41
92
|
export class Payload<
|
|
42
93
|
const TEncoding extends string | undefined = string | undefined,
|
|
43
|
-
const
|
|
94
|
+
const TSchema extends PayloadSchema<TEncoding> = PayloadSchema<TEncoding>,
|
|
44
95
|
> {
|
|
45
96
|
constructor(
|
|
46
97
|
readonly encoding: TEncoding,
|
|
47
|
-
readonly schema:
|
|
98
|
+
readonly schema: TSchema,
|
|
48
99
|
) {
|
|
49
100
|
if (encoding === undefined && schema !== undefined) {
|
|
50
101
|
throw new TypeError('schema cannot be defined when encoding is undefined')
|
|
@@ -86,17 +137,70 @@ export class Payload<
|
|
|
86
137
|
}
|
|
87
138
|
}
|
|
88
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Creates a payload definition for Lexicon endpoint bodies.
|
|
142
|
+
*
|
|
143
|
+
* Defines the expected MIME type and optional validation schema for
|
|
144
|
+
* request or response bodies.
|
|
145
|
+
*
|
|
146
|
+
* @param encoding - MIME type string (e.g., 'application/json', 'image/*'), or undefined for no body
|
|
147
|
+
* @param validator - Optional schema for validating the body content. Must be undefined if encoding is undefined.
|
|
148
|
+
* @returns A new {@link Payload} instance
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* // JSON payload with schema
|
|
153
|
+
* const output = l.payload('application/json', l.object({
|
|
154
|
+
* posts: l.array(postSchema),
|
|
155
|
+
* cursor: l.optional(l.string()),
|
|
156
|
+
* }))
|
|
157
|
+
*
|
|
158
|
+
* // Binary payload (no schema validation)
|
|
159
|
+
* const blobInput = l.payload('*\/*', undefined)
|
|
160
|
+
*
|
|
161
|
+
* // Image payload with wildcard
|
|
162
|
+
* const imageInput = l.payload('image/*', undefined)
|
|
163
|
+
*
|
|
164
|
+
* // No payload (for endpoints without body)
|
|
165
|
+
* const noBody = l.payload()
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
89
168
|
/*@__NO_SIDE_EFFECTS__*/
|
|
90
169
|
export function payload<
|
|
91
170
|
const E extends string | undefined = undefined,
|
|
92
|
-
const S extends
|
|
171
|
+
const S extends PayloadSchema<E> = undefined,
|
|
93
172
|
>(encoding: E = undefined as E, validator: S = undefined as S) {
|
|
94
173
|
return new Payload<E, S>(encoding, validator)
|
|
95
174
|
}
|
|
96
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Creates a JSON payload with an object schema.
|
|
178
|
+
*
|
|
179
|
+
* Convenience function for the common case of JSON request/response bodies.
|
|
180
|
+
* Equivalent to `l.payload('application/json', l.object(properties))`.
|
|
181
|
+
*
|
|
182
|
+
* @param properties - Object mapping property names to validators
|
|
183
|
+
* @returns A new {@link Payload} instance with 'application/json' encoding
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* // Query output
|
|
188
|
+
* const profileOutput = l.jsonPayload({
|
|
189
|
+
* did: l.string({ format: 'did' }),
|
|
190
|
+
* handle: l.string({ format: 'handle' }),
|
|
191
|
+
* displayName: l.optional(l.string()),
|
|
192
|
+
* })
|
|
193
|
+
*
|
|
194
|
+
* // Procedure input
|
|
195
|
+
* const createPostInput = l.jsonPayload({
|
|
196
|
+
* text: l.string({ maxGraphemes: 300 }),
|
|
197
|
+
* createdAt: l.string({ format: 'datetime' }),
|
|
198
|
+
* })
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
97
201
|
/*@__NO_SIDE_EFFECTS__*/
|
|
98
|
-
export function jsonPayload<
|
|
99
|
-
|
|
100
|
-
): Payload<'application/json', ObjectSchema<P>> {
|
|
202
|
+
export function jsonPayload<
|
|
203
|
+
P extends Record<string, Validator<undefined | LexValue>>,
|
|
204
|
+
>(properties: P): Payload<'application/json', ObjectSchema<P>> {
|
|
101
205
|
return payload('application/json', object(properties))
|
|
102
206
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { NsidString } from '../core.js'
|
|
2
2
|
import { Permission } from './permission.js'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Configuration options for a permission set.
|
|
6
|
+
*
|
|
7
|
+
* @property title - Human-readable title for the permission set
|
|
8
|
+
* @property title:lang - Localized titles by language code
|
|
9
|
+
* @property detail - Detailed description of the permission set
|
|
10
|
+
* @property detail:lang - Localized descriptions by language code
|
|
11
|
+
*/
|
|
4
12
|
export type PermissionSetOptions = {
|
|
5
13
|
title?: string
|
|
6
14
|
'title:lang'?: Record<string, undefined | string>
|
|
@@ -8,6 +16,24 @@ export type PermissionSetOptions = {
|
|
|
8
16
|
'detail:lang'?: Record<string, undefined | string>
|
|
9
17
|
}
|
|
10
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Represents a collection of related permissions in AT Protocol.
|
|
21
|
+
*
|
|
22
|
+
* Permission sets group permissions together with metadata for OAuth
|
|
23
|
+
* authorization flows. They are identified by an NSID.
|
|
24
|
+
*
|
|
25
|
+
* @template TNsid - The NSID identifying this permission set
|
|
26
|
+
* @template TPermissions - Tuple type of the included permissions
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const feedAccess = new PermissionSet(
|
|
31
|
+
* 'app.bsky.feed.access',
|
|
32
|
+
* [readPermission, writePermission],
|
|
33
|
+
* { title: 'Feed Access', detail: 'Read and write to your feed' }
|
|
34
|
+
* )
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
11
37
|
export class PermissionSet<
|
|
12
38
|
const TNsid extends NsidString = any,
|
|
13
39
|
const TPermissions extends readonly Permission[] = any,
|
|
@@ -19,6 +45,38 @@ export class PermissionSet<
|
|
|
19
45
|
) {}
|
|
20
46
|
}
|
|
21
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Creates a permission set grouping related permissions.
|
|
50
|
+
*
|
|
51
|
+
* Permission sets define OAuth scopes that applications can request.
|
|
52
|
+
* They include human-readable metadata for authorization UIs.
|
|
53
|
+
*
|
|
54
|
+
* @param nsid - The NSID identifying this permission set
|
|
55
|
+
* @param permissions - Array of permissions included in this set
|
|
56
|
+
* @param options - Optional metadata (title, detail, localization)
|
|
57
|
+
* @returns A new {@link PermissionSet} instance
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* // Define individual permissions
|
|
62
|
+
* const readPosts = l.permission('read', { collection: 'app.bsky.feed.post' })
|
|
63
|
+
* const writePosts = l.permission('write', { collection: 'app.bsky.feed.post' })
|
|
64
|
+
*
|
|
65
|
+
* // Group into a permission set
|
|
66
|
+
* const postManagement = l.permissionSet(
|
|
67
|
+
* 'app.bsky.feed.postManagement',
|
|
68
|
+
* [readPosts, writePosts],
|
|
69
|
+
* {
|
|
70
|
+
* title: 'Post Management',
|
|
71
|
+
* detail: 'View and create posts on your behalf',
|
|
72
|
+
* 'title:lang': {
|
|
73
|
+
* 'es': 'Gestion de publicaciones',
|
|
74
|
+
* 'fr': 'Gestion des publications',
|
|
75
|
+
* },
|
|
76
|
+
* }
|
|
77
|
+
* )
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
22
80
|
/*@__NO_SIDE_EFFECTS__*/
|
|
23
81
|
export function permissionSet<
|
|
24
82
|
const N extends NsidString,
|
package/src/schema/permission.ts
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import { Params } from './params.js'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Type alias for permission options (same as Params).
|
|
5
|
+
*/
|
|
3
6
|
export type PermissionOptions = Params
|
|
4
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Represents a single permission in an AT Protocol permission set.
|
|
10
|
+
*
|
|
11
|
+
* Permissions define access rights to specific resources with optional
|
|
12
|
+
* parameters for fine-grained control.
|
|
13
|
+
*
|
|
14
|
+
* @template TResource - The resource identifier string type
|
|
15
|
+
* @template TOptions - The options type (must be valid Params)
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const readPermission = new Permission('read', { collection: 'app.bsky.feed.post' })
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
5
22
|
export class Permission<
|
|
6
23
|
const TResource extends string = any,
|
|
7
24
|
const TOptions extends PermissionOptions = any,
|
|
@@ -12,6 +29,31 @@ export class Permission<
|
|
|
12
29
|
) {}
|
|
13
30
|
}
|
|
14
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Creates a permission definition for AT Protocol authorization.
|
|
34
|
+
*
|
|
35
|
+
* Permissions specify what resources an application can access.
|
|
36
|
+
* Used in permission sets to define OAuth scopes.
|
|
37
|
+
*
|
|
38
|
+
* @param resource - The resource identifier (e.g., 'read', 'write', 'admin')
|
|
39
|
+
* @param options - Optional parameters for the permission
|
|
40
|
+
* @returns A new {@link Permission} instance
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* // Simple permission
|
|
45
|
+
* const readPermission = l.permission('read')
|
|
46
|
+
*
|
|
47
|
+
* // Permission with options
|
|
48
|
+
* const writePostsPermission = l.permission('write', {
|
|
49
|
+
* collection: 'app.bsky.feed.post',
|
|
50
|
+
* })
|
|
51
|
+
*
|
|
52
|
+
* // Multiple permissions with different scopes
|
|
53
|
+
* const readProfile = l.permission('read', { collection: 'app.bsky.actor.profile' })
|
|
54
|
+
* const readFeed = l.permission('read', { collection: 'app.bsky.feed.*' })
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
15
57
|
/*@__NO_SIDE_EFFECTS__*/
|
|
16
58
|
export function permission<
|
|
17
59
|
const R extends string,
|
package/src/schema/procedure.ts
CHANGED
|
@@ -2,6 +2,30 @@ import { NsidString } from '../core.js'
|
|
|
2
2
|
import { ParamsSchema } from './params.js'
|
|
3
3
|
import { Payload } from './payload.js'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Represents a Lexicon procedure (HTTP POST) endpoint definition.
|
|
7
|
+
*
|
|
8
|
+
* Procedures are operations that may modify state on the server.
|
|
9
|
+
* They have parameters, an input payload (request body), an output
|
|
10
|
+
* payload (response body), and optional error types.
|
|
11
|
+
*
|
|
12
|
+
* @template TNsid - The NSID identifying this procedure
|
|
13
|
+
* @template TParameters - The parameters schema type
|
|
14
|
+
* @template TInputPayload - The request body payload type
|
|
15
|
+
* @template TOutputPayload - The response body payload type
|
|
16
|
+
* @template TErrors - Array of error type strings, or undefined
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const createPost = new Procedure(
|
|
21
|
+
* 'app.bsky.feed.post',
|
|
22
|
+
* l.params({}),
|
|
23
|
+
* l.jsonPayload({ text: l.string() }),
|
|
24
|
+
* l.jsonPayload({ uri: l.string(), cid: l.string() }),
|
|
25
|
+
* ['InvalidRecord']
|
|
26
|
+
* )
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
5
29
|
export class Procedure<
|
|
6
30
|
const TNsid extends NsidString = NsidString,
|
|
7
31
|
const TParameters extends ParamsSchema = ParamsSchema,
|
|
@@ -22,6 +46,46 @@ export class Procedure<
|
|
|
22
46
|
) {}
|
|
23
47
|
}
|
|
24
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Creates a procedure definition for a Lexicon POST endpoint.
|
|
51
|
+
*
|
|
52
|
+
* Procedures can modify server state. They accept both URL parameters
|
|
53
|
+
* and a request body (input payload).
|
|
54
|
+
*
|
|
55
|
+
* @param nsid - The NSID identifying this procedure endpoint
|
|
56
|
+
* @param parameters - Schema for URL query parameters
|
|
57
|
+
* @param input - Schema for request body payload
|
|
58
|
+
* @param output - Schema for response body payload
|
|
59
|
+
* @param errors - Optional array of error type strings
|
|
60
|
+
* @returns A new {@link Procedure} instance
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* // Create record procedure
|
|
65
|
+
* const createRecord = l.procedure(
|
|
66
|
+
* 'com.atproto.repo.createRecord',
|
|
67
|
+
* l.params({}),
|
|
68
|
+
* l.jsonPayload({
|
|
69
|
+
* repo: l.string({ format: 'at-identifier' }),
|
|
70
|
+
* collection: l.string({ format: 'nsid' }),
|
|
71
|
+
* record: l.unknown(),
|
|
72
|
+
* }),
|
|
73
|
+
* l.jsonPayload({
|
|
74
|
+
* uri: l.string({ format: 'at-uri' }),
|
|
75
|
+
* cid: l.string({ format: 'cid' }),
|
|
76
|
+
* }),
|
|
77
|
+
* ['InvalidRecord', 'RepoNotFound'],
|
|
78
|
+
* )
|
|
79
|
+
*
|
|
80
|
+
* // Procedure with binary input
|
|
81
|
+
* const uploadBlob = l.procedure(
|
|
82
|
+
* 'com.atproto.repo.uploadBlob',
|
|
83
|
+
* l.params({}),
|
|
84
|
+
* l.payload('*\/*', undefined), // Accept any content type
|
|
85
|
+
* l.jsonPayload({ blob: l.blob() }),
|
|
86
|
+
* )
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
25
89
|
/*@__NO_SIDE_EFFECTS__*/
|
|
26
90
|
export function procedure<
|
|
27
91
|
const N extends NsidString,
|
package/src/schema/query.ts
CHANGED
|
@@ -2,6 +2,28 @@ import { NsidString } from '../core.js'
|
|
|
2
2
|
import { ParamsSchema } from './params.js'
|
|
3
3
|
import { Payload } from './payload.js'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Represents a Lexicon query (HTTP GET) endpoint definition.
|
|
7
|
+
*
|
|
8
|
+
* Queries are read-only operations that retrieve data from a server.
|
|
9
|
+
* They have parameters (passed as URL query parameters), an output
|
|
10
|
+
* payload, and optional error types.
|
|
11
|
+
*
|
|
12
|
+
* @template TNsid - The NSID identifying this query
|
|
13
|
+
* @template TParameters - The parameters schema type
|
|
14
|
+
* @template TOutputPayload - The output payload type
|
|
15
|
+
* @template TErrors - Array of error type strings, or undefined
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const getPostQuery = new Query(
|
|
20
|
+
* 'app.bsky.feed.getPost',
|
|
21
|
+
* l.params({ uri: l.string({ format: 'at-uri' }) }),
|
|
22
|
+
* l.payload('application/json', postSchema),
|
|
23
|
+
* ['NotFound']
|
|
24
|
+
* )
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
5
27
|
export class Query<
|
|
6
28
|
const TNsid extends NsidString = NsidString,
|
|
7
29
|
const TParameters extends ParamsSchema = ParamsSchema,
|
|
@@ -20,6 +42,39 @@ export class Query<
|
|
|
20
42
|
) {}
|
|
21
43
|
}
|
|
22
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Creates a query definition for a Lexicon GET endpoint.
|
|
47
|
+
*
|
|
48
|
+
* Queries retrieve data without side effects. Parameters are sent as
|
|
49
|
+
* URL query string parameters.
|
|
50
|
+
*
|
|
51
|
+
* @param nsid - The NSID identifying this query endpoint
|
|
52
|
+
* @param parameters - Schema for URL query parameters
|
|
53
|
+
* @param output - Expected response payload schema
|
|
54
|
+
* @param errors - Optional array of error type strings
|
|
55
|
+
* @returns A new {@link Query} instance
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* // Simple query with JSON output
|
|
60
|
+
* const getProfile = l.query(
|
|
61
|
+
* 'app.bsky.actor.getProfile',
|
|
62
|
+
* l.params({ actor: l.string({ format: 'at-identifier' }) }),
|
|
63
|
+
* l.jsonPayload({ displayName: l.string(), handle: l.string() }),
|
|
64
|
+
* )
|
|
65
|
+
*
|
|
66
|
+
* // Query with pagination and errors
|
|
67
|
+
* const getTimeline = l.query(
|
|
68
|
+
* 'app.bsky.feed.getTimeline',
|
|
69
|
+
* l.params({
|
|
70
|
+
* limit: l.optional(l.integer({ minimum: 1, maximum: 100 })),
|
|
71
|
+
* cursor: l.optional(l.string()),
|
|
72
|
+
* }),
|
|
73
|
+
* l.jsonPayload({ feed: l.array(feedItemSchema), cursor: l.optional(l.string()) }),
|
|
74
|
+
* ['BlockedActor', 'BlockedByActor'],
|
|
75
|
+
* )
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
23
78
|
/*@__NO_SIDE_EFFECTS__*/
|
|
24
79
|
export function query<
|
|
25
80
|
const N extends NsidString,
|
package/src/schema/record.ts
CHANGED
|
@@ -14,9 +14,34 @@ import {
|
|
|
14
14
|
import { literal } from './literal.js'
|
|
15
15
|
import { string } from './string.js'
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Infers the record key type from a RecordSchema.
|
|
19
|
+
*
|
|
20
|
+
* @template R - The RecordSchema type
|
|
21
|
+
*/
|
|
17
22
|
export type InferRecordKey<R extends RecordSchema> =
|
|
18
23
|
R extends RecordSchema<infer TKey> ? RecordKeySchemaOutput<TKey> : never
|
|
19
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Schema for AT Protocol records with a type identifier and key constraints.
|
|
27
|
+
*
|
|
28
|
+
* Records are the primary data unit in AT Protocol. Each record has a `$type`
|
|
29
|
+
* field identifying its Lexicon schema, and is stored at a specific key
|
|
30
|
+
* (TID, NSID, or other format) in a repository.
|
|
31
|
+
*
|
|
32
|
+
* @template TKey - The record key type ('tid', 'nsid', 'any', or 'literal:...')
|
|
33
|
+
* @template TType - The NSID string identifying this record type
|
|
34
|
+
* @template TShape - The validator type for the record's data shape
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const postSchema = new RecordSchema(
|
|
39
|
+
* 'tid',
|
|
40
|
+
* 'app.bsky.feed.post',
|
|
41
|
+
* l.object({ text: l.string(), createdAt: l.string() })
|
|
42
|
+
* )
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
20
45
|
export class RecordSchema<
|
|
21
46
|
const TKey extends LexiconRecordKey = any,
|
|
22
47
|
const TType extends NsidString = any,
|
|
@@ -115,15 +140,45 @@ function recordKey<Key extends LexiconRecordKey>(
|
|
|
115
140
|
type AsNsid<T> = T extends `${string}#${string}` ? never : T
|
|
116
141
|
|
|
117
142
|
/**
|
|
143
|
+
* Creates a record schema for AT Protocol records.
|
|
144
|
+
*
|
|
145
|
+
* Records are the primary data unit in AT Protocol repositories. They have
|
|
146
|
+
* a `$type` field identifying their Lexicon schema, and are stored at keys
|
|
147
|
+
* following a specific format (TID, NSID, etc.).
|
|
148
|
+
*
|
|
118
149
|
* This function offers two overloads:
|
|
119
|
-
* - One that
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* -
|
|
125
|
-
*
|
|
126
|
-
*
|
|
150
|
+
* - One that infers the output type from the provided arguments (does not
|
|
151
|
+
* support circular references)
|
|
152
|
+
* - One with an explicitly defined interface for use with codegen and
|
|
153
|
+
* circular references
|
|
154
|
+
*
|
|
155
|
+
* @param key - The record key type: 'tid', 'nsid', 'any', or 'literal:value'
|
|
156
|
+
* @param type - The NSID identifying this record type (e.g., 'app.bsky.feed.post')
|
|
157
|
+
* @param validator - Schema validator for the record's properties
|
|
158
|
+
* @returns A new {@link RecordSchema} instance
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* // Post record with TID key
|
|
163
|
+
* const postSchema = l.record('tid', 'app.bsky.feed.post', l.object({
|
|
164
|
+
* text: l.string({ maxGraphemes: 300 }),
|
|
165
|
+
* createdAt: l.string({ format: 'datetime' }),
|
|
166
|
+
* reply: l.optional(l.object({
|
|
167
|
+
* root: l.ref(() => strongRefSchema),
|
|
168
|
+
* parent: l.ref(() => strongRefSchema),
|
|
169
|
+
* })),
|
|
170
|
+
* }))
|
|
171
|
+
*
|
|
172
|
+
* // Profile record with literal 'self' key
|
|
173
|
+
* const profileSchema = l.record('literal:self', 'app.bsky.actor.profile', l.object({
|
|
174
|
+
* displayName: l.optional(l.string({ maxGraphemes: 64 })),
|
|
175
|
+
* description: l.optional(l.string({ maxGraphemes: 256 })),
|
|
176
|
+
* avatar: l.optional(l.blob({ accept: ['image/*'] })),
|
|
177
|
+
* }))
|
|
178
|
+
*
|
|
179
|
+
* // Build a record with automatic $type injection
|
|
180
|
+
* const post = postSchema.build({ text: 'Hello!', createdAt: new Date().toISOString() })
|
|
181
|
+
* ```
|
|
127
182
|
*/
|
|
128
183
|
export function record<
|
|
129
184
|
const K extends LexiconRecordKey,
|
package/src/schema/ref.ts
CHANGED
|
@@ -7,8 +7,30 @@ import {
|
|
|
7
7
|
WrappedValidator,
|
|
8
8
|
} from '../core.js'
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Function type that returns a validator, used for lazy schema resolution.
|
|
12
|
+
*
|
|
13
|
+
* @template TValidator - The validator type that will be returned
|
|
14
|
+
*/
|
|
10
15
|
export type RefSchemaGetter<out TValidator extends Validator> = () => TValidator
|
|
11
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Schema for creating references to other schemas with lazy resolution.
|
|
19
|
+
*
|
|
20
|
+
* Useful for handling circular references or breaking module dependency cycles.
|
|
21
|
+
* The referenced schema is resolved lazily when first needed for validation.
|
|
22
|
+
*
|
|
23
|
+
* @template TValidator - The referenced validator type
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* // Self-referential schema for tree structure
|
|
28
|
+
* const nodeSchema = l.object({
|
|
29
|
+
* value: l.string(),
|
|
30
|
+
* children: l.array(l.ref(() => nodeSchema)),
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
12
34
|
export class RefSchema<const TValidator extends Validator>
|
|
13
35
|
extends Schema<
|
|
14
36
|
InferInput<TValidator>,
|
|
@@ -41,6 +63,34 @@ export class RefSchema<const TValidator extends Validator>
|
|
|
41
63
|
}
|
|
42
64
|
}
|
|
43
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Creates a reference schema with lazy resolution.
|
|
68
|
+
*
|
|
69
|
+
* Allows referencing schemas that may not be defined yet, enabling
|
|
70
|
+
* circular references and breaking dependency cycles. The getter function
|
|
71
|
+
* is called lazily when validation is first performed.
|
|
72
|
+
*
|
|
73
|
+
* @param get - Function that returns the referenced validator
|
|
74
|
+
* @returns A new {@link RefSchema} instance
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* // Circular reference - tree node that contains children of the same type
|
|
79
|
+
* const treeNodeSchema = l.object({
|
|
80
|
+
* name: l.string(),
|
|
81
|
+
* children: l.optional(l.array(l.ref(() => treeNodeSchema))),
|
|
82
|
+
* })
|
|
83
|
+
*
|
|
84
|
+
* // Cross-module reference
|
|
85
|
+
* const commentSchema = l.object({
|
|
86
|
+
* text: l.string(),
|
|
87
|
+
* author: l.ref(() => userSchema), // userSchema defined elsewhere
|
|
88
|
+
* })
|
|
89
|
+
*
|
|
90
|
+
* // Explicitly typed reference
|
|
91
|
+
* const itemSchema = l.ref<Item>(() => complexItemSchema)
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
44
94
|
/*@__NO_SIDE_EFFECTS__*/
|
|
45
95
|
export function ref<const TValidator extends Validator>(
|
|
46
96
|
get: RefSchemaGetter<TValidator>,
|