@atproto/lex-schema 0.0.19 → 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.
- package/CHANGELOG.md +26 -0
- package/dist/core/$type.js +2 -6
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.js +4 -8
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/result.js +6 -14
- package/dist/core/result.js.map +1 -1
- package/dist/core/schema.js +16 -20
- package/dist/core/schema.js.map +1 -1
- package/dist/core/standard-schema.js +5 -10
- package/dist/core/standard-schema.js.map +1 -1
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +37 -61
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/types.js +1 -2
- package/dist/core/validation-error.js +14 -25
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validation-issue.js +13 -41
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.js +19 -28
- package/dist/core/validator.js.map +1 -1
- package/dist/core.js +9 -12
- package/dist/core.js.map +1 -1
- package/dist/external.js +3 -6
- package/dist/external.js.map +1 -1
- package/dist/helpers.js +5 -9
- package/dist/helpers.js.map +1 -1
- package/dist/index.js +3 -7
- package/dist/index.js.map +1 -1
- package/dist/schema/array.js +5 -11
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.js +10 -17
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.js +8 -9
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.js +7 -12
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.js +7 -12
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.js +5 -13
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.js +6 -13
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.js +10 -18
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.js +6 -11
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.js +5 -10
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.js +4 -11
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/lex-map.js +13 -14
- package/dist/schema/lex-map.js.map +1 -1
- package/dist/schema/lex-value.js +11 -12
- package/dist/schema/lex-value.js.map +1 -1
- package/dist/schema/literal.js +4 -10
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.js +8 -9
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.js +9 -10
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.js +5 -10
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.js +8 -14
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.js +5 -10
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.js +39 -44
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.js +5 -13
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.js +2 -10
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.js +2 -9
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.js +3 -13
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.js +3 -12
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.js +15 -24
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.js +4 -9
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.js +3 -6
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.js +4 -11
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.js +15 -26
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.js +3 -12
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.js +5 -11
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.js +11 -18
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.js +4 -9
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.js +8 -15
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.js +5 -11
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown.js +8 -9
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.js +4 -11
- package/dist/schema/with-default.js.map +1 -1
- package/dist/schema.js +38 -41
- package/dist/schema.js.map +1 -1
- package/dist/util/array-agg.js +1 -4
- package/dist/util/array-agg.js.map +1 -1
- package/dist/util/assertion-util.js +1 -2
- package/dist/util/if-any.js +1 -2
- package/dist/util/lazy-property.js +1 -4
- package/dist/util/lazy-property.js.map +1 -1
- package/dist/util/memoize.js +2 -6
- package/dist/util/memoize.js.map +1 -1
- package/package.json +7 -8
- package/src/core/string-format.ts +2 -1
- package/src/core/validation-issue.ts +1 -1
- package/src/helpers.test.ts +52 -52
- package/src/schema/record.test.ts +2 -2
- package/src/schema/ref.test.ts +1 -1
- package/src/schema/string.test.ts +6 -6
- package/src/schema/subscription.test.ts +4 -4
- package/src/schema/typed-object.test.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optional.js","sourceRoot":"","sources":["../../src/schema/optional.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"optional.js","sourceRoot":"","sources":["../../src/schema/optional.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,MAAM,GAIP,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,cAA6C,SAAQ,MAKjE;IAGC,YAAqB,SAAqB;QACxC,KAAK,EAAE,CAAA;QADY,cAAS,GAAT,SAAS,CAAY;QAFjC,SAAI,GAAG,UAAmB,CAAA;IAInC,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,0EAA0E;QAC1E,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3D,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC3B,CAAC;QAED,0EAA0E;QAC1E,8BAA8B;QAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QAElD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,MAAM,CAAA;QACf,CAAC;QAED,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC3B,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,aAAa,CAAC,mBAAmB,CAAC,UAExD,SAAqB;IACrB,OAAO,IAAI,cAAc,CAAa,SAAS,CAAC,CAAA;AAClD,CAAC,CAAC,CAAA","sourcesContent":["import {\n InferInput,\n InferOutput,\n Schema,\n UnwrapValidator,\n ValidationContext,\n Validator,\n} from '../core.js'\nimport { memoizedTransformer } from '../util/memoize.js'\nimport { WithDefaultSchema } from './with-default.js'\n\n/**\n * Schema wrapper that makes a value optional (allows undefined).\n *\n * When the input is `undefined`, validation succeeds without running the\n * inner validator. If the inner validator has a default value (via `withDefault`),\n * that default will be applied in parse mode.\n *\n * @template TValidator - The wrapped validator type\n *\n * @example\n * ```ts\n * const schema = new OptionalSchema(l.string())\n * schema.validate(undefined) // success\n * schema.validate('hello') // success\n * ```\n */\nexport class OptionalSchema<TValidator extends Validator> extends Schema<\n InferInput<TValidator> | undefined,\n UnwrapValidator<TValidator> extends WithDefaultSchema<infer TValidator>\n ? InferOutput<TValidator>\n : InferOutput<TValidator> | undefined\n> {\n readonly type = 'optional' as const\n\n constructor(readonly validator: TValidator) {\n super()\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n // Optimization: No need to apply child schema defaults in validation mode\n if (input === undefined && ctx.options.mode === 'validate') {\n return ctx.success(input)\n }\n\n // @NOTE The inner schema might apply a default value so we need to run it\n // even if input is undefined.\n const result = ctx.validate(input, this.validator)\n\n if (result.success) {\n return result\n }\n\n if (input === undefined) {\n return ctx.success(input)\n }\n\n return result\n }\n}\n\n/**\n * Creates an optional schema that allows undefined values.\n *\n * Wraps another schema to make it optional. When used in an object schema,\n * properties with optional schemas are not required.\n *\n * @param validator - The validator to make optional\n * @returns A new {@link OptionalSchema} instance\n *\n * @example\n * ```ts\n * // Optional string\n * const optionalBio = l.optional(l.string())\n *\n * // In an object - property is not required\n * const userSchema = l.object({\n * name: l.string(),\n * bio: l.optional(l.string()),\n * })\n * userSchema.parse({ name: 'Alice' }) // Valid, bio is undefined\n *\n * // With default value\n * const countSchema = l.optional(l.withDefault(l.integer(), 0))\n * countSchema.parse(undefined) // Returns 0\n * ```\n */\nexport const optional = /*#__PURE__*/ memoizedTransformer(function <\n const TValidator extends Validator,\n>(validator: TValidator) {\n return new OptionalSchema<TValidator>(validator)\n})\n"]}
|
package/dist/schema/params.js
CHANGED
|
@@ -1,34 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const union_js_1 = require("./union.js");
|
|
17
|
-
const with_default_js_1 = require("./with-default.js");
|
|
18
|
-
const paramScalarSchema = (0, union_js_1.union)([(0, boolean_js_1.boolean)(), (0, integer_js_1.integer)(), (0, string_js_1.string)()]);
|
|
1
|
+
import { isPlainObject } from '@atproto/lex-data';
|
|
2
|
+
import { IssueInvalidType, IssueInvalidValue, LexValidationError, Schema, } from '../core.js';
|
|
3
|
+
import { lazyProperty } from '../util/lazy-property.js';
|
|
4
|
+
import { memoizedOptions } from '../util/memoize.js';
|
|
5
|
+
import { ArraySchema, array } from './array.js';
|
|
6
|
+
import { BooleanSchema, boolean } from './boolean.js';
|
|
7
|
+
import { dict } from './dict.js';
|
|
8
|
+
import { EnumSchema } from './enum.js';
|
|
9
|
+
import { IntegerSchema, integer } from './integer.js';
|
|
10
|
+
import { LiteralSchema } from './literal.js';
|
|
11
|
+
import { OptionalSchema, optional } from './optional.js';
|
|
12
|
+
import { StringSchema, string } from './string.js';
|
|
13
|
+
import { union } from './union.js';
|
|
14
|
+
import { WithDefaultSchema } from './with-default.js';
|
|
15
|
+
const paramScalarSchema = union([boolean(), integer(), string()]);
|
|
19
16
|
/**
|
|
20
17
|
* Schema for validating individual parameter values.
|
|
21
18
|
*/
|
|
22
|
-
|
|
19
|
+
export const paramSchema = union([
|
|
23
20
|
paramScalarSchema,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
array(boolean()),
|
|
22
|
+
array(integer()),
|
|
23
|
+
array(string()),
|
|
27
24
|
]);
|
|
28
25
|
/**
|
|
29
26
|
* Schema for validating arbitrary params objects.
|
|
30
27
|
*/
|
|
31
|
-
|
|
28
|
+
export const paramsSchema = dict(string(), optional(paramSchema));
|
|
32
29
|
/**
|
|
33
30
|
* Schema for validating URL query parameters in Lexicon endpoints.
|
|
34
31
|
*
|
|
@@ -48,19 +45,18 @@ exports.paramsSchema = (0, dict_js_1.dict)((0, string_js_1.string)(), (0, option
|
|
|
48
45
|
* })
|
|
49
46
|
* ```
|
|
50
47
|
*/
|
|
51
|
-
class ParamsSchema extends
|
|
52
|
-
shape;
|
|
53
|
-
type = 'params';
|
|
48
|
+
export class ParamsSchema extends Schema {
|
|
54
49
|
constructor(shape) {
|
|
55
50
|
super();
|
|
56
51
|
this.shape = shape;
|
|
52
|
+
this.type = 'params';
|
|
57
53
|
}
|
|
58
54
|
get shapeValidators() {
|
|
59
55
|
const map = new Map(Object.entries(this.shape));
|
|
60
|
-
return
|
|
56
|
+
return lazyProperty(this, 'shapeValidators', map);
|
|
61
57
|
}
|
|
62
58
|
validateInContext(input, ctx) {
|
|
63
|
-
if (!
|
|
59
|
+
if (!isPlainObject(input)) {
|
|
64
60
|
return ctx.issueUnexpectedType(input, 'object');
|
|
65
61
|
}
|
|
66
62
|
// Lazily copy value
|
|
@@ -69,7 +65,7 @@ class ParamsSchema extends core_js_1.Schema {
|
|
|
69
65
|
for (const key in input) {
|
|
70
66
|
if (this.shapeValidators.has(key))
|
|
71
67
|
continue;
|
|
72
|
-
const result = ctx.validateChild(input, key,
|
|
68
|
+
const result = ctx.validateChild(input, key, paramSchema);
|
|
73
69
|
if (!result.success)
|
|
74
70
|
return result;
|
|
75
71
|
if (result.value !== input[key]) {
|
|
@@ -116,7 +112,7 @@ class ParamsSchema extends core_js_1.Schema {
|
|
|
116
112
|
continue;
|
|
117
113
|
const validator = this.shapeValidators.get(name);
|
|
118
114
|
const innerValidator = validator ? unwrapSchema(validator) : undefined;
|
|
119
|
-
const expectsArray = innerValidator instanceof
|
|
115
|
+
const expectsArray = innerValidator instanceof ArraySchema;
|
|
120
116
|
const scalarValidator = expectsArray
|
|
121
117
|
? unwrapSchema(innerValidator.validator)
|
|
122
118
|
: innerValidator;
|
|
@@ -152,7 +148,6 @@ class ParamsSchema extends core_js_1.Schema {
|
|
|
152
148
|
return urlSearchParams;
|
|
153
149
|
}
|
|
154
150
|
}
|
|
155
|
-
exports.ParamsSchema = ParamsSchema;
|
|
156
151
|
function coerceParam(name, param, schema, options) {
|
|
157
152
|
let issue;
|
|
158
153
|
if (!schema) {
|
|
@@ -160,34 +155,34 @@ function coerceParam(name, param, schema, options) {
|
|
|
160
155
|
// coercion and just return the string value.
|
|
161
156
|
return param;
|
|
162
157
|
}
|
|
163
|
-
else if (schema instanceof
|
|
158
|
+
else if (schema instanceof StringSchema) {
|
|
164
159
|
return param;
|
|
165
160
|
}
|
|
166
|
-
else if (schema instanceof
|
|
161
|
+
else if (schema instanceof IntegerSchema) {
|
|
167
162
|
if (/^-?\d+$/.test(param))
|
|
168
163
|
return Number(param);
|
|
169
|
-
issue = new
|
|
164
|
+
issue = new IssueInvalidType(paramPath(name, options), param, ['integer']);
|
|
170
165
|
}
|
|
171
|
-
else if (schema instanceof
|
|
166
|
+
else if (schema instanceof BooleanSchema) {
|
|
172
167
|
if (param === 'true')
|
|
173
168
|
return true;
|
|
174
169
|
if (param === 'false')
|
|
175
170
|
return false;
|
|
176
|
-
issue = new
|
|
171
|
+
issue = new IssueInvalidType(paramPath(name, options), param, ['boolean']);
|
|
177
172
|
}
|
|
178
|
-
else if (schema instanceof
|
|
173
|
+
else if (schema instanceof LiteralSchema) {
|
|
179
174
|
const { value } = schema;
|
|
180
175
|
if (String(value) === param)
|
|
181
176
|
return value;
|
|
182
|
-
issue = new
|
|
177
|
+
issue = new IssueInvalidValue(paramPath(name, options), param, [value]);
|
|
183
178
|
}
|
|
184
|
-
else if (schema instanceof
|
|
179
|
+
else if (schema instanceof EnumSchema) {
|
|
185
180
|
const { values } = schema;
|
|
186
181
|
for (const value of values) {
|
|
187
182
|
if (String(value) === param)
|
|
188
183
|
return value;
|
|
189
184
|
}
|
|
190
|
-
issue = new
|
|
185
|
+
issue = new IssueInvalidValue(paramPath(name, options), param, values);
|
|
191
186
|
}
|
|
192
187
|
else {
|
|
193
188
|
// This should never happen. If it *does*, it means that the user of
|
|
@@ -207,7 +202,7 @@ function coerceParam(name, param, schema, options) {
|
|
|
207
202
|
// the index of the param in case of array params (e.g. "tags[1]"), which
|
|
208
203
|
// could be helpful for debugging. The cost overhead is not worth it though
|
|
209
204
|
// (IMO).
|
|
210
|
-
throw new
|
|
205
|
+
throw new LexValidationError([issue]);
|
|
211
206
|
}
|
|
212
207
|
function paramPath(key, options) {
|
|
213
208
|
return options?.path ? [...options.path, key] : [key];
|
|
@@ -247,12 +242,12 @@ function paramPath(key, options) {
|
|
|
247
242
|
* const searchParams = paginationParams.toURLSearchParams({ limit: 25 })
|
|
248
243
|
* ```
|
|
249
244
|
*/
|
|
250
|
-
|
|
245
|
+
export const params = /*#__PURE__*/ memoizedOptions(function params(properties = {}) {
|
|
251
246
|
return new ParamsSchema(properties);
|
|
252
247
|
});
|
|
253
248
|
function unwrapSchema(schema) {
|
|
254
|
-
while (schema instanceof
|
|
255
|
-
schema instanceof
|
|
249
|
+
while (schema instanceof OptionalSchema ||
|
|
250
|
+
schema instanceof WithDefaultSchema) {
|
|
256
251
|
return unwrapSchema(schema.validator);
|
|
257
252
|
}
|
|
258
253
|
return schema;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/schema/params.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPlainObject } from '@atproto/lex-data'\nimport {\n Infer,\n InferInput,\n InferOutput,\n Issue,\n IssueInvalidType,\n IssueInvalidValue,\n LexValidationError,\n ParseOptions,\n Schema,\n ValidationContext,\n Validator,\n WithOptionalProperties,\n} from '../core.js'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { memoizedOptions } from '../util/memoize.js'\nimport { ArraySchema, array } from './array.js'\nimport { BooleanSchema, boolean } from './boolean.js'\nimport { dict } from './dict.js'\nimport { EnumSchema } from './enum.js'\nimport { IntegerSchema, integer } from './integer.js'\nimport { LiteralSchema } from './literal.js'\nimport { OptionalSchema, optional } from './optional.js'\nimport { StringSchema, string } from './string.js'\nimport { union } from './union.js'\nimport { WithDefaultSchema } from './with-default.js'\n\n/**\n * Scalar types allowed in URL parameters: boolean, integer, or string.\n */\nexport type ParamScalar = Infer<typeof paramScalarSchema>\nconst paramScalarSchema = union([boolean(), integer(), string()])\n\n/**\n * A single parameter value: scalar or array of scalars.\n */\nexport type Param = Infer<typeof paramSchema>\n\n/**\n * Schema for validating individual parameter values.\n */\nexport const paramSchema = union([\n paramScalarSchema,\n array(boolean()),\n array(integer()),\n array(string()),\n])\n\n/**\n * Type for a params object with string keys and optional param values.\n */\nexport type Params = Infer<typeof paramsSchema>\n\n/**\n * Schema for validating arbitrary params objects.\n */\nexport const paramsSchema = dict(string(), optional(paramSchema))\n\nexport type ParamScalarValidator =\n // @NOTE In order to properly coerce URLSearchParams, we need to distinguish\n // between scalar and array validators, requiring to be able to detect which\n // schema types are being used, restricting the allowed param validators here.\n | LiteralSchema<string>\n | LiteralSchema<number>\n | LiteralSchema<boolean>\n | EnumSchema<string>\n | EnumSchema<number>\n // | EnumSchema<boolean> // Boolean lexicon definitions don't allow \"enum\"\n | StringSchema<any>\n | BooleanSchema\n | IntegerSchema\n\ntype AsArrayParamSchema<TSchema extends Validator> =\n // This allows to \"distribute\" any union of scalar validators into a union of\n // arrays of those validators, instead of an array of union. If TSchema is\n // BooleanSchema | IntegerSchema, we want the result to be\n // ArraySchema<BooleanSchema> | ArraySchema<IntegerSchema>, not\n // ArraySchema<BooleanSchema | IntegerSchema>, since the latter would allow\n // arrays with mixed types (e.g. [true, 42]), which we don't want.\n TSchema extends any ? ArraySchema<TSchema> : never\n\nexport type ParamValueValidator =\n | ParamScalarValidator\n | AsArrayParamSchema<ParamScalarValidator>\n\nexport type ParamValidator =\n | ParamValueValidator\n | OptionalSchema<ParamValueValidator>\n | OptionalSchema<WithDefaultSchema<ParamValueValidator>>\n | WithDefaultSchema<ParamValueValidator>\n\n/**\n * Type representing the shape of a params schema definition.\n *\n * Maps parameter names to their validators (must be Param or undefined).\n */\nexport type ParamsShape = {\n [x: string]: ParamValidator\n}\n\n/**\n * Schema for validating URL query parameters in Lexicon endpoints.\n *\n * Params are the query string parameters passed to queries, procedures,\n * and subscriptions. Values must be scalars (boolean, integer, string)\n * or arrays of scalars, as they need to be serializable to URL format.\n *\n * Provides methods for converting to/from URLSearchParams.\n *\n * @template TShape - The params shape type mapping names to validators\n *\n * @example\n * ```ts\n * const schema = new ParamsSchema({\n * limit: l.optional(l.integer({ minimum: 1, maximum: 100 })),\n * cursor: l.optional(l.string()),\n * })\n * ```\n */\nexport class ParamsSchema<\n const TShape extends ParamsShape = ParamsShape,\n> extends Schema<\n WithOptionalProperties<{\n [K in keyof TShape]: InferInput<TShape[K]>\n }>,\n WithOptionalProperties<{\n [K in keyof TShape]: InferOutput<TShape[K]>\n }>\n> {\n readonly type = 'params' as const\n\n constructor(readonly shape: TShape) {\n super()\n }\n\n get shapeValidators(): Map<string, ParamValidator> {\n const map = new Map(Object.entries(this.shape))\n\n return lazyProperty(this, 'shapeValidators', map)\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (!isPlainObject(input)) {\n return ctx.issueUnexpectedType(input, 'object')\n }\n\n // Lazily copy value\n let copy: undefined | Record<string, unknown>\n\n // Ensure that non-specified params conform to param schema\n for (const key in input) {\n if (this.shapeValidators.has(key)) continue\n\n const result = ctx.validateChild(input, key, paramSchema)\n if (!result.success) return result\n\n if (result.value !== input[key]) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n for (const [key, propDef] of this.shapeValidators) {\n const result = ctx.validateChild(input, key, propDef)\n if (!result.success) {\n if (!(key in input)) {\n // Transform into \"required key\" issue\n return ctx.issueRequiredKey(input, key)\n }\n\n return result\n }\n\n // Skip copying if key is not present in input (and value is undefined)\n if (result.value === undefined && !(key in input)) {\n continue\n }\n\n if (!Object.is(result.value, input[key])) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n // Copy on write\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n return ctx.success(copy ?? input)\n }\n\n fromURLSearchParams(\n input: string | Iterable<[string, string]>,\n options?: ParseOptions,\n ): InferOutput<this> {\n const params: Record<string, unknown> = {}\n\n const iterable =\n typeof input === 'string' ? new URLSearchParams(input) : input\n const entries =\n iterable instanceof URLSearchParams ? iterable.entries() : iterable\n\n for (const [name, value] of entries) {\n // Ignore empty strings\n if (!value) continue\n\n const validator = this.shapeValidators.get(name)\n const innerValidator = validator ? unwrapSchema(validator) : undefined\n const expectsArray = innerValidator instanceof ArraySchema\n const scalarValidator = expectsArray\n ? unwrapSchema(innerValidator.validator)\n : innerValidator\n\n const coerced = coerceParam(name, value, scalarValidator, options)\n\n const currentParam = params[name]\n if (currentParam === undefined) {\n params[name] = expectsArray ? [coerced] : coerced\n } else if (Array.isArray(currentParam)) {\n currentParam.push(coerced)\n } else {\n params[name] = [currentParam, coerced]\n }\n }\n\n return this.parse(params, options)\n }\n\n toURLSearchParams(input: InferInput<this>): URLSearchParams {\n const urlSearchParams = new URLSearchParams()\n\n // @NOTE We apply defaults here to ensure that server with different\n // defaults still receive all expected parameters.\n const params = this.parse(input)\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n urlSearchParams.append(key, String(v))\n }\n } else if (value !== undefined) {\n urlSearchParams.append(key, String(value))\n }\n }\n\n return urlSearchParams\n }\n}\n\nfunction coerceParam(\n name: string,\n param: string,\n schema?: ParamScalarValidator,\n options?: ParseOptions,\n): ParamScalar {\n let issue: Issue\n\n if (!schema) {\n // The param is unknown (not defined in schema), so we don't apply any\n // coercion and just return the string value.\n return param\n } else if (schema instanceof StringSchema) {\n return param\n } else if (schema instanceof IntegerSchema) {\n if (/^-?\\d+$/.test(param)) return Number(param)\n issue = new IssueInvalidType(paramPath(name, options), param, ['integer'])\n } else if (schema instanceof BooleanSchema) {\n if (param === 'true') return true\n if (param === 'false') return false\n issue = new IssueInvalidType(paramPath(name, options), param, ['boolean'])\n } else if (schema instanceof LiteralSchema) {\n const { value } = schema\n if (String(value) === param) return value\n issue = new IssueInvalidValue(paramPath(name, options), param, [value])\n } else if (schema instanceof EnumSchema) {\n const { values } = schema\n for (const value of values) {\n if (String(value) === param) return value\n }\n issue = new IssueInvalidValue(paramPath(name, options), param, values)\n } else {\n // This should never happen. If it *does*, it means that the user of\n // lex-schema is mixing different versions of the lib, which is not\n // supported. Throwing an error here is better than silently accepting\n // invalid params and causing unexpected behavior down the line (ie. error\n // message returning the string value instead of the expected\n // boolean/number/string value).\n throw new Error(`Unsupported schema type for param coercion: ${schema}`)\n }\n\n // We were not able to coerce the param to the expected type. There is no\n // point in returning the original string value since it doesn't conform to\n // the expected schema, so we throw a validation error instead. We could\n // return the \"param\" here, which would cause the validation to fail later on\n // (see fromURLSearchParams()'s return statement). The main benefit of\n // returning the original \"param\" value is that the error path would include\n // the index of the param in case of array params (e.g. \"tags[1]\"), which\n // could be helpful for debugging. The cost overhead is not worth it though\n // (IMO).\n throw new LexValidationError([issue])\n}\n\nfunction paramPath(key: string, options?: ParseOptions) {\n return options?.path ? [...options.path, key] : [key]\n}\n\n/**\n * Creates a params schema for URL query parameters.\n *\n * Params schemas validate query string parameters for Lexicon endpoints.\n * Values must be boolean, integer, string, or arrays of those types.\n *\n * @param properties - Object mapping parameter names to their validators\n * @returns A new {@link ParamsSchema} instance\n *\n * @example\n * ```ts\n * // Simple pagination params\n * const paginationParams = l.params({\n * limit: l.optional(l.withDefault(l.integer({ minimum: 1, maximum: 100 }), 50)),\n * cursor: l.optional(l.string()),\n * })\n *\n * // Required parameter\n * const actorParams = l.params({\n * actor: l.string({ format: 'at-identifier' }),\n * })\n *\n * // Array parameter (multiple values)\n * const filterParams = l.params({\n * tags: l.optional(l.array(l.string())),\n * })\n *\n * // Convert from URL\n * const urlParams = new URLSearchParams('limit=25&cursor=abc')\n * const validated = paginationParams.fromURLSearchParams(urlParams)\n *\n * // Convert to URL\n * const searchParams = paginationParams.toURLSearchParams({ limit: 25 })\n * ```\n */\nexport const params = /*#__PURE__*/ memoizedOptions(function params<\n const TShape extends ParamsShape = NonNullable<unknown>,\n>(properties: TShape = {} as TShape) {\n return new ParamsSchema<TShape>(properties)\n})\n\ntype UnwrapSchema<S extends Validator> =\n S extends OptionalSchema<infer U>\n ? UnwrapSchema<U>\n : S extends WithDefaultSchema<infer U>\n ? UnwrapSchema<U>\n : S\n\nfunction unwrapSchema<S extends Validator>(schema: S): UnwrapSchema<S> {\n while (\n schema instanceof OptionalSchema ||\n schema instanceof WithDefaultSchema\n ) {\n return unwrapSchema(schema.validator)\n }\n return schema as UnwrapSchema<S>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/schema/params.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPlainObject } from '@atproto/lex-data'\nimport {\n Infer,\n InferInput,\n InferOutput,\n Issue,\n IssueInvalidType,\n IssueInvalidValue,\n LexValidationError,\n ParseOptions,\n Schema,\n ValidationContext,\n Validator,\n WithOptionalProperties,\n} from '../core.js'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { memoizedOptions } from '../util/memoize.js'\nimport { ArraySchema, array } from './array.js'\nimport { BooleanSchema, boolean } from './boolean.js'\nimport { dict } from './dict.js'\nimport { EnumSchema } from './enum.js'\nimport { IntegerSchema, integer } from './integer.js'\nimport { LiteralSchema } from './literal.js'\nimport { OptionalSchema, optional } from './optional.js'\nimport { StringSchema, string } from './string.js'\nimport { union } from './union.js'\nimport { WithDefaultSchema } from './with-default.js'\n\n/**\n * Scalar types allowed in URL parameters: boolean, integer, or string.\n */\nexport type ParamScalar = Infer<typeof paramScalarSchema>\nconst paramScalarSchema = union([boolean(), integer(), string()])\n\n/**\n * A single parameter value: scalar or array of scalars.\n */\nexport type Param = Infer<typeof paramSchema>\n\n/**\n * Schema for validating individual parameter values.\n */\nexport const paramSchema = union([\n paramScalarSchema,\n array(boolean()),\n array(integer()),\n array(string()),\n])\n\n/**\n * Type for a params object with string keys and optional param values.\n */\nexport type Params = Infer<typeof paramsSchema>\n\n/**\n * Schema for validating arbitrary params objects.\n */\nexport const paramsSchema = dict(string(), optional(paramSchema))\n\nexport type ParamScalarValidator =\n // @NOTE In order to properly coerce URLSearchParams, we need to distinguish\n // between scalar and array validators, requiring to be able to detect which\n // schema types are being used, restricting the allowed param validators here.\n | LiteralSchema<string>\n | LiteralSchema<number>\n | LiteralSchema<boolean>\n | EnumSchema<string>\n | EnumSchema<number>\n // | EnumSchema<boolean> // Boolean lexicon definitions don't allow \"enum\"\n | StringSchema<any>\n | BooleanSchema\n | IntegerSchema\n\ntype AsArrayParamSchema<TSchema extends Validator> =\n // This allows to \"distribute\" any union of scalar validators into a union of\n // arrays of those validators, instead of an array of union. If TSchema is\n // BooleanSchema | IntegerSchema, we want the result to be\n // ArraySchema<BooleanSchema> | ArraySchema<IntegerSchema>, not\n // ArraySchema<BooleanSchema | IntegerSchema>, since the latter would allow\n // arrays with mixed types (e.g. [true, 42]), which we don't want.\n TSchema extends any ? ArraySchema<TSchema> : never\n\nexport type ParamValueValidator =\n | ParamScalarValidator\n | AsArrayParamSchema<ParamScalarValidator>\n\nexport type ParamValidator =\n | ParamValueValidator\n | OptionalSchema<ParamValueValidator>\n | OptionalSchema<WithDefaultSchema<ParamValueValidator>>\n | WithDefaultSchema<ParamValueValidator>\n\n/**\n * Type representing the shape of a params schema definition.\n *\n * Maps parameter names to their validators (must be Param or undefined).\n */\nexport type ParamsShape = {\n [x: string]: ParamValidator\n}\n\n/**\n * Schema for validating URL query parameters in Lexicon endpoints.\n *\n * Params are the query string parameters passed to queries, procedures,\n * and subscriptions. Values must be scalars (boolean, integer, string)\n * or arrays of scalars, as they need to be serializable to URL format.\n *\n * Provides methods for converting to/from URLSearchParams.\n *\n * @template TShape - The params shape type mapping names to validators\n *\n * @example\n * ```ts\n * const schema = new ParamsSchema({\n * limit: l.optional(l.integer({ minimum: 1, maximum: 100 })),\n * cursor: l.optional(l.string()),\n * })\n * ```\n */\nexport class ParamsSchema<\n const TShape extends ParamsShape = ParamsShape,\n> extends Schema<\n WithOptionalProperties<{\n [K in keyof TShape]: InferInput<TShape[K]>\n }>,\n WithOptionalProperties<{\n [K in keyof TShape]: InferOutput<TShape[K]>\n }>\n> {\n readonly type = 'params' as const\n\n constructor(readonly shape: TShape) {\n super()\n }\n\n get shapeValidators(): Map<string, ParamValidator> {\n const map = new Map(Object.entries(this.shape))\n\n return lazyProperty(this, 'shapeValidators', map)\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (!isPlainObject(input)) {\n return ctx.issueUnexpectedType(input, 'object')\n }\n\n // Lazily copy value\n let copy: undefined | Record<string, unknown>\n\n // Ensure that non-specified params conform to param schema\n for (const key in input) {\n if (this.shapeValidators.has(key)) continue\n\n const result = ctx.validateChild(input, key, paramSchema)\n if (!result.success) return result\n\n if (result.value !== input[key]) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n for (const [key, propDef] of this.shapeValidators) {\n const result = ctx.validateChild(input, key, propDef)\n if (!result.success) {\n if (!(key in input)) {\n // Transform into \"required key\" issue\n return ctx.issueRequiredKey(input, key)\n }\n\n return result\n }\n\n // Skip copying if key is not present in input (and value is undefined)\n if (result.value === undefined && !(key in input)) {\n continue\n }\n\n if (!Object.is(result.value, input[key])) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n // Copy on write\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n return ctx.success(copy ?? input)\n }\n\n fromURLSearchParams(\n input: string | Iterable<[string, string]>,\n options?: ParseOptions,\n ): InferOutput<this> {\n const params: Record<string, unknown> = {}\n\n const iterable =\n typeof input === 'string' ? new URLSearchParams(input) : input\n const entries =\n iterable instanceof URLSearchParams ? iterable.entries() : iterable\n\n for (const [name, value] of entries) {\n // Ignore empty strings\n if (!value) continue\n\n const validator = this.shapeValidators.get(name)\n const innerValidator = validator ? unwrapSchema(validator) : undefined\n const expectsArray = innerValidator instanceof ArraySchema\n const scalarValidator = expectsArray\n ? unwrapSchema(innerValidator.validator)\n : innerValidator\n\n const coerced = coerceParam(name, value, scalarValidator, options)\n\n const currentParam = params[name]\n if (currentParam === undefined) {\n params[name] = expectsArray ? [coerced] : coerced\n } else if (Array.isArray(currentParam)) {\n currentParam.push(coerced)\n } else {\n params[name] = [currentParam, coerced]\n }\n }\n\n return this.parse(params, options)\n }\n\n toURLSearchParams(input: InferInput<this>): URLSearchParams {\n const urlSearchParams = new URLSearchParams()\n\n // @NOTE We apply defaults here to ensure that server with different\n // defaults still receive all expected parameters.\n const params = this.parse(input)\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n urlSearchParams.append(key, String(v))\n }\n } else if (value !== undefined) {\n urlSearchParams.append(key, String(value))\n }\n }\n\n return urlSearchParams\n }\n}\n\nfunction coerceParam(\n name: string,\n param: string,\n schema?: ParamScalarValidator,\n options?: ParseOptions,\n): ParamScalar {\n let issue: Issue\n\n if (!schema) {\n // The param is unknown (not defined in schema), so we don't apply any\n // coercion and just return the string value.\n return param\n } else if (schema instanceof StringSchema) {\n return param\n } else if (schema instanceof IntegerSchema) {\n if (/^-?\\d+$/.test(param)) return Number(param)\n issue = new IssueInvalidType(paramPath(name, options), param, ['integer'])\n } else if (schema instanceof BooleanSchema) {\n if (param === 'true') return true\n if (param === 'false') return false\n issue = new IssueInvalidType(paramPath(name, options), param, ['boolean'])\n } else if (schema instanceof LiteralSchema) {\n const { value } = schema\n if (String(value) === param) return value\n issue = new IssueInvalidValue(paramPath(name, options), param, [value])\n } else if (schema instanceof EnumSchema) {\n const { values } = schema\n for (const value of values) {\n if (String(value) === param) return value\n }\n issue = new IssueInvalidValue(paramPath(name, options), param, values)\n } else {\n // This should never happen. If it *does*, it means that the user of\n // lex-schema is mixing different versions of the lib, which is not\n // supported. Throwing an error here is better than silently accepting\n // invalid params and causing unexpected behavior down the line (ie. error\n // message returning the string value instead of the expected\n // boolean/number/string value).\n throw new Error(`Unsupported schema type for param coercion: ${schema}`)\n }\n\n // We were not able to coerce the param to the expected type. There is no\n // point in returning the original string value since it doesn't conform to\n // the expected schema, so we throw a validation error instead. We could\n // return the \"param\" here, which would cause the validation to fail later on\n // (see fromURLSearchParams()'s return statement). The main benefit of\n // returning the original \"param\" value is that the error path would include\n // the index of the param in case of array params (e.g. \"tags[1]\"), which\n // could be helpful for debugging. The cost overhead is not worth it though\n // (IMO).\n throw new LexValidationError([issue])\n}\n\nfunction paramPath(key: string, options?: ParseOptions) {\n return options?.path ? [...options.path, key] : [key]\n}\n\n/**\n * Creates a params schema for URL query parameters.\n *\n * Params schemas validate query string parameters for Lexicon endpoints.\n * Values must be boolean, integer, string, or arrays of those types.\n *\n * @param properties - Object mapping parameter names to their validators\n * @returns A new {@link ParamsSchema} instance\n *\n * @example\n * ```ts\n * // Simple pagination params\n * const paginationParams = l.params({\n * limit: l.optional(l.withDefault(l.integer({ minimum: 1, maximum: 100 }), 50)),\n * cursor: l.optional(l.string()),\n * })\n *\n * // Required parameter\n * const actorParams = l.params({\n * actor: l.string({ format: 'at-identifier' }),\n * })\n *\n * // Array parameter (multiple values)\n * const filterParams = l.params({\n * tags: l.optional(l.array(l.string())),\n * })\n *\n * // Convert from URL\n * const urlParams = new URLSearchParams('limit=25&cursor=abc')\n * const validated = paginationParams.fromURLSearchParams(urlParams)\n *\n * // Convert to URL\n * const searchParams = paginationParams.toURLSearchParams({ limit: 25 })\n * ```\n */\nexport const params = /*#__PURE__*/ memoizedOptions(function params<\n const TShape extends ParamsShape = NonNullable<unknown>,\n>(properties: TShape = {} as TShape) {\n return new ParamsSchema<TShape>(properties)\n})\n\ntype UnwrapSchema<S extends Validator> =\n S extends OptionalSchema<infer U>\n ? UnwrapSchema<U>\n : S extends WithDefaultSchema<infer U>\n ? UnwrapSchema<U>\n : S\n\nfunction unwrapSchema<S extends Validator>(schema: S): UnwrapSchema<S> {\n while (\n schema instanceof OptionalSchema ||\n schema instanceof WithDefaultSchema\n ) {\n return unwrapSchema(schema.validator)\n }\n return schema as UnwrapSchema<S>\n}\n"]}
|
package/dist/schema/payload.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Payload = void 0;
|
|
4
|
-
exports.payload = payload;
|
|
5
|
-
exports.jsonPayload = jsonPayload;
|
|
6
|
-
const object_js_1 = require("./object.js");
|
|
1
|
+
import { object } from './object.js';
|
|
7
2
|
/**
|
|
8
3
|
* Represents a payload definition for Lexicon endpoints.
|
|
9
4
|
*
|
|
@@ -21,9 +16,7 @@ const object_js_1 = require("./object.js");
|
|
|
21
16
|
* const noPayload = new Payload(undefined, undefined)
|
|
22
17
|
* ```
|
|
23
18
|
*/
|
|
24
|
-
class Payload {
|
|
25
|
-
encoding;
|
|
26
|
-
schema;
|
|
19
|
+
export class Payload {
|
|
27
20
|
constructor(encoding, schema) {
|
|
28
21
|
this.encoding = encoding;
|
|
29
22
|
this.schema = schema;
|
|
@@ -59,7 +52,6 @@ class Payload {
|
|
|
59
52
|
return encoding === mime;
|
|
60
53
|
}
|
|
61
54
|
}
|
|
62
|
-
exports.Payload = Payload;
|
|
63
55
|
/**
|
|
64
56
|
* Creates a payload definition for Lexicon endpoint bodies.
|
|
65
57
|
*
|
|
@@ -89,7 +81,7 @@ exports.Payload = Payload;
|
|
|
89
81
|
* ```
|
|
90
82
|
*/
|
|
91
83
|
/*@__NO_SIDE_EFFECTS__*/
|
|
92
|
-
function payload(encoding = undefined, validator = undefined) {
|
|
84
|
+
export function payload(encoding = undefined, validator = undefined) {
|
|
93
85
|
return new Payload(encoding, validator);
|
|
94
86
|
}
|
|
95
87
|
/**
|
|
@@ -118,7 +110,7 @@ function payload(encoding = undefined, validator = undefined) {
|
|
|
118
110
|
* ```
|
|
119
111
|
*/
|
|
120
112
|
/*@__NO_SIDE_EFFECTS__*/
|
|
121
|
-
function jsonPayload(properties) {
|
|
122
|
-
return payload('application/json',
|
|
113
|
+
export function jsonPayload(properties) {
|
|
114
|
+
return payload('application/json', object(properties));
|
|
123
115
|
}
|
|
124
116
|
//# sourceMappingURL=payload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/schema/payload.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/schema/payload.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,MAAM,EAAE,MAAM,aAAa,CAAA;AAwElD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,OAAO;IAIlB,YACW,QAAmB,EACnB,MAAe;QADf,aAAQ,GAAR,QAAQ,CAAW;QACnB,WAAM,GAAN,MAAM,CAAS;QAExB,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACnD,MAAM,IAAI,SAAS,CAAC,qDAAqD,CAAC,CAAA;QAC5E,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,WAA+B;QAC7C,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;QAEzB,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,4EAA4E;YAC5E,OAAO,IAAI,CAAA;QACb,CAAC;aAAM,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;YAC/B,4CAA4C;YAC5C,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;YACvB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACjD,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/C,CAAC;QAED,gEAAgE;QAChE,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,QAAQ,KAAK,IAAI,CAAA;IAC1B,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAwB;AACxB,MAAM,UAAU,OAAO,CAGrB,WAAc,SAAc,EAAE,YAAe,SAAc;IAC3D,OAAO,IAAI,OAAO,CAAO,QAAQ,EAAE,SAAS,CAAC,CAAA;AAC/C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAwB;AACxB,MAAM,UAAU,WAAW,CAEzB,UAAa;IACb,OAAO,OAAO,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAA;AACxD,CAAC","sourcesContent":["import { LexValue } from '@atproto/lex-data'\nimport { InferInput, Schema, Validator } from '../core.js'\nimport { ObjectSchema, object } from './object.js'\n\nexport type { LexValue }\n\ntype ToBodyMime<TEncoding extends string> = TEncoding extends '*/*'\n ? `${string}/${string}`\n : TEncoding extends `${infer T extends string}/*`\n ? `${T}/${string}`\n : TEncoding\n\ntype ToBodyType<\n TEncoding extends string,\n TSchema,\n TBinary,\n> = TSchema extends Schema\n ? InferInput<TSchema>\n : TEncoding extends `application/json`\n ? LexValue\n : TBinary\n\n/**\n * Infers the type of a Payload's encoding and body.\n *\n * @template TPayload - The Payload type\n * @template TBody - Fallback body type for non-JSON encodings\n */\nexport type InferPayload<TPayload extends Payload, TBinary> =\n TPayload extends Payload<infer TEncoding, infer TSchema>\n ? TEncoding extends string\n ? {\n encoding: ToBodyMime<TEncoding>\n body: ToBodyType<TEncoding, TSchema, TBinary>\n }\n : undefined\n : never\n\n/**\n * Converts schema encoding patterns to data encoding types.\n *\n * Handles wildcards like '*\\/*' and 'image/*' in MIME types.\n *\n * @template TPayload - The Payload type\n */\nexport type InferPayloadEncoding<TPayload extends Payload> =\n TPayload extends Payload<infer TEncoding, any>\n ? TEncoding extends string\n ? ToBodyMime<TEncoding>\n : undefined\n : never\n\n/**\n * Infers the body type from a Payload and fallback type.\n *\n * @template TPayload - The Payload type\n * @template TBody - Fallback body type for non-JSON encodings without schema\n */\nexport type InferPayloadBody<TPayload extends Payload, TBinary> =\n TPayload extends Payload<infer TEncoding, infer TSchema>\n ? TEncoding extends string\n ? ToBodyType<TEncoding, TSchema, TBinary>\n : undefined\n : never\n\n/**\n * Determines valid schema type based on encoding presence.\n *\n * @template E - The encoding string type, or undefined\n */\nexport type PayloadSchema<E extends string | undefined> = E extends undefined\n ? undefined\n : Schema<LexValue> | undefined\n\n/**\n * Represents a payload definition for Lexicon endpoints.\n *\n * Payloads define the body format for HTTP requests and responses.\n * They consist of an encoding (MIME type) and an optional schema\n * for validating the body content.\n *\n * @template TEncoding - The MIME type string, or undefined for no body\n * @template TPayload - The schema type for body validation\n *\n * @example\n * ```ts\n * const jsonPayload = new Payload('application/json', l.object({ data: l.string() }))\n * const binaryPayload = new Payload('image/*', undefined)\n * const noPayload = new Payload(undefined, undefined)\n * ```\n */\nexport class Payload<\n const TEncoding extends string | undefined = string | undefined,\n const TSchema extends PayloadSchema<TEncoding> = PayloadSchema<TEncoding>,\n> {\n constructor(\n readonly encoding: TEncoding,\n readonly schema: TSchema,\n ) {\n if (encoding === undefined && schema !== undefined) {\n throw new TypeError('schema cannot be defined when encoding is undefined')\n }\n }\n\n /**\n * Checks whether the given content-type matches the expected payload schema's\n * encoding.\n */\n matchesEncoding(contentType: string | undefined): boolean {\n const { encoding } = this\n\n if (encoding === undefined) {\n // When the output is not defined, we don't enforce any rule on the payload.\n return true\n } else if (contentType == null) {\n // Expecting a body, but got no content-type\n return false\n }\n\n if (encoding === '*/*') {\n return true\n }\n\n const mime = contentType?.split(';', 1)[0].trim()\n if (encoding.endsWith('/*')) {\n return mime.startsWith(encoding.slice(0, -1))\n }\n\n // Invalid: Lexicon can only specify \"*/*\" or \"type/*\" wildcards\n if (encoding.includes('*')) {\n return false\n }\n\n return encoding === mime\n }\n}\n\n/**\n * Creates a payload definition for Lexicon endpoint bodies.\n *\n * Defines the expected MIME type and optional validation schema for\n * request or response bodies.\n *\n * @param encoding - MIME type string (e.g., 'application/json', 'image/*'), or undefined for no body\n * @param validator - Optional schema for validating the body content. Must be undefined if encoding is undefined.\n * @returns A new {@link Payload} instance\n *\n * @example\n * ```ts\n * // JSON payload with schema\n * const output = l.payload('application/json', l.object({\n * posts: l.array(postSchema),\n * cursor: l.optional(l.string()),\n * }))\n *\n * // Binary payload (no schema validation)\n * const blobInput = l.payload('*\\/*', undefined)\n *\n * // Image payload with wildcard\n * const imageInput = l.payload('image/*', undefined)\n *\n * // No payload (for endpoints without body)\n * const noBody = l.payload()\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function payload<\n const E extends string | undefined = undefined,\n const S extends PayloadSchema<E> = undefined,\n>(encoding: E = undefined as E, validator: S = undefined as S) {\n return new Payload<E, S>(encoding, validator)\n}\n\n/**\n * Creates a JSON payload with an object schema.\n *\n * Convenience function for the common case of JSON request/response bodies.\n * Equivalent to `l.payload('application/json', l.object(properties))`.\n *\n * @param properties - Object mapping property names to validators\n * @returns A new {@link Payload} instance with 'application/json' encoding\n *\n * @example\n * ```ts\n * // Query output\n * const profileOutput = l.jsonPayload({\n * did: l.string({ format: 'did' }),\n * handle: l.string({ format: 'handle' }),\n * displayName: l.optional(l.string()),\n * })\n *\n * // Procedure input\n * const createPostInput = l.jsonPayload({\n * text: l.string({ maxGraphemes: 300 }),\n * createdAt: l.string({ format: 'datetime' }),\n * })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function jsonPayload<\n P extends Record<string, Validator<undefined | LexValue>>,\n>(properties: P): Payload<'application/json', ObjectSchema<P>> {\n return payload('application/json', object(properties))\n}\n"]}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PermissionSet = void 0;
|
|
4
|
-
exports.permissionSet = permissionSet;
|
|
5
1
|
/**
|
|
6
2
|
* Represents a collection of related permissions in AT Protocol.
|
|
7
3
|
*
|
|
@@ -20,17 +16,13 @@ exports.permissionSet = permissionSet;
|
|
|
20
16
|
* )
|
|
21
17
|
* ```
|
|
22
18
|
*/
|
|
23
|
-
class PermissionSet {
|
|
24
|
-
nsid;
|
|
25
|
-
permissions;
|
|
26
|
-
options;
|
|
19
|
+
export class PermissionSet {
|
|
27
20
|
constructor(nsid, permissions, options = {}) {
|
|
28
21
|
this.nsid = nsid;
|
|
29
22
|
this.permissions = permissions;
|
|
30
23
|
this.options = options;
|
|
31
24
|
}
|
|
32
25
|
}
|
|
33
|
-
exports.PermissionSet = PermissionSet;
|
|
34
26
|
/**
|
|
35
27
|
* Creates a permission set grouping related permissions.
|
|
36
28
|
*
|
|
@@ -64,7 +56,7 @@ exports.PermissionSet = PermissionSet;
|
|
|
64
56
|
* ```
|
|
65
57
|
*/
|
|
66
58
|
/*@__NO_SIDE_EFFECTS__*/
|
|
67
|
-
function permissionSet(nsid, permissions, options) {
|
|
59
|
+
export function permissionSet(nsid, permissions, options) {
|
|
68
60
|
return new PermissionSet(nsid, permissions, options);
|
|
69
61
|
}
|
|
70
62
|
//# sourceMappingURL=permission-set.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-set.js","sourceRoot":"","sources":["../../src/schema/permission-set.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"permission-set.js","sourceRoot":"","sources":["../../src/schema/permission-set.ts"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,aAAa;IAIxB,YACW,IAAW,EACX,WAAyB,EACzB,UAAgC,EAAE;QAFlC,SAAI,GAAJ,IAAI,CAAO;QACX,gBAAW,GAAX,WAAW,CAAc;QACzB,YAAO,GAAP,OAAO,CAA2B;IAC1C,CAAC;CACL;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAwB;AACxB,MAAM,UAAU,aAAa,CAG3B,IAAO,EAAE,WAAc,EAAE,OAA8B;IACvD,OAAO,IAAI,aAAa,CAAO,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;AAC5D,CAAC","sourcesContent":["import { NsidString } from '../core.js'\nimport { Permission } from './permission.js'\n\n/**\n * Configuration options for a permission set.\n *\n * @property title - Human-readable title for the permission set\n * @property title:lang - Localized titles by language code\n * @property detail - Detailed description of the permission set\n * @property detail:lang - Localized descriptions by language code\n */\nexport type PermissionSetOptions = {\n title?: string\n 'title:lang'?: Record<string, undefined | string>\n detail?: string\n 'detail:lang'?: Record<string, undefined | string>\n}\n\n/**\n * Represents a collection of related permissions in AT Protocol.\n *\n * Permission sets group permissions together with metadata for OAuth\n * authorization flows. They are identified by an NSID.\n *\n * @template TNsid - The NSID identifying this permission set\n * @template TPermissions - Tuple type of the included permissions\n *\n * @example\n * ```ts\n * const feedAccess = new PermissionSet(\n * 'app.bsky.feed.access',\n * [readPermission, writePermission],\n * { title: 'Feed Access', detail: 'Read and write to your feed' }\n * )\n * ```\n */\nexport class PermissionSet<\n const TNsid extends NsidString = any,\n const TPermissions extends readonly Permission[] = any,\n> {\n constructor(\n readonly nsid: TNsid,\n readonly permissions: TPermissions,\n readonly options: PermissionSetOptions = {},\n ) {}\n}\n\n/**\n * Creates a permission set grouping related permissions.\n *\n * Permission sets define OAuth scopes that applications can request.\n * They include human-readable metadata for authorization UIs.\n *\n * @param nsid - The NSID identifying this permission set\n * @param permissions - Array of permissions included in this set\n * @param options - Optional metadata (title, detail, localization)\n * @returns A new {@link PermissionSet} instance\n *\n * @example\n * ```ts\n * // Define individual permissions\n * const readPosts = l.permission('read', { collection: 'app.bsky.feed.post' })\n * const writePosts = l.permission('write', { collection: 'app.bsky.feed.post' })\n *\n * // Group into a permission set\n * const postManagement = l.permissionSet(\n * 'app.bsky.feed.postManagement',\n * [readPosts, writePosts],\n * {\n * title: 'Post Management',\n * detail: 'View and create posts on your behalf',\n * 'title:lang': {\n * 'es': 'Gestion de publicaciones',\n * 'fr': 'Gestion des publications',\n * },\n * }\n * )\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function permissionSet<\n const N extends NsidString,\n const P extends readonly Permission[],\n>(nsid: N, permissions: P, options?: PermissionSetOptions) {\n return new PermissionSet<N, P>(nsid, permissions, options)\n}\n"]}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Permission = void 0;
|
|
4
|
-
exports.permission = permission;
|
|
5
1
|
/**
|
|
6
2
|
* Represents a single permission in an AT Protocol permission set.
|
|
7
3
|
*
|
|
@@ -16,15 +12,12 @@ exports.permission = permission;
|
|
|
16
12
|
* const readPermission = new Permission('read', { collection: 'app.bsky.feed.post' })
|
|
17
13
|
* ```
|
|
18
14
|
*/
|
|
19
|
-
class Permission {
|
|
20
|
-
resource;
|
|
21
|
-
options;
|
|
15
|
+
export class Permission {
|
|
22
16
|
constructor(resource, options) {
|
|
23
17
|
this.resource = resource;
|
|
24
18
|
this.options = options;
|
|
25
19
|
}
|
|
26
20
|
}
|
|
27
|
-
exports.Permission = Permission;
|
|
28
21
|
/**
|
|
29
22
|
* Creates a permission definition for AT Protocol authorization.
|
|
30
23
|
*
|
|
@@ -51,7 +44,7 @@ exports.Permission = Permission;
|
|
|
51
44
|
* ```
|
|
52
45
|
*/
|
|
53
46
|
/*@__NO_SIDE_EFFECTS__*/
|
|
54
|
-
function permission(resource, options = {}) {
|
|
47
|
+
export function permission(resource, options = {}) {
|
|
55
48
|
return new Permission(resource, options);
|
|
56
49
|
}
|
|
57
50
|
//# sourceMappingURL=permission.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission.js","sourceRoot":"","sources":["../../src/schema/permission.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"permission.js","sourceRoot":"","sources":["../../src/schema/permission.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,UAAU;IAIrB,YACW,QAAmB,EACnB,OAAiB;QADjB,aAAQ,GAAR,QAAQ,CAAW;QACnB,YAAO,GAAP,OAAO,CAAU;IACzB,CAAC;CACL;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAwB;AACxB,MAAM,UAAU,UAAU,CAGxB,QAAW,EAAE,UAAiC,EAAO;IACrD,OAAO,IAAI,UAAU,CAAO,QAAQ,EAAE,OAAO,CAAC,CAAA;AAChD,CAAC","sourcesContent":["import { Params } from './params.js'\n\n/**\n * Type alias for permission options (same as Params).\n */\nexport type PermissionOptions = Params\n\n/**\n * Represents a single permission in an AT Protocol permission set.\n *\n * Permissions define access rights to specific resources with optional\n * parameters for fine-grained control.\n *\n * @template TResource - The resource identifier string type\n * @template TOptions - The options type (must be valid Params)\n *\n * @example\n * ```ts\n * const readPermission = new Permission('read', { collection: 'app.bsky.feed.post' })\n * ```\n */\nexport class Permission<\n const TResource extends string = any,\n const TOptions extends PermissionOptions = any,\n> {\n constructor(\n readonly resource: TResource,\n readonly options: TOptions,\n ) {}\n}\n\n/**\n * Creates a permission definition for AT Protocol authorization.\n *\n * Permissions specify what resources an application can access.\n * Used in permission sets to define OAuth scopes.\n *\n * @param resource - The resource identifier (e.g., 'read', 'write', 'admin')\n * @param options - Optional parameters for the permission\n * @returns A new {@link Permission} instance\n *\n * @example\n * ```ts\n * // Simple permission\n * const readPermission = l.permission('read')\n *\n * // Permission with options\n * const writePostsPermission = l.permission('write', {\n * collection: 'app.bsky.feed.post',\n * })\n *\n * // Multiple permissions with different scopes\n * const readProfile = l.permission('read', { collection: 'app.bsky.actor.profile' })\n * const readFeed = l.permission('read', { collection: 'app.bsky.feed.*' })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function permission<\n const R extends string,\n const O extends PermissionOptions,\n>(resource: R, options: PermissionOptions & O = {} as O) {\n return new Permission<R, O>(resource, options)\n}\n"]}
|
package/dist/schema/procedure.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Procedure = void 0;
|
|
4
|
-
exports.procedure = procedure;
|
|
5
1
|
/**
|
|
6
2
|
* Represents a Lexicon procedure (HTTP POST) endpoint definition.
|
|
7
3
|
*
|
|
@@ -26,22 +22,16 @@ exports.procedure = procedure;
|
|
|
26
22
|
* )
|
|
27
23
|
* ```
|
|
28
24
|
*/
|
|
29
|
-
class Procedure {
|
|
30
|
-
nsid;
|
|
31
|
-
parameters;
|
|
32
|
-
input;
|
|
33
|
-
output;
|
|
34
|
-
errors;
|
|
35
|
-
type = 'procedure';
|
|
25
|
+
export class Procedure {
|
|
36
26
|
constructor(nsid, parameters, input, output, errors) {
|
|
37
27
|
this.nsid = nsid;
|
|
38
28
|
this.parameters = parameters;
|
|
39
29
|
this.input = input;
|
|
40
30
|
this.output = output;
|
|
41
31
|
this.errors = errors;
|
|
32
|
+
this.type = 'procedure';
|
|
42
33
|
}
|
|
43
34
|
}
|
|
44
|
-
exports.Procedure = Procedure;
|
|
45
35
|
/**
|
|
46
36
|
* Creates a procedure definition for a Lexicon POST endpoint.
|
|
47
37
|
*
|
|
@@ -83,7 +73,7 @@ exports.Procedure = Procedure;
|
|
|
83
73
|
* ```
|
|
84
74
|
*/
|
|
85
75
|
/*@__NO_SIDE_EFFECTS__*/
|
|
86
|
-
function procedure(nsid, parameters, input, output, errors = undefined) {
|
|
76
|
+
export function procedure(nsid, parameters, input, output, errors = undefined) {
|
|
87
77
|
return new Procedure(nsid, parameters, input, output, errors);
|
|
88
78
|
}
|
|
89
79
|
//# sourceMappingURL=procedure.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"procedure.js","sourceRoot":"","sources":["../../src/schema/procedure.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"procedure.js","sourceRoot":"","sources":["../../src/schema/procedure.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,SAAS;IAWpB,YACW,IAAW,EACX,UAAuB,EACvB,KAAoB,EACpB,MAAsB,EACtB,MAAe;QAJf,SAAI,GAAJ,IAAI,CAAO;QACX,eAAU,GAAV,UAAU,CAAa;QACvB,UAAK,GAAL,KAAK,CAAe;QACpB,WAAM,GAAN,MAAM,CAAgB;QACtB,WAAM,GAAN,MAAM,CAAS;QAPjB,SAAI,GAAG,WAAoB,CAAA;IAQjC,CAAC;CACL;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAwB;AACxB,MAAM,UAAU,SAAS,CAMvB,IAAO,EAAE,UAAa,EAAE,KAAQ,EAAE,MAAS,EAAE,SAAY,SAAc;IACvE,OAAO,IAAI,SAAS,CAAgB,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC9E,CAAC","sourcesContent":["import { NsidString } from '../core.js'\nimport { ParamsSchema } from './params.js'\nimport { Payload } from './payload.js'\n\n/**\n * Represents a Lexicon procedure (HTTP POST) endpoint definition.\n *\n * Procedures are operations that may modify state on the server.\n * They have parameters, an input payload (request body), an output\n * payload (response body), and optional error types.\n *\n * @template TNsid - The NSID identifying this procedure\n * @template TParameters - The parameters schema type\n * @template TInputPayload - The request body payload type\n * @template TOutputPayload - The response body payload type\n * @template TErrors - Array of error type strings, or undefined\n *\n * @example\n * ```ts\n * const createPost = new Procedure(\n * 'app.bsky.feed.post',\n * l.params({}),\n * l.jsonPayload({ text: l.string() }),\n * l.jsonPayload({ uri: l.string(), cid: l.string() }),\n * ['InvalidRecord']\n * )\n * ```\n */\nexport class Procedure<\n const TNsid extends NsidString = NsidString,\n const TParameters extends ParamsSchema = ParamsSchema,\n const TInputPayload extends Payload = Payload,\n const TOutputPayload extends Payload = Payload,\n const TErrors extends undefined | readonly string[] =\n | undefined\n | readonly string[],\n> {\n readonly type = 'procedure' as const\n\n constructor(\n readonly nsid: TNsid,\n readonly parameters: TParameters,\n readonly input: TInputPayload,\n readonly output: TOutputPayload,\n readonly errors: TErrors,\n ) {}\n}\n\n/**\n * Creates a procedure definition for a Lexicon POST endpoint.\n *\n * Procedures can modify server state. They accept both URL parameters\n * and a request body (input payload).\n *\n * @param nsid - The NSID identifying this procedure endpoint\n * @param parameters - Schema for URL query parameters\n * @param input - Schema for request body payload\n * @param output - Schema for response body payload\n * @param errors - Optional array of error type strings\n * @returns A new {@link Procedure} instance\n *\n * @example\n * ```ts\n * // Create record procedure\n * const createRecord = l.procedure(\n * 'com.atproto.repo.createRecord',\n * l.params({}),\n * l.jsonPayload({\n * repo: l.string({ format: 'at-identifier' }),\n * collection: l.string({ format: 'nsid' }),\n * record: l.unknown(),\n * }),\n * l.jsonPayload({\n * uri: l.string({ format: 'at-uri' }),\n * cid: l.string({ format: 'cid' }),\n * }),\n * ['InvalidRecord', 'RepoNotFound'],\n * )\n *\n * // Procedure with binary input\n * const uploadBlob = l.procedure(\n * 'com.atproto.repo.uploadBlob',\n * l.params({}),\n * l.payload('*\\/*', undefined), // Accept any content type\n * l.jsonPayload({ blob: l.blob() }),\n * )\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function procedure<\n const N extends NsidString,\n const P extends ParamsSchema,\n const I extends Payload,\n const O extends Payload,\n const E extends undefined | readonly string[] = undefined,\n>(nsid: N, parameters: P, input: I, output: O, errors: E = undefined as E) {\n return new Procedure<N, P, I, O, E>(nsid, parameters, input, output, errors)\n}\n"]}
|
package/dist/schema/query.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Query = void 0;
|
|
4
|
-
exports.query = query;
|
|
5
1
|
/**
|
|
6
2
|
* Represents a Lexicon query (HTTP GET) endpoint definition.
|
|
7
3
|
*
|
|
@@ -24,20 +20,15 @@ exports.query = query;
|
|
|
24
20
|
* )
|
|
25
21
|
* ```
|
|
26
22
|
*/
|
|
27
|
-
class Query {
|
|
28
|
-
nsid;
|
|
29
|
-
parameters;
|
|
30
|
-
output;
|
|
31
|
-
errors;
|
|
32
|
-
type = 'query';
|
|
23
|
+
export class Query {
|
|
33
24
|
constructor(nsid, parameters, output, errors) {
|
|
34
25
|
this.nsid = nsid;
|
|
35
26
|
this.parameters = parameters;
|
|
36
27
|
this.output = output;
|
|
37
28
|
this.errors = errors;
|
|
29
|
+
this.type = 'query';
|
|
38
30
|
}
|
|
39
31
|
}
|
|
40
|
-
exports.Query = Query;
|
|
41
32
|
/**
|
|
42
33
|
* Creates a query definition for a Lexicon GET endpoint.
|
|
43
34
|
*
|
|
@@ -72,7 +63,7 @@ exports.Query = Query;
|
|
|
72
63
|
* ```
|
|
73
64
|
*/
|
|
74
65
|
/*@__NO_SIDE_EFFECTS__*/
|
|
75
|
-
function query(nsid, parameters, output, errors = undefined) {
|
|
66
|
+
export function query(nsid, parameters, output, errors = undefined) {
|
|
76
67
|
return new Query(nsid, parameters, output, errors);
|
|
77
68
|
}
|
|
78
69
|
//# sourceMappingURL=query.js.map
|
package/dist/schema/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/schema/query.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/schema/query.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,KAAK;IAUhB,YACW,IAAW,EACX,UAAuB,EACvB,MAAsB,EACtB,MAAe;QAHf,SAAI,GAAJ,IAAI,CAAO;QACX,eAAU,GAAV,UAAU,CAAa;QACvB,WAAM,GAAN,MAAM,CAAgB;QACtB,WAAM,GAAN,MAAM,CAAS;QANjB,SAAI,GAAG,OAAgB,CAAA;IAO7B,CAAC;CACL;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAwB;AACxB,MAAM,UAAU,KAAK,CAKnB,IAAO,EAAE,UAAa,EAAE,MAAS,EAAE,SAAY,SAAc;IAC7D,OAAO,IAAI,KAAK,CAAa,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAChE,CAAC","sourcesContent":["import { NsidString } from '../core.js'\nimport { ParamsSchema } from './params.js'\nimport { Payload } from './payload.js'\n\n/**\n * Represents a Lexicon query (HTTP GET) endpoint definition.\n *\n * Queries are read-only operations that retrieve data from a server.\n * They have parameters (passed as URL query parameters), an output\n * payload, and optional error types.\n *\n * @template TNsid - The NSID identifying this query\n * @template TParameters - The parameters schema type\n * @template TOutputPayload - The output payload type\n * @template TErrors - Array of error type strings, or undefined\n *\n * @example\n * ```ts\n * const getPostQuery = new Query(\n * 'app.bsky.feed.getPost',\n * l.params({ uri: l.string({ format: 'at-uri' }) }),\n * l.payload('application/json', postSchema),\n * ['NotFound']\n * )\n * ```\n */\nexport class Query<\n const TNsid extends NsidString = NsidString,\n const TParameters extends ParamsSchema = ParamsSchema,\n const TOutputPayload extends Payload = Payload,\n const TErrors extends undefined | readonly string[] =\n | undefined\n | readonly string[],\n> {\n readonly type = 'query' as const\n\n constructor(\n readonly nsid: TNsid,\n readonly parameters: TParameters,\n readonly output: TOutputPayload,\n readonly errors: TErrors,\n ) {}\n}\n\n/**\n * Creates a query definition for a Lexicon GET endpoint.\n *\n * Queries retrieve data without side effects. Parameters are sent as\n * URL query string parameters.\n *\n * @param nsid - The NSID identifying this query endpoint\n * @param parameters - Schema for URL query parameters\n * @param output - Expected response payload schema\n * @param errors - Optional array of error type strings\n * @returns A new {@link Query} instance\n *\n * @example\n * ```ts\n * // Simple query with JSON output\n * const getProfile = l.query(\n * 'app.bsky.actor.getProfile',\n * l.params({ actor: l.string({ format: 'at-identifier' }) }),\n * l.jsonPayload({ displayName: l.string(), handle: l.string() }),\n * )\n *\n * // Query with pagination and errors\n * const getTimeline = l.query(\n * 'app.bsky.feed.getTimeline',\n * l.params({\n * limit: l.optional(l.integer({ minimum: 1, maximum: 100 })),\n * cursor: l.optional(l.string()),\n * }),\n * l.jsonPayload({ feed: l.array(feedItemSchema), cursor: l.optional(l.string()) }),\n * ['BlockedActor', 'BlockedByActor'],\n * )\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function query<\n const N extends NsidString,\n const P extends ParamsSchema,\n const O extends Payload,\n const E extends undefined | readonly string[] = undefined,\n>(nsid: N, parameters: P, output: O, errors: E = undefined as E) {\n return new Query<N, P, O, E>(nsid, parameters, output, errors)\n}\n"]}
|