Skip to content

Commit 18a4c3f

Browse files
authored
Stop using rest-api-spec (#5831)
* Remove reAddAvailability function * Remove jsonSpec as a global variable This makes it easier to spot functions that use it. * Stop reading endpoints from jsonSpec * Stop reading docUrl, docTag, extDocUrl, requestBodyRequired and availability from rest-api-spec * Stop reading description and urls from rest-api-spec * Stop validating rest-api-spec * Stop using jsonSpec in compilation steps * Stop using rest-api-spec altogether * Fix compiler tests
1 parent 6caf375 commit 18a4c3f

File tree

23 files changed

+69
-526
lines changed

23 files changed

+69
-526
lines changed

compiler/src/compiler.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,10 @@ import { writeFile, mkdir } from 'fs/promises'
2121
import { join } from 'path'
2222
import stringify from 'safe-stable-stringify'
2323
import { Model } from './model/metamodel'
24-
import {
25-
compileEndpoints,
26-
compileSpecification,
27-
reAddAvailability
28-
} from './model/build-model'
29-
import buildJsonSpec, { JsonSpec } from './model/json-spec'
24+
import { compileSpecification } from './model/build-model'
3025
import { ValidationErrors } from './validation-errors'
3126

32-
type StepFunction = (model: Model, restSpec: Map<string, JsonSpec>, errors: ValidationErrors) => Promise<Model>
27+
type StepFunction = (model: Model, errors: ValidationErrors) => Promise<Model>
3328

3429
/**
3530
* The main job of the compiler is to generate the Model and write it on disk.
@@ -42,7 +37,6 @@ type StepFunction = (model: Model, restSpec: Map<string, JsonSpec>, errors: Vali
4237
export default class Compiler {
4338
queue: StepFunction[]
4439
model: Model
45-
jsonSpec: Map<string, JsonSpec>
4640
errors: ValidationErrors
4741
specsFolder: string
4842
outputFolder: string
@@ -55,16 +49,13 @@ export default class Compiler {
5549
}
5650

5751
generateModel (): this {
58-
this.jsonSpec = buildJsonSpec()
59-
const endpoints = compileEndpoints()
60-
this.model = compileSpecification(endpoints, this.specsFolder, this.outputFolder)
61-
this.model = reAddAvailability(this.model) // resync availability information based on json spec if typescript has none.
52+
this.model = compileSpecification(this.specsFolder, this.outputFolder)
6253
return this
6354
}
6455

6556
async write (): Promise<void> {
6657
for (const step of this.queue) {
67-
this.model = await step(this.model, this.jsonSpec, this.errors)
58+
this.model = await step(this.model, this.errors)
6859
}
6960

7061
const customStringify = stringify.configure(

compiler/src/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ import { readFileSync, existsSync, lstatSync } from 'fs'
2121
import { join, resolve } from 'path'
2222
import { argv } from 'zx'
2323
import Compiler from './compiler'
24-
import validateRestSpec from './steps/validate-rest-spec'
2524
import addInfo from './steps/add-info'
26-
import addDescription from './steps/add-description'
2725
import validateModel from './steps/validate-model'
2826
import readDefinitionValidation from './steps/read-definition-validation'
2927
import addDeprecation from './steps/add-deprecation'
@@ -73,8 +71,6 @@ compiler
7371
.step(addInfo)
7472
.step(addDeprecation)
7573
.step(readDefinitionValidation)
76-
.step(validateRestSpec)
77-
.step(addDescription)
7874
.step(validateModel)
7975
.step(addExamples)
8076
.write()

compiler/src/model/build-model.ts

Lines changed: 13 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
TypeAliasDeclaration
3333
} from 'ts-morph'
3434
import * as model from './metamodel'
35-
import buildJsonSpec from './json-spec'
3635
import {
3736
assert,
3837
customTypes,
@@ -57,62 +56,10 @@ import {
5756
mediaTypeToStringArray
5857
} from './utils'
5958

60-
const jsonSpec = buildJsonSpec()
61-
62-
export function reAddAvailability (model: model.Model): model.Model {
63-
for (const [api, spec] of jsonSpec.entries()) {
64-
for (const endpoint of model.endpoints) {
65-
if (endpoint.name === api) {
66-
if ((spec.stability != null || spec.visibility != null) && (endpoint.availability.stack === undefined && endpoint.availability.serverless === undefined)) {
67-
endpoint.availability = {
68-
stack: {
69-
stability: spec.stability,
70-
visibility: spec.visibility
71-
}
72-
}
73-
}
74-
}
75-
}
76-
}
77-
return model
78-
}
79-
80-
export function compileEndpoints (): Record<string, model.Endpoint> {
81-
// Create endpoints and merge them with
82-
// the recorded mappings if present.
83-
const map = {}
84-
for (const [api, spec] of jsonSpec.entries()) {
85-
map[api] = {
86-
name: api,
87-
description: spec.documentation.description,
88-
docUrl: spec.documentation.url,
89-
docTag: spec.docTag,
90-
extDocUrl: spec.externalDocs?.url,
91-
// Setting these values by default should be removed
92-
// when we no longer use rest-api-spec stubs as the
93-
// source of truth for stability/visibility.
94-
availability: {},
95-
request: null,
96-
requestBodyRequired: Boolean(spec.body?.required),
97-
response: null,
98-
urls: spec.url.paths.map(path => {
99-
return {
100-
path: path.path,
101-
methods: path.methods,
102-
...(path.deprecated != null && { deprecation: path.deprecated })
103-
}
104-
})
105-
}
106-
if (typeof spec.feature_flag === 'string') {
107-
map[api].availability.stack = { featureFlag: spec.feature_flag }
108-
}
109-
}
110-
return map
111-
}
112-
113-
export function compileSpecification (endpointMappings: Record<string, model.Endpoint>, specsFolder: string, outputFolder: string): model.Model {
59+
export function compileSpecification (specsFolder: string, outputFolder: string): model.Model {
11460
const tsConfigFilePath = join(specsFolder, 'tsconfig.json')
11561
const project = new Project({ tsConfigFilePath })
62+
const endpointMappings: Record<string, model.Endpoint> = {}
11663

11764
verifyUniqueness(project)
11865

@@ -151,9 +98,6 @@ export function compileSpecification (endpointMappings: Record<string, model.End
15198
definedButNeverUsed.join('\n'),
15299
{ encoding: 'utf8', flag: 'w' }
153100
)
154-
for (const api of jsonSpec.keys()) {
155-
model.endpoints.push(endpointMappings[api])
156-
}
157101

158102
// Visit all class, interface, enum and type alias definitions
159103
for (const declaration of declarations.classes) {
@@ -175,6 +119,11 @@ export function compileSpecification (endpointMappings: Record<string, model.End
175119
// Sort the types in alphabetical order
176120
sortTypeDefinitions(model.types)
177121

122+
const sortedEndpointKeys = Object.keys(endpointMappings).sort()
123+
for (const key of sortedEndpointKeys) {
124+
model.endpoints.push(endpointMappings[key])
125+
}
126+
178127
return model
179128
}
180129

@@ -225,6 +174,10 @@ function compileClassOrInterfaceDeclaration (declaration: ClassDeclaration | Int
225174
throw new Error(`Cannot find url template for ${namespace}, very likely the specification folder does not follow the rest-api-spec`)
226175
}
227176

177+
if (type.description !== '' && type.description !== null && type.description !== undefined) {
178+
mapping.description = type.description
179+
}
180+
228181
let pathMember: Node | null = null
229182
let bodyProperties: model.Property[] = []
230183
let bodyValue: model.ValueOf | null = null
@@ -288,7 +241,7 @@ function compileClassOrInterfaceDeclaration (declaration: ClassDeclaration | Int
288241
assert(
289242
pathMember as Node,
290243
urlTemplateParams.includes(part.name),
291-
`The property '${part.name}' does not exist in the rest-api-spec ${namespace} url template`
244+
`The property '${part.name}' does not exist in the url template`
292245
)
293246
if (type.query.map(p => p.name).includes(part.name)) {
294247
const queryType = type.query.find(property => property != null && property.name === part.name) as model.Property
@@ -636,7 +589,7 @@ function visitRequestOrResponseProperty (member: PropertyDeclaration | PropertyS
636589
* ```
637590
* urls: [
638591
* {
639-
* /** @deprecated 1.2.3 Use something else
592+
* /** \@deprecated 1.2.3 Use something else
640593
* path: '/some/path',
641594
* methods: ["GET", "POST"]
642595
* }

compiler/src/model/json-spec.ts

Lines changed: 0 additions & 84 deletions
This file was deleted.

compiler/src/model/utils.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import {
3535
Node,
3636
Project
3737
} from 'ts-morph'
38-
import { closest } from 'fastest-levenshtein'
3938
import semver from 'semver'
4039
import chalk from 'chalk'
4140
import * as model from './metamodel'
@@ -629,6 +628,23 @@ function setTags<TType extends model.BaseType | model.Property | model.EnumMembe
629628
}
630629
}
631630

631+
export function updateEndpoints (mappings: Record<string, model.Endpoint>, name: string): model.Endpoint {
632+
mappings[name] = {
633+
name: name,
634+
// @ts-expect-error TODO
635+
description: null,
636+
// @ts-expect-error TODO
637+
docUrl: null,
638+
request: null,
639+
requestBodyRequired: false,
640+
response: null,
641+
urls: []
642+
}
643+
mappings[name].availability = {}
644+
645+
return mappings[name]
646+
}
647+
632648
/** Lifts jsDoc type annotations to request properties */
633649
export function hoistRequestAnnotations (
634650
request: model.Request, jsDocs: JSDoc[], mappings: Record<string, model.Endpoint>, response: model.TypeName | null
@@ -651,9 +667,7 @@ export function hoistRequestAnnotations (
651667
assert(jsDocs, apiName !== '' && apiName !== null && apiName !== undefined,
652668
`Request ${request.name.name} does not declare the @rest_spec_name to link back to`)
653669

654-
const endpoint = mappings[apiName]
655-
assert(jsDocs, endpoint != null, `The api '${apiName}' does not exists, did you mean '${closest(apiName, Object.keys(mappings))}'?`)
656-
670+
const endpoint = updateEndpoints(mappings, apiName)
657671
endpoint.request = request.name
658672
endpoint.response = response
659673

compiler/src/steps/add-deprecation.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818
*/
1919

2020
import * as model from '../model/metamodel'
21-
import { JsonSpec } from '../model/json-spec'
2221

2322
/**
2423
* Populates the `deprecation` field for endpoints from the value of the corresponding request definition.
2524
*/
26-
export default async function addContentType (model: model.Model, jsonSpec: Map<string, JsonSpec>): Promise<model.Model> {
25+
export default async function addContentType (model: model.Model): Promise<model.Model> {
2726
for (const endpoint of model.endpoints) {
2827
if (endpoint.deprecation != null) {
2928
continue

compiler/src/steps/add-description.ts

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)