microsoft/typespec

Public

mirrored from https://github.com/microsoft/typespecAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
a6b7827fcd2db3bf604d42e235216c8d5b244f13

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

packages/json-schema/src/index.ts

269lines · modecode

1import {
2 DecoratorContext,
3 EmitContext,
4 Enum,
5 Model,
6 ModelProperty,
7 Namespace,
8 Program,
9 Scalar,
10 StringLiteral,
11 Tuple,
12 Type,
13 Union,
14 typespecTypeToJson,
15} from "@typespec/compiler";
16import { JsonSchemaEmitter } from "./json-schema-emitter.js";
17import { JSONSchemaEmitterOptions, createStateSymbol } from "./lib.js";
18
19export { JsonSchemaEmitter } from "./json-schema-emitter.js";
20export { $lib, EmitterOptionsSchema, JSONSchemaEmitterOptions } from "./lib.js";
21
22export const namespace = "TypeSpec.JsonSchema";
23export type JsonSchemaDeclaration = Model | Union | Enum | Scalar;
24
25const jsonSchemaKey = createStateSymbol("JsonSchema");
26
27export async function $onEmit(context: EmitContext<JSONSchemaEmitterOptions>) {
28 const emitter = context.getAssetEmitter(JsonSchemaEmitter);
29
30 if (emitter.getOptions().emitAllModels) {
31 emitter.emitProgram({ emitTypeSpecNamespace: false });
32 } else {
33 for (const item of getJsonSchemaTypes(context.program)) {
34 emitter.emitType(item);
35 }
36 }
37
38 await emitter.writeOutput();
39}
40
41export function $jsonSchema(
42 context: DecoratorContext,
43 target: JsonSchemaDeclaration | Namespace,
44 baseUriOrId?: string
45) {
46 context.program.stateSet(jsonSchemaKey).add(target);
47 if (baseUriOrId) {
48 if (target.kind === "Namespace") {
49 context.call($baseUri, target, baseUriOrId);
50 } else {
51 context.call($id, target, baseUriOrId);
52 }
53 }
54}
55
56const baseUriKey = createStateSymbol("JsonSchema.baseURI");
57export function $baseUri(context: DecoratorContext, target: Namespace, baseUri: string) {
58 context.program.stateMap(baseUriKey).set(target, baseUri);
59}
60
61export function getBaseUri(program: Program, target: Type) {
62 return program.stateMap(baseUriKey).get(target);
63}
64
65export function findBaseUri(
66 program: Program,
67 target: JsonSchemaDeclaration | Namespace
68): string | undefined {
69 let baseUrl: string | undefined;
70 let current: JsonSchemaDeclaration | Namespace | undefined = target;
71 do {
72 baseUrl = getBaseUri(program, current);
73 current = current.namespace;
74 } while (!baseUrl && current);
75
76 return baseUrl;
77}
78
79export function isJsonSchemaDeclaration(program: Program, target: JsonSchemaDeclaration) {
80 let current: JsonSchemaDeclaration | Namespace | undefined = target;
81 do {
82 if (getJsonSchema(program, current)) {
83 return true;
84 }
85
86 current = current.namespace;
87 } while (current);
88
89 return false;
90}
91
92export function getJsonSchemaTypes(program: Program): (Namespace | Model)[] {
93 return [...(program.stateSet(jsonSchemaKey) || [])] as (Namespace | Model)[];
94}
95
96export function getJsonSchema(program: Program, target: Type) {
97 return program.stateSet(jsonSchemaKey).has(target);
98}
99
100const multipleOfKey = createStateSymbol("JsonSchema.multipleOf");
101export function $multipleOf(context: DecoratorContext, target: Model, value: number) {
102 context.program.stateMap(multipleOfKey).set(target, value);
103}
104
105export function getMultipleOf(program: Program, target: Type) {
106 return program.stateMap(multipleOfKey).get(target);
107}
108
109const idKey = createStateSymbol("JsonSchema.id");
110export function $id(
111 context: DecoratorContext,
112 target: Model | Union | Enum | Scalar,
113 value: string
114) {
115 context.program.stateMap(idKey).set(target, value);
116}
117
118export function getId(program: Program, target: Type) {
119 return program.stateMap(idKey).get(target);
120}
121
122const containsKey = createStateSymbol("JsonSchema.contains");
123export function $contains(context: DecoratorContext, target: Model | ModelProperty, value: Type) {
124 context.program.stateMap(containsKey).set(target, value);
125}
126
127export function getContains(program: Program, target: Type) {
128 return program.stateMap(containsKey).get(target);
129}
130
131const minContainsKey = createStateSymbol("JsonSchema.minContains");
132export function $minContains(
133 context: DecoratorContext,
134 target: Model | ModelProperty,
135 value: number
136) {
137 context.program.stateMap(minContainsKey).set(target, value);
138}
139
140export function getMinContains(program: Program, target: Type) {
141 return program.stateMap(minContainsKey).get(target);
142}
143
144const maxContainsKey = createStateSymbol("JsonSchema.maxContains");
145export function $maxContains(
146 context: DecoratorContext,
147 target: Model | ModelProperty,
148 value: number
149) {
150 context.program.stateMap(maxContainsKey).set(target, value);
151}
152
153export function getMaxContains(program: Program, target: Type) {
154 return program.stateMap(maxContainsKey).get(target);
155}
156
157const uniqueItemsKey = createStateSymbol("JsonSchema.uniqueItems");
158export function $uniqueItems(context: DecoratorContext, target: Model | ModelProperty) {
159 context.program.stateMap(uniqueItemsKey).set(target, true);
160}
161
162export function getUniqueItems(program: Program, target: Type) {
163 return program.stateMap(uniqueItemsKey).get(target);
164}
165
166const minPropertiesKey = createStateSymbol("JsonSchema.minProperties");
167export function $minProperties(
168 context: DecoratorContext,
169 target: Model | ModelProperty,
170 value: number
171) {
172 context.program.stateMap(minPropertiesKey).set(target, value);
173}
174
175export function getMinProperties(program: Program, target: Type) {
176 return program.stateMap(minPropertiesKey).get(target);
177}
178
179const maxPropertiesKey = createStateSymbol("JsonSchema.maxProperties");
180export function $maxProperties(
181 context: DecoratorContext,
182 target: Model | ModelProperty,
183 value: number
184) {
185 context.program.stateMap(maxPropertiesKey).set(target, value);
186}
187
188export function getMaxProperties(program: Program, target: Type) {
189 return program.stateMap(maxPropertiesKey).get(target);
190}
191
192const contentEncodingKey = createStateSymbol("JsonSchema.contentEncoding");
193export function $contentEncoding(
194 context: DecoratorContext,
195 target: StringLiteral | ModelProperty,
196 value: string
197) {
198 context.program.stateMap(contentEncodingKey).set(target, value);
199}
200
201export function getContentEncoding(program: Program, target: Type): string {
202 return program.stateMap(contentEncodingKey).get(target);
203}
204
205const contentMediaType = createStateSymbol("JsonSchema.contentMediaType");
206export function $contentMediaType(
207 context: DecoratorContext,
208 target: StringLiteral | ModelProperty,
209 value: string
210) {
211 context.program.stateMap(contentMediaType).set(target, value);
212}
213
214export function getContentMediaType(program: Program, target: Type): string {
215 return program.stateMap(contentMediaType).get(target);
216}
217
218const contentSchemaKey = createStateSymbol("JsonSchema.contentSchema");
219export function $contentSchema(
220 context: DecoratorContext,
221 target: StringLiteral | ModelProperty,
222 value: Type
223) {
224 context.program.stateMap(contentSchemaKey).set(target, value);
225}
226
227export function getContentSchema(program: Program, target: Type) {
228 return program.stateMap(contentSchemaKey).get(target);
229}
230
231const prefixItemsKey = createStateSymbol("JsonSchema.prefixItems");
232export function $prefixItems(
233 context: DecoratorContext,
234 target: Model | ModelProperty,
235 value: Tuple
236) {
237 context.program.stateMap(prefixItemsKey).set(target, value);
238}
239
240export function getPrefixItems(program: Program, target: Type): Tuple | undefined {
241 return program.stateMap(prefixItemsKey).get(target);
242}
243
244export interface ExtensionRecord {
245 key: string;
246 value: Type;
247}
248
249const extensionsKey = createStateSymbol("JsonSchema.extension");
250export function $extension(context: DecoratorContext, target: Type, key: string, value: Type) {
251 const stateMap = context.program.stateMap(extensionsKey) as Map<Type, ExtensionRecord[]>;
252 const extensions = stateMap.has(target)
253 ? stateMap.get(target)!
254 : stateMap.set(target, []).get(target)!;
255
256 extensions.push({ key, value });
257}
258
259export function getExtensions(program: Program, target: Type): ExtensionRecord[] {
260 return program.stateMap(extensionsKey).get(target) ?? [];
261}
262
263export function $validatesRawJson(context: DecoratorContext, target: Model, value: Type) {
264 const [_, diagnostics] = typespecTypeToJson(value, target);
265 if (diagnostics.length > 0) {
266 context.program.reportDiagnostics(diagnostics);
267 }
268}
269$validatesRawJson.namespace = "Private";