@scalar/schemas 0.13.1 → 0.13.2

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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # @scalar/schemas
2
2
 
3
+ ## 0.13.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#10554](https://github.com/scalar/scalar/pull/10554): Render AsyncAPI boolean schemas with explanations in message payloads, headers, and reusable models.
8
+ - [#10565](https://github.com/scalar/scalar/pull/10565): Inherit AsyncAPI operation metadata and replies from traits using recursive merge rules, and use inherited titles in navigation.
9
+
3
10
  ## 0.13.1
4
11
 
5
12
  ## 0.13.0
@@ -1 +1 @@
1
- {"version":3,"file":"operation-trait.d.ts","sourceRoot":"","sources":["../../../src/asyncapi/3.1/operation-trait.ts"],"names":[],"mappings":"AAQA,gDAAgD;AAChD,eAAO,MAAM,4BAA4B,qCAuBxC,CAAA"}
1
+ {"version":3,"file":"operation-trait.d.ts","sourceRoot":"","sources":["../../../src/asyncapi/3.1/operation-trait.ts"],"names":[],"mappings":"AASA,gDAAgD;AAChD,eAAO,MAAM,4BAA4B,qCAwBxC,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { array, object, optional, string } from '@scalar/validation';
2
2
  import { asyncApiOperationBindingsObject } from './bindings.js';
3
3
  import { asyncApiExternalDocumentationObject } from './external-documentation.js';
4
+ import { asyncApiOperationReplyObject } from './operation-reply.js';
4
5
  import { recursiveRef } from './reference.js';
5
6
  import { asyncApiSecuritySchemeObject } from './security-scheme.js';
6
7
  import { asyncApiTagsObject } from './tag.js';
@@ -17,4 +18,5 @@ export const asyncApiOperationTraitObject = recursiveRef(object({
17
18
  tags: optional(asyncApiTagsObject),
18
19
  externalDocs: optional(asyncApiExternalDocumentationObject),
19
20
  bindings: optional(recursiveRef(asyncApiOperationBindingsObject)),
21
+ reply: optional(asyncApiOperationReplyObject),
20
22
  }, { typeName: 'AsyncApiOperationTraitObject' }));
@@ -1,5 +1,5 @@
1
1
  import { literal, object, optional, string, union, unknown } from '@scalar/validation';
2
- import { schema as schemaObject } from '../../openapi/3.1/schema.js';
2
+ import { createSchema } from '../../openapi/3.1/schema.js';
3
3
  import { recursiveRef } from './reference.js';
4
4
  export const asyncApiMultiFormatSchemaObject = object({
5
5
  schemaFormat: optional(string({
@@ -11,7 +11,7 @@ export const asyncApiMultiFormatSchemaObject = object({
11
11
  }, { typeName: 'AsyncApiMultiFormatSchemaObject' });
12
12
  // AsyncAPI's default schema format is JSON Schema, the same dialect OpenAPI 3.1 uses, so we reuse the
13
13
  // OpenAPI Schema Object here instead of an opaque `unknown`. A schema may also be a boolean per JSON Schema.
14
- const asyncApiSchemaJsonShape = union([literal(true), literal(false), schemaObject], {
14
+ const asyncApiSchemaJsonShape = union([literal(true), literal(false), createSchema(true)], {
15
15
  typeName: 'AsyncApiSchemaJsonShape',
16
16
  });
17
17
  /** Schema Object | Reference Object */
@@ -1,3 +1,8 @@
1
1
  import { type Schema } from '@scalar/validation';
2
+ /**
3
+ * Build the shared Schema Object shape, optionally accepting boolean child schemas.
4
+ * AsyncAPI uses JSON Schema booleans recursively; the OpenAPI ingestion pipeline normalizes them first.
5
+ */
6
+ export declare const createSchema: (booleanSchemas?: boolean) => Schema;
2
7
  export declare const schema: Schema;
3
8
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/openapi/3.1/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EAaZ,MAAM,oBAAoB,CAAA;AA0K3B,eAAO,MAAM,MAAM,EAAE,MAOpB,CAAA"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/openapi/3.1/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EAaZ,MAAM,oBAAoB,CAAA;AAS3B;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,wBAAsB,KAAG,MA6KrD,CAAA;AAED,eAAO,MAAM,MAAM,QAAiB,CAAA"}
@@ -5,128 +5,137 @@ import { discriminatorObject } from '../../openapi/3.1/discriminator.js';
5
5
  import { externalDocs } from '../../openapi/3.1/external-docs.js';
6
6
  import { normalRef } from '../../openapi/3.1/reference.js';
7
7
  import { xml } from '../../openapi/3.1/xml.js';
8
- const schemaExtensionObjects = [
9
- XScalarIgnore,
10
- XInternal,
11
- XVariable,
12
- XExamples,
13
- XEnumDescriptions,
14
- XEnumVarNames,
15
- XAdditionalPropertiesName,
16
- XTags,
17
- ];
18
- const coreSchemaProperties = object({
19
- name: optional(string({ typeComment: 'Schema name (extension).' })),
20
- title: optional(string({ typeComment: 'A title for the schema.' })),
21
- description: optional(string({ typeComment: 'A description of the schema.' })),
22
- default: optional(any({ typeComment: 'Default value for the schema.' })),
23
- enum: optional(array(any(), { typeComment: 'Array of allowed values.', typeName: 'JsonSchemaEnum' })),
24
- const: optional(any({ typeComment: 'Constant value that must match exactly.' })),
25
- contentMediaType: optional(string({ typeComment: 'Media type for content validation.' })),
26
- contentEncoding: optional(string({ typeComment: 'Content encoding.' })),
27
- contentSchema: optional(normalRef(lazy(() => schema))),
28
- deprecated: optional(boolean({ typeComment: 'Whether the schema is deprecated.' })),
29
- discriminator: optional(discriminatorObject),
30
- readOnly: optional(boolean({ typeComment: 'Whether the schema is read-only.' })),
31
- writeOnly: optional(boolean({ typeComment: 'Whether the schema is write-only.' })),
32
- xml: optional(xml),
33
- externalDocs: optional(externalDocs),
34
- example: optional(any({
35
- typeComment: 'A free-form field to include an example of an instance for this schema. Deprecated in favor of the JSON Schema examples keyword.',
36
- })),
37
- examples: optional(array(any(), {
38
- typeComment: 'An array of examples of valid instances for this schema. This keyword follows the JSON Schema Draft 2020-12 specification.',
39
- typeName: 'SchemaExamplesArray',
40
- })),
41
- allOf: optional(array(normalRef(lazy(() => schema)), { typeName: 'SchemaObjectAllOf' })),
42
- oneOf: optional(array(normalRef(lazy(() => schema)), { typeName: 'SchemaObjectOneOf' })),
43
- anyOf: optional(array(normalRef(lazy(() => schema)), { typeName: 'SchemaObjectAnyOf' })),
44
- not: optional(normalRef(lazy(() => schema))),
45
- });
46
- const numericValidationKeywords = object({
47
- multipleOf: optional(number({ typeComment: 'Number must be a multiple of this value.' })),
48
- maximum: optional(number({ typeComment: 'Maximum value (inclusive).' })),
49
- exclusiveMaximum: optional(number({ typeComment: 'Maximum value (exclusive).' })),
50
- minimum: optional(number({ typeComment: 'Minimum value (inclusive).' })),
51
- exclusiveMinimum: optional(number({ typeComment: 'Minimum value (exclusive).' })),
52
- });
53
- const numericSchema = intersection([
54
- object({
55
- type: union([literal('number'), literal('integer')]),
56
- format: optional(string({ typeComment: 'Different subtypes.' })),
57
- }),
58
- numericValidationKeywords,
59
- ], { typeName: 'NumberSchemaObject' });
60
- const stringValidationKeywords = object({
61
- maxLength: optional(number({ typeComment: 'Maximum string length.' })),
62
- minLength: optional(number({ typeComment: 'Minimum string length.' })),
63
- pattern: optional(string({ typeComment: 'Regular expression pattern.' })),
64
- });
65
- const stringSchema = intersection([
66
- object({
67
- type: literal('string'),
68
- format: optional(string({ typeComment: 'Different subtypes.' })),
69
- }),
70
- stringValidationKeywords,
71
- ], { typeName: 'StringSchemaObject' });
72
- const objectValidationKeywords = object({
73
- maxProperties: optional(number({ typeComment: 'Maximum number of properties.' })),
74
- minProperties: optional(number({ typeComment: 'Minimum number of properties.' })),
75
- properties: optional(record(string(), normalRef(lazy(() => schema)), { typeName: 'SchemaObjectProperties' })),
76
- required: optional(array(string(), { typeName: 'SchemaObjectRequired' })),
77
- additionalProperties: optional(union([normalRef(lazy(() => schema)), object({}), boolean()], {
78
- typeName: 'SchemaObjectAdditionalProperties',
79
- })),
80
- patternProperties: optional(record(string(), normalRef(lazy(() => schema)), { typeName: 'SchemaObjectPatternProperties' })),
81
- propertyNames: optional(normalRef(lazy(() => schema))),
82
- });
83
- const objectSchema = intersection([
84
- object({
85
- type: literal('object'),
86
- }),
87
- objectValidationKeywords,
88
- ], { typeName: 'ObjectSchemaObject' });
89
- const arrayValidationKeywords = object({
90
- maxItems: optional(number({ typeComment: 'Maximum number of items in array.' })),
91
- minItems: optional(number({ typeComment: 'Minimum number of items in array.' })),
92
- uniqueItems: optional(boolean({ typeComment: 'Whether array items must be unique.' })),
93
- items: optional(normalRef(lazy(() => schema))),
94
- prefixItems: optional(array(normalRef(lazy(() => schema)), { typeComment: 'Schema for tuple validation.' })),
95
- });
96
- const arraySchema = intersection([
97
- object({
98
- type: literal('array'),
99
- }),
100
- arrayValidationKeywords,
101
- ], { typeName: 'ArraySchemaObject' });
102
- const schemaTypeMulti = union([
103
- literal('null'),
104
- literal('boolean'),
105
- literal('string'),
106
- literal('number'),
107
- literal('integer'),
108
- literal('object'),
109
- literal('array'),
110
- ], { typeName: 'SchemaObjectMultiTypeKeywords' });
111
- const otherTypeSchema = object({
112
- type: union([literal('null'), literal('boolean')], {
113
- typeName: 'SchemaObjectOtherTypeKeyword',
114
- }),
115
- });
116
- const multiTypeSchema = intersection([
117
- object({
118
- type: array(schemaTypeMulti, {
119
- typeName: 'SchemaObjectMultiTypeKeywordArray',
8
+ /**
9
+ * Build the shared Schema Object shape, optionally accepting boolean child schemas.
10
+ * AsyncAPI uses JSON Schema booleans recursively; the OpenAPI ingestion pipeline normalizes them first.
11
+ */
12
+ export const createSchema = (booleanSchemas = false) => {
13
+ const schemaExtensionObjects = [
14
+ XScalarIgnore,
15
+ XInternal,
16
+ XVariable,
17
+ XExamples,
18
+ XEnumDescriptions,
19
+ XEnumVarNames,
20
+ XAdditionalPropertiesName,
21
+ XTags,
22
+ ];
23
+ const coreSchemaProperties = object({
24
+ name: optional(string({ typeComment: 'Schema name (extension).' })),
25
+ title: optional(string({ typeComment: 'A title for the schema.' })),
26
+ description: optional(string({ typeComment: 'A description of the schema.' })),
27
+ default: optional(any({ typeComment: 'Default value for the schema.' })),
28
+ enum: optional(array(any(), { typeComment: 'Array of allowed values.', typeName: 'JsonSchemaEnum' })),
29
+ const: optional(any({ typeComment: 'Constant value that must match exactly.' })),
30
+ contentMediaType: optional(string({ typeComment: 'Media type for content validation.' })),
31
+ contentEncoding: optional(string({ typeComment: 'Content encoding.' })),
32
+ contentSchema: optional(normalRef(lazy(() => nestedSchema))),
33
+ deprecated: optional(boolean({ typeComment: 'Whether the schema is deprecated.' })),
34
+ discriminator: optional(discriminatorObject),
35
+ readOnly: optional(boolean({ typeComment: 'Whether the schema is read-only.' })),
36
+ writeOnly: optional(boolean({ typeComment: 'Whether the schema is write-only.' })),
37
+ xml: optional(xml),
38
+ externalDocs: optional(externalDocs),
39
+ example: optional(any({
40
+ typeComment: 'A free-form field to include an example of an instance for this schema. Deprecated in favor of the JSON Schema examples keyword.',
41
+ })),
42
+ examples: optional(array(any(), {
43
+ typeComment: 'An array of examples of valid instances for this schema. This keyword follows the JSON Schema Draft 2020-12 specification.',
44
+ typeName: 'SchemaExamplesArray',
45
+ })),
46
+ allOf: optional(array(normalRef(lazy(() => nestedSchema)), { typeName: 'SchemaObjectAllOf' })),
47
+ oneOf: optional(array(normalRef(lazy(() => nestedSchema)), { typeName: 'SchemaObjectOneOf' })),
48
+ anyOf: optional(array(normalRef(lazy(() => nestedSchema)), { typeName: 'SchemaObjectAnyOf' })),
49
+ not: optional(normalRef(lazy(() => nestedSchema))),
50
+ });
51
+ const numericValidationKeywords = object({
52
+ multipleOf: optional(number({ typeComment: 'Number must be a multiple of this value.' })),
53
+ maximum: optional(number({ typeComment: 'Maximum value (inclusive).' })),
54
+ exclusiveMaximum: optional(number({ typeComment: 'Maximum value (exclusive).' })),
55
+ minimum: optional(number({ typeComment: 'Minimum value (inclusive).' })),
56
+ exclusiveMinimum: optional(number({ typeComment: 'Minimum value (exclusive).' })),
57
+ });
58
+ const numericSchema = intersection([
59
+ object({
60
+ type: union([literal('number'), literal('integer')]),
61
+ format: optional(string({ typeComment: 'Different subtypes.' })),
120
62
  }),
121
- format: optional(string({ typeComment: 'Different subtypes.' })),
122
- }),
123
- numericValidationKeywords,
124
- stringValidationKeywords,
125
- arrayValidationKeywords,
126
- objectValidationKeywords,
127
- ], { typeName: 'MultiTypeSchemaObject' });
128
- export const schema = intersection([
129
- coreSchemaProperties,
130
- ...schemaExtensionObjects,
131
- union([otherTypeSchema, numericSchema, stringSchema, objectSchema, arraySchema, multiTypeSchema, object({})]),
132
- ], { typeName: 'SchemaObject' });
63
+ numericValidationKeywords,
64
+ ], { typeName: 'NumberSchemaObject' });
65
+ const stringValidationKeywords = object({
66
+ maxLength: optional(number({ typeComment: 'Maximum string length.' })),
67
+ minLength: optional(number({ typeComment: 'Minimum string length.' })),
68
+ pattern: optional(string({ typeComment: 'Regular expression pattern.' })),
69
+ });
70
+ const stringSchema = intersection([
71
+ object({
72
+ type: literal('string'),
73
+ format: optional(string({ typeComment: 'Different subtypes.' })),
74
+ }),
75
+ stringValidationKeywords,
76
+ ], { typeName: 'StringSchemaObject' });
77
+ const objectValidationKeywords = object({
78
+ maxProperties: optional(number({ typeComment: 'Maximum number of properties.' })),
79
+ minProperties: optional(number({ typeComment: 'Minimum number of properties.' })),
80
+ properties: optional(record(string(), normalRef(lazy(() => nestedSchema)), { typeName: 'SchemaObjectProperties' })),
81
+ required: optional(array(string(), { typeName: 'SchemaObjectRequired' })),
82
+ additionalProperties: optional(union([normalRef(lazy(() => nestedSchema)), object({}), boolean()], {
83
+ typeName: 'SchemaObjectAdditionalProperties',
84
+ })),
85
+ patternProperties: optional(record(string(), normalRef(lazy(() => nestedSchema)), { typeName: 'SchemaObjectPatternProperties' })),
86
+ propertyNames: optional(normalRef(lazy(() => nestedSchema))),
87
+ });
88
+ const objectSchema = intersection([
89
+ object({
90
+ type: literal('object'),
91
+ }),
92
+ objectValidationKeywords,
93
+ ], { typeName: 'ObjectSchemaObject' });
94
+ const arrayValidationKeywords = object({
95
+ maxItems: optional(number({ typeComment: 'Maximum number of items in array.' })),
96
+ minItems: optional(number({ typeComment: 'Minimum number of items in array.' })),
97
+ uniqueItems: optional(boolean({ typeComment: 'Whether array items must be unique.' })),
98
+ items: optional(normalRef(lazy(() => nestedSchema))),
99
+ prefixItems: optional(array(normalRef(lazy(() => nestedSchema)), { typeComment: 'Schema for tuple validation.' })),
100
+ });
101
+ const arraySchema = intersection([
102
+ object({
103
+ type: literal('array'),
104
+ }),
105
+ arrayValidationKeywords,
106
+ ], { typeName: 'ArraySchemaObject' });
107
+ const schemaTypeMulti = union([
108
+ literal('null'),
109
+ literal('boolean'),
110
+ literal('string'),
111
+ literal('number'),
112
+ literal('integer'),
113
+ literal('object'),
114
+ literal('array'),
115
+ ], { typeName: 'SchemaObjectMultiTypeKeywords' });
116
+ const otherTypeSchema = object({
117
+ type: union([literal('null'), literal('boolean')], {
118
+ typeName: 'SchemaObjectOtherTypeKeyword',
119
+ }),
120
+ });
121
+ const multiTypeSchema = intersection([
122
+ object({
123
+ type: array(schemaTypeMulti, {
124
+ typeName: 'SchemaObjectMultiTypeKeywordArray',
125
+ }),
126
+ format: optional(string({ typeComment: 'Different subtypes.' })),
127
+ }),
128
+ numericValidationKeywords,
129
+ stringValidationKeywords,
130
+ arrayValidationKeywords,
131
+ objectValidationKeywords,
132
+ ], { typeName: 'MultiTypeSchemaObject' });
133
+ const schema = intersection([
134
+ coreSchemaProperties,
135
+ ...schemaExtensionObjects,
136
+ union([otherTypeSchema, numericSchema, stringSchema, objectSchema, arraySchema, multiTypeSchema, object({})]),
137
+ ], { typeName: 'SchemaObject' });
138
+ const nestedSchema = booleanSchemas ? union([boolean(), schema]) : schema;
139
+ return schema;
140
+ };
141
+ export const schema = createSchema();
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "schemas",
15
15
  "scalar"
16
16
  ],
17
- "version": "0.13.1",
17
+ "version": "0.13.2",
18
18
  "engines": {
19
19
  "node": ">=22"
20
20
  },
@@ -41,11 +41,11 @@
41
41
  "CHANGELOG.md"
42
42
  ],
43
43
  "dependencies": {
44
- "@scalar/helpers": "0.16.2",
45
- "@scalar/validation": "0.6.6"
44
+ "@scalar/helpers": "0.16.3",
45
+ "@scalar/validation": "0.6.7"
46
46
  },
47
47
  "devDependencies": {
48
- "@scalar/types": "0.23.1",
48
+ "@scalar/types": "0.23.2",
49
49
  "vitest": "4.1.10"
50
50
  },
51
51
  "scripts": {