Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@typespec/openapi3

Package Overview
Dependencies
Maintainers
1
Versions
219
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@typespec/openapi3 - npm Package Compare versions

Comparing version 0.54.0-dev.4 to 0.54.0-dev.5

112

dist/src/lib.d.ts

@@ -224,3 +224,3 @@ import { JSONSchemaType } from "@typespec/compiler";

}, OpenAPI3EmitterOptions, never>;
export declare const reportDiagnostic: <C extends "oneof-union" | "inconsistent-shared-route-request-visibility" | "invalid-server-variable" | "invalid-format" | "resource-namespace" | "path-query" | "duplicate-body" | "duplicate-header" | "status-code-in-default-response" | "invalid-schema" | "union-null" | "empty-union" | "empty-enum" | "enum-unique-type" | "invalid-default" | "inline-cycle" | "unsupported-status-code-range" | "unsupported-auth", M extends keyof {
export declare const createDiagnostic: <C extends "oneof-union" | "inconsistent-shared-route-request-visibility" | "invalid-server-variable" | "invalid-format" | "resource-namespace" | "path-query" | "duplicate-body" | "duplicate-header" | "status-code-in-default-response" | "invalid-schema" | "union-null" | "empty-union" | "empty-enum" | "enum-unique-type" | "invalid-default" | "inline-cycle" | "unsupported-status-code-range" | "unsupported-auth", M extends keyof {
"oneof-union": {

@@ -280,2 +280,112 @@ readonly default: "@oneOf decorator can only be used on a union or a model property which type is a union.";

};
}[C]>(diag: import("@typespec/compiler").DiagnosticReport<{
"oneof-union": {
readonly default: "@oneOf decorator can only be used on a union or a model property which type is a union.";
};
"inconsistent-shared-route-request-visibility": {
readonly default: "All operations with `@sharedRoutes` must have the same `@requestVisibility`.";
};
"invalid-server-variable": {
readonly default: import("@typespec/compiler").CallableMessage<["propName"]>;
};
"invalid-format": {
readonly default: import("@typespec/compiler").CallableMessage<["value", "paramType"]>;
};
"resource-namespace": {
readonly default: "Resource goes on namespace";
};
"path-query": {
readonly default: "OpenAPI does not allow paths containing a query string.";
};
"duplicate-body": {
readonly default: "Duplicate @body declarations on response type";
};
"duplicate-header": {
readonly default: import("@typespec/compiler").CallableMessage<["header"]>;
};
"status-code-in-default-response": {
readonly default: "a default response should not have an explicit status code";
};
"invalid-schema": {
readonly default: import("@typespec/compiler").CallableMessage<["type"]>;
};
"union-null": {
readonly default: "Cannot have a union containing only null types.";
};
"empty-union": {
readonly default: "Empty unions are not supported for OpenAPI v3 - enums must have at least one value.";
};
"empty-enum": {
readonly default: "Empty enums are not supported for OpenAPI v3 - enums must have at least one value.";
};
"enum-unique-type": {
readonly default: "Enums are not supported unless all options are literals of the same type.";
};
"invalid-default": {
readonly default: import("@typespec/compiler").CallableMessage<["type"]>;
};
"inline-cycle": {
readonly default: import("@typespec/compiler").CallableMessage<["type"]>;
};
"unsupported-status-code-range": {
readonly default: import("@typespec/compiler").CallableMessage<["start", "end"]>;
};
"unsupported-auth": {
readonly default: import("@typespec/compiler").CallableMessage<["authType"]>;
};
}, C, M>) => import("@typespec/compiler").Diagnostic, reportDiagnostic: <C extends "oneof-union" | "inconsistent-shared-route-request-visibility" | "invalid-server-variable" | "invalid-format" | "resource-namespace" | "path-query" | "duplicate-body" | "duplicate-header" | "status-code-in-default-response" | "invalid-schema" | "union-null" | "empty-union" | "empty-enum" | "enum-unique-type" | "invalid-default" | "inline-cycle" | "unsupported-status-code-range" | "unsupported-auth", M extends keyof {
"oneof-union": {
readonly default: "@oneOf decorator can only be used on a union or a model property which type is a union.";
};
"inconsistent-shared-route-request-visibility": {
readonly default: "All operations with `@sharedRoutes` must have the same `@requestVisibility`.";
};
"invalid-server-variable": {
readonly default: import("@typespec/compiler").CallableMessage<["propName"]>;
};
"invalid-format": {
readonly default: import("@typespec/compiler").CallableMessage<["value", "paramType"]>;
};
"resource-namespace": {
readonly default: "Resource goes on namespace";
};
"path-query": {
readonly default: "OpenAPI does not allow paths containing a query string.";
};
"duplicate-body": {
readonly default: "Duplicate @body declarations on response type";
};
"duplicate-header": {
readonly default: import("@typespec/compiler").CallableMessage<["header"]>;
};
"status-code-in-default-response": {
readonly default: "a default response should not have an explicit status code";
};
"invalid-schema": {
readonly default: import("@typespec/compiler").CallableMessage<["type"]>;
};
"union-null": {
readonly default: "Cannot have a union containing only null types.";
};
"empty-union": {
readonly default: "Empty unions are not supported for OpenAPI v3 - enums must have at least one value.";
};
"empty-enum": {
readonly default: "Empty enums are not supported for OpenAPI v3 - enums must have at least one value.";
};
"enum-unique-type": {
readonly default: "Enums are not supported unless all options are literals of the same type.";
};
"invalid-default": {
readonly default: import("@typespec/compiler").CallableMessage<["type"]>;
};
"inline-cycle": {
readonly default: import("@typespec/compiler").CallableMessage<["type"]>;
};
"unsupported-status-code-range": {
readonly default: import("@typespec/compiler").CallableMessage<["start", "end"]>;
};
"unsupported-auth": {
readonly default: import("@typespec/compiler").CallableMessage<["authType"]>;
};
}[C]>(program: import("@typespec/compiler").Program, diag: import("@typespec/compiler").DiagnosticReport<{

@@ -282,0 +392,0 @@ "oneof-union": {

2

dist/src/lib.js

@@ -180,3 +180,3 @@ import { createTypeSpecLibrary, paramMessage } from "@typespec/compiler";

export const $lib = createTypeSpecLibrary(libDef);
export const { reportDiagnostic, createStateSymbol } = $lib;
export const { createDiagnostic, reportDiagnostic, createStateSymbol } = $lib;
//# sourceMappingURL=lib.js.map

@@ -1,4 +0,15 @@

import { EmitContext, NewLine } from "@typespec/compiler";
import { EmitContext, NewLine, Program } from "@typespec/compiler";
import { FileType, OpenAPI3EmitterOptions } from "./lib.js";
import { OpenAPI3ServiceRecord } from "./types.js";
export declare function $onEmit(context: EmitContext<OpenAPI3EmitterOptions>): Promise<void>;
type IrrelevantOpenAPI3EmitterOptionsForObject = "file-type" | "output-file" | "new-line";
/**
* Get the OpenAPI 3 document records from the given program. The documents are
* returned as a JS object.
*
* @param program The program to emit to OpenAPI 3
* @param options OpenAPI 3 emit options
* @returns An array of OpenAPI 3 document records.
*/
export declare function getOpenAPI3(program: Program, options?: Omit<OpenAPI3EmitterOptions, IrrelevantOpenAPI3EmitterOptionsForObject>): Promise<OpenAPI3ServiceRecord[]>;
export declare function resolveOptions(context: EmitContext<OpenAPI3EmitterOptions>): ResolvedOpenAPI3EmitterOptions;

@@ -12,2 +23,3 @@ export interface ResolvedOpenAPI3EmitterOptions {

}
export {};
//# sourceMappingURL=openapi.d.ts.map

@@ -1,2 +0,3 @@

import { compilerAssert, emitFile, getAllTags, getAnyExtensionFromPath, getDoc, getEncode, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMaxValueExclusive, getMinItems, getMinLength, getMinValue, getMinValueExclusive, getNamespaceFullName, getPattern, getService, getSummary, ignoreDiagnostics, interpolatePath, isDeprecated, isGlobalNamespace, isNeverType, isSecret, isVoidType, listServices, navigateTypesInNamespace, projectProgram, resolvePath, } from "@typespec/compiler";
import { compilerAssert, createDiagnosticCollector, emitFile, getAllTags, getAnyExtensionFromPath, getDoc, getEncode, getFormat, getKnownValues, getMaxItems, getMaxLength, getMaxValue, getMaxValueExclusive, getMinItems, getMinLength, getMinValue, getMinValueExclusive, getNamespaceFullName, getPattern, getService, getSummary, ignoreDiagnostics, interpolatePath, isDeprecated, isGlobalNamespace, isNeverType, isSecret, isVoidType, listServices, navigateTypesInNamespace, projectProgram, resolvePath, } from "@typespec/compiler";
import { createAssetEmitter } from "@typespec/compiler/emitter-framework";
import { createMetadataInfo, getAuthentication, getHttpService, getServers, getStatusCodeDescription, isContentTypeHeader, isOverloadSameEndpoint, reportIfNoRoutes, resolveRequestVisibility, Visibility, } from "@typespec/http";

@@ -7,3 +8,3 @@ import { getExtensions, getExternalDocs, getInfo, getOpenAPITypeName, getParameterKey, isDefaultResponse, isReadonlyProperty, resolveOperationId, shouldInline, } from "@typespec/openapi";

import { getRef } from "./decorators.js";
import { reportDiagnostic } from "./lib.js";
import { createDiagnostic } from "./lib.js";
import { getDefaultValue, OpenAPI3SchemaEmitter } from "./schema-emitter.js";

@@ -23,2 +24,24 @@ import { deepEquals } from "./util.js";

}
/**
* Get the OpenAPI 3 document records from the given program. The documents are
* returned as a JS object.
*
* @param program The program to emit to OpenAPI 3
* @param options OpenAPI 3 emit options
* @returns An array of OpenAPI 3 document records.
*/
export async function getOpenAPI3(program, options = {}) {
const context = {
program,
// this value doesn't matter for getting the OpenAPI3 objects
emitterOutputDir: "tsp-output",
options: options,
getAssetEmitter(TypeEmitterClass) {
return createAssetEmitter(program, TypeEmitterClass, this);
},
};
const resolvedOptions = resolveOptions(context);
const emitter = createOAPIEmitter(context, resolvedOptions);
return emitter.getOpenAPI();
}
function findFileTypeFromFilename(filename) {

@@ -55,2 +78,3 @@ if (filename === undefined) {

let root;
let diagnostics;
let currentService;

@@ -79,3 +103,39 @@ // Get the service namespace string for use in name shortening

};
return { emitOpenAPI };
return { emitOpenAPI, getOpenAPI };
async function emitOpenAPI() {
const services = await getOpenAPI();
// first, emit diagnostics
for (const serviceRecord of services) {
if (serviceRecord.versioned) {
for (const documentRecord of serviceRecord.versions) {
program.reportDiagnostics(documentRecord.diagnostics);
}
}
else {
program.reportDiagnostics(serviceRecord.diagnostics);
}
}
if (program.compilerOptions.noEmit || program.hasError()) {
return;
}
const multipleService = services.length > 1;
for (const serviceRecord of services) {
if (serviceRecord.versioned) {
for (const documentRecord of serviceRecord.versions) {
await emitFile(program, {
path: resolveOutputFile(serviceRecord.service, multipleService, documentRecord.version),
content: serializeDocument(documentRecord.document, options.fileType),
newLine: options.newLine,
});
}
}
else {
await emitFile(program, {
path: resolveOutputFile(serviceRecord.service, multipleService),
content: serializeDocument(serviceRecord.document, options.fileType),
newLine: options.newLine,
});
}
}
}
function initializeEmitter(service, version) {

@@ -116,2 +176,3 @@ var _a, _b, _c;

};
diagnostics = createDiagnosticCollector();
const servers = getServers(program, service.type);

@@ -148,7 +209,7 @@ if (servers) {

if (!isValid) {
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "invalid-server-variable",
format: { propName: prop.name },
target: prop,
});
}));
}

@@ -189,3 +250,4 @@ return isValid;

}
async function emitOpenAPI() {
async function getOpenAPI() {
const serviceRecords = [];
const services = listServices(program);

@@ -196,2 +258,42 @@ if (services.length === 0) {

for (const service of services) {
const versions = buildVersionProjections(program, service.type);
if (versions.length === 1 && versions[0].version === undefined) {
// non-versioned spec
const document = await getProjectedOpenAPIDocument(service, versions[0]);
if (document === undefined) {
// an error occurred producing this document, so don't return it
return serviceRecords;
}
serviceRecords.push({
service,
versioned: false,
document: document[0],
diagnostics: document[1],
});
}
else {
// versioned spec
const serviceRecord = {
service,
versioned: true,
versions: [],
};
serviceRecords.push(serviceRecord);
for (const record of versions) {
const document = await getProjectedOpenAPIDocument(service, record);
if (document === undefined) {
// an error occurred producing this document
continue;
}
serviceRecord.versions.push({
service,
version: record.version,
document: document[0],
diagnostics: document[1],
});
}
}
}
return serviceRecords;
async function getProjectedOpenAPIDocument(service, record) {
const commonProjections = [

@@ -204,13 +306,11 @@ {

const originalProgram = program;
const versions = buildVersionProjections(program, service.type);
for (const record of versions) {
const projectedProgram = (program = projectProgram(originalProgram, [
...commonProjections,
...record.projections,
]));
const projectedServiceNs = projectedProgram.projector.projectedTypes.get(service.type);
await emitOpenAPIFromVersion(projectedServiceNs === projectedProgram.getGlobalNamespaceType()
? { type: projectedProgram.getGlobalNamespaceType() }
: getService(program, projectedServiceNs), services.length > 1, record.version);
}
const projectedProgram = (program = projectProgram(originalProgram, [
...commonProjections,
...record.projections,
]));
const projectedServiceNs = projectedProgram.projector.projectedTypes.get(service.type);
const document = await getOpenApiFromVersion(projectedServiceNs === projectedProgram.getGlobalNamespaceType()
? { type: projectedProgram.getGlobalNamespaceType() }
: getService(program, projectedServiceNs), record.version);
return document;
}

@@ -309,7 +409,7 @@ }

function rangeToOpenAPI(range, diagnosticTarget) {
const reportInvalid = () => reportDiagnostic(program, {
const reportInvalid = () => diagnostics.add(createDiagnostic({
code: "unsupported-status-code-range",
format: { start: String(range.start), end: String(range.end) },
target: diagnosticTarget,
});
}));
const codes = [];

@@ -426,3 +526,3 @@ let start = range.start;

}
async function emitOpenAPIFromVersion(service, multipleService, version) {
async function getOpenApiFromVersion(service, version) {
initializeEmitter(service, version);

@@ -451,10 +551,3 @@ try {

}
if (!program.compilerOptions.noEmit && !program.hasError()) {
// Write out the OpenAPI document to the output path
await emitFile(program, {
path: resolveOutputFile(service, multipleService, version),
content: serializeDocument(root, options.fileType),
newLine: options.newLine,
});
}
return [root, diagnostics.diagnostics];
}

@@ -525,6 +618,6 @@ catch (err) {

if (visibilities.some((v) => v !== visibilities[0])) {
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "inconsistent-shared-route-request-visibility",
target: ops[0],
});
}));
}

@@ -553,3 +646,3 @@ const visibility = resolveRequestVisibility(program, shared.operations[0], verb);

if (fullPath.indexOf("?") > 0) {
reportDiagnostic(program, { code: "path-query", target: op });
diagnostics.add(createDiagnostic({ code: "path-query", target: op }));
return;

@@ -653,7 +746,7 @@ }

if (!deepEquals(existing, headerVal)) {
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "duplicate-header",
format: { header: key },
target: target,
});
}));
}

@@ -717,7 +810,7 @@ continue;

case "circular":
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "inline-cycle",
format: { type: getOpenAPITypeName(program, type, typeNameOptions) },
target: type,
});
}));
return {};

@@ -735,7 +828,7 @@ case "none":

case "circular":
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "inline-cycle",
format: { type: getOpenAPITypeName(program, type, typeNameOptions) },
target: type,
});
}));
return {};

@@ -949,3 +1042,3 @@ case "none":

default:
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "invalid-format",

@@ -957,3 +1050,3 @@ format: {

target: parameter.param,
});
}));
return undefined;

@@ -977,3 +1070,3 @@ }

default:
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "invalid-format",

@@ -985,3 +1078,3 @@ format: {

target: parameter.param,
});
}));
return undefined;

@@ -1213,7 +1306,7 @@ }

default:
reportDiagnostic(program, {
diagnostics.add(createDiagnostic({
code: "unsupported-auth",
format: { authType: auth.type },
target: currentService.type,
});
}));
return undefined;

@@ -1220,0 +1313,0 @@ }

@@ -0,1 +1,2 @@

import { Diagnostic, Service } from "@typespec/compiler";
import { ExtensionKey } from "@typespec/openapi";

@@ -32,2 +33,38 @@ export type Extensions = {

}
/**
* A record containing the the OpenAPI 3 documents corresponding to
* a particular service definition.
*/
export type OpenAPI3ServiceRecord = OpenAPI3UnversionedServiceRecord | OpenAPI3VersionedServiceRecord;
export interface OpenAPI3UnversionedServiceRecord {
/** The service that generated this OpenAPI document */
readonly service: Service;
/** Whether the service is versioned */
readonly versioned: false;
/** The OpenAPI 3 document */
readonly document: OpenAPI3Document;
/** The diagnostics created for this document */
readonly diagnostics: readonly Diagnostic[];
}
export interface OpenAPI3VersionedServiceRecord {
/** The service that generated this OpenAPI document */
readonly service: Service;
/** Whether the service is versioned */
readonly versioned: true;
/** The OpenAPI 3 document records for each version of this service */
readonly versions: OpenAPI3VersionedDocumentRecord[];
}
/**
* A record containing an unversioned OpenAPI document and associated metadata.
*/
export interface OpenAPI3VersionedDocumentRecord {
/** The OpenAPI document*/
readonly document: OpenAPI3Document;
/** The service that generated this OpenAPI document. */
readonly service: Service;
/** The version of the service. Absent if the service is unversioned. */
readonly version: string;
/** The diagnostics created for this version. */
readonly diagnostics: readonly Diagnostic[];
}
export interface OpenAPI3Info extends Extensions {

@@ -34,0 +71,0 @@ title: string;

{
"name": "@typespec/openapi3",
"version": "0.54.0-dev.4",
"version": "0.54.0-dev.5",
"author": "Microsoft Corporation",

@@ -5,0 +5,0 @@ "description": "TypeSpec library for emitting OpenAPI 3.0 from the TypeSpec REST protocol binding",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc