From b5f8aa89b8dec9716011bfea77ec50707524fa3f Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Thu, 23 Jul 2020 14:42:56 +0200 Subject: [PATCH 01/26] feat(catalog): add entity to describe APIs --- .../software-catalog/descriptor-format.md | 75 ++++++ .../examples/hello-world-api.yaml | 46 ++++ .../catalog-model/examples/petstore-api.yaml | 119 ++++++++++ .../examples/streetlights-api.yaml | 217 ++++++++++++++++++ packages/catalog-model/src/EntityPolicies.ts | 2 + .../src/kinds/ApiEntityV1alpha1.test.ts | 126 ++++++++++ .../src/kinds/ApiEntityV1alpha1.ts | 52 +++++ packages/catalog-model/src/kinds/index.ts | 5 + 8 files changed, 642 insertions(+) create mode 100644 packages/catalog-model/examples/hello-world-api.yaml create mode 100644 packages/catalog-model/examples/petstore-api.yaml create mode 100644 packages/catalog-model/examples/streetlights-api.yaml create mode 100644 packages/catalog-model/src/kinds/ApiEntityV1alpha1.test.ts create mode 100644 packages/catalog-model/src/kinds/ApiEntityV1alpha1.ts diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 68cee2352c..a99ce40e25 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -14,6 +14,8 @@ humans. However, the structure and semantics is the same in both cases. - [Common to All Kinds: The Envelope](#common-to-all-kinds-the-envelope) - [Common to All Kinds: The Metadata](#common-to-all-kinds-the-metadata) - [Kind: Component](#kind-component) +- [Kind: Template](#kind-template) +- [Kind: API](#kind-api) ## Overall Shape Of An Entity @@ -422,3 +424,76 @@ specify relative to the `template.yaml` definition. This is also particularly useful when you have multiple template definitions in the same repository but only a single `template.yaml` registered in backstage. + +## Kind: API + +Describes the following entity kind: + +| Field | Value | +| ------------ | ----------------------- | +| `apiVersion` | `backstage.io/v1alpha1` | +| `kind` | `API` | + +An API describes an interface that can be exposed by a component. The API can be +defined in different formats, like [OpenAPI](https://swagger.io/specification/), +[AsyncAPI](https://www.asyncapi.com/docs/specifications/latest/), +[gRPC](https://developers.google.com/protocol-buffers), or other formats. + +Descriptor files for this kind may look as follows. + +```yaml +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: artist-api + description: Retrieve artist details +spec: + type: openapi + definition: | + openapi: "3.0.0" + info: + version: 1.0.0 + title: Artist API + license: + name: MIT + servers: + - url: http://artist.spotify.net/v1 + paths: + /artists: + get: + summary: List all artists + ... +``` + +In addition to the [common envelope metadata](#common-to-all-kinds-the-metadata) +shape, this kind has the following structure. + +### `apiVersion` and `kind` [required] + +Exactly equal to `backstage.io/v1alpha1` and `API`, respectively. + +### `spec.type` [required] + +The type of the API definition as a string, e.g. `openapi`. This field is +required. + +The software catalog accepts any type value, but an organisation should take +great care to establish a proper taxonomy for these. Tools including Backstage +itself may read this field and behave differently depending on its value. For +example, an OpenAPI type API may be displayed using an OpenAPI viewer tooling in +the Backstage interface. + +The current set of well-known and common values for this field is: + +- `openapi` - An API definition in YAML or JSON format based on the + [OpenAPI](https://swagger.io/specification/) version 2 or version 3 spec. +- `asyncapi` - An API definition based on the + [AsyncAPI](https://www.asyncapi.com/docs/specifications/latest/) spec. +- `grpc` - An API definition based on + [Protocol Buffers](https://developers.google.com/protocol-buffers) to use with + [gRPC](https://grpc.io/). + +### `spec.definition` [required] + +The definition of the API, based on the format defined by `spec.type`. This +field is required. diff --git a/packages/catalog-model/examples/hello-world-api.yaml b/packages/catalog-model/examples/hello-world-api.yaml new file mode 100644 index 0000000000..298b0cb835 --- /dev/null +++ b/packages/catalog-model/examples/hello-world-api.yaml @@ -0,0 +1,46 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: hello-world + description: Hello World example for gRPC +spec: + type: grpc + definition: | + // Copyright 2015 gRPC authors. + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. + // You may obtain a copy of the License at + // + // http://www.apache.org/licenses/LICENSE-2.0 + // + // Unless required by applicable law or agreed to in writing, software + // distributed under the License is distributed on an "AS IS" BASIS, + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + // See the License for the specific language governing permissions and + // limitations under the License. + + syntax = "proto3"; + + option java_multiple_files = true; + option java_package = "io.grpc.examples.helloworld"; + option java_outer_classname = "HelloWorldProto"; + option objc_class_prefix = "HLW"; + + package helloworld; + + // The greeting service definition. + service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} + } + + // The request message containing the user's name. + message HelloRequest { + string name = 1; + } + + // The response message containing the greetings + message HelloReply { + string message = 1; + } diff --git a/packages/catalog-model/examples/petstore-api.yaml b/packages/catalog-model/examples/petstore-api.yaml new file mode 100644 index 0000000000..01953a4a97 --- /dev/null +++ b/packages/catalog-model/examples/petstore-api.yaml @@ -0,0 +1,119 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: petstore + description: The petstore API +spec: + type: openapi + definition: | + openapi: "3.0.0" + info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT + servers: + - url: http://petstore.swagger.io/v1 + paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + post: + summary: Create a pet + operationId: createPets + tags: + - pets + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + components: + schemas: + Pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/packages/catalog-model/examples/streetlights-api.yaml b/packages/catalog-model/examples/streetlights-api.yaml new file mode 100644 index 0000000000..69a6d101cb --- /dev/null +++ b/packages/catalog-model/examples/streetlights-api.yaml @@ -0,0 +1,217 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: streetlights + description: The Smartylighting Streetlights API allows you to remotely manage the city lights. +spec: + type: asyncapi + definition: | + asyncapi: 2.0.0 + info: + title: Streetlights API + version: '1.0.0' + description: | + The Smartylighting Streetlights API allows you to remotely manage the city lights. + + ### Check out its awesome features: + + * Turn a specific streetlight on/off 🌃 + * Dim a specific streetlight šŸ˜Ž + * Receive real-time information about environmental lighting conditions šŸ“ˆ + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 + + servers: + production: + url: api.streetlights.smartylighting.com:{port} + protocol: mqtt + description: Test broker + variables: + port: + description: Secure connection (TLS) is available through port 8883. + default: '1883' + enum: + - '1883' + - '8883' + security: + - apiKey: [] + - supportedOauthFlows: + - streetlights:on + - streetlights:off + - streetlights:dim + - openIdConnectWellKnown: [] + + defaultContentType: application/json + + channels: + smartylighting/streetlights/1/0/event/{streetlightId}/lighting/measured: + description: The topic on which measured values may be produced and consumed. + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + subscribe: + summary: Receive information about environmental lighting conditions of a particular streetlight. + operationId: receiveLightMeasurement + traits: + - $ref: '#/components/operationTraits/kafka' + message: + $ref: '#/components/messages/lightMeasured' + + smartylighting/streetlights/1/0/action/{streetlightId}/turn/on: + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + publish: + operationId: turnOn + traits: + - $ref: '#/components/operationTraits/kafka' + message: + $ref: '#/components/messages/turnOnOff' + + smartylighting/streetlights/1/0/action/{streetlightId}/turn/off: + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + publish: + operationId: turnOff + traits: + - $ref: '#/components/operationTraits/kafka' + message: + $ref: '#/components/messages/turnOnOff' + + smartylighting/streetlights/1/0/action/{streetlightId}/dim: + parameters: + streetlightId: + $ref: '#/components/parameters/streetlightId' + publish: + operationId: dimLight + traits: + - $ref: '#/components/operationTraits/kafka' + message: + $ref: '#/components/messages/dimLight' + + components: + messages: + lightMeasured: + name: lightMeasured + title: Light measured + summary: Inform about environmental lighting conditions for a particular streetlight. + contentType: application/json + traits: + - $ref: '#/components/messageTraits/commonHeaders' + payload: + $ref: "#/components/schemas/lightMeasuredPayload" + turnOnOff: + name: turnOnOff + title: Turn on/off + summary: Command a particular streetlight to turn the lights on or off. + traits: + - $ref: '#/components/messageTraits/commonHeaders' + payload: + $ref: "#/components/schemas/turnOnOffPayload" + dimLight: + name: dimLight + title: Dim light + summary: Command a particular streetlight to dim the lights. + traits: + - $ref: '#/components/messageTraits/commonHeaders' + payload: + $ref: "#/components/schemas/dimLightPayload" + + schemas: + lightMeasuredPayload: + type: object + properties: + lumens: + type: integer + minimum: 0 + description: Light intensity measured in lumens. + sentAt: + $ref: "#/components/schemas/sentAt" + turnOnOffPayload: + type: object + properties: + command: + type: string + enum: + - on + - off + description: Whether to turn on or off the light. + sentAt: + $ref: "#/components/schemas/sentAt" + dimLightPayload: + type: object + properties: + percentage: + type: integer + description: Percentage to which the light should be dimmed to. + minimum: 0 + maximum: 100 + sentAt: + $ref: "#/components/schemas/sentAt" + sentAt: + type: string + format: date-time + description: Date and time when the message was sent. + + securitySchemes: + apiKey: + type: apiKey + in: user + description: Provide your API key as the user and leave the password empty. + supportedOauthFlows: + type: oauth2 + description: Flows to support OAuth 2.0 + flows: + implicit: + authorizationUrl: 'https://authserver.example/auth' + scopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + password: + tokenUrl: 'https://authserver.example/token' + scopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + clientCredentials: + tokenUrl: 'https://authserver.example/token' + scopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + authorizationCode: + authorizationUrl: 'https://authserver.example/auth' + tokenUrl: 'https://authserver.example/token' + refreshUrl: 'https://authserver.example/refresh' + scopes: + 'streetlights:on': Ability to switch lights on + 'streetlights:off': Ability to switch lights off + 'streetlights:dim': Ability to dim the lights + openIdConnectWellKnown: + type: openIdConnect + openIdConnectUrl: 'https://authserver.example/.well-known' + + parameters: + streetlightId: + description: The ID of the streetlight. + schema: + type: string + + messageTraits: + commonHeaders: + headers: + type: object + properties: + my-app-header: + type: integer + minimum: 0 + maximum: 100 + + operationTraits: + kafka: + bindings: + kafka: + clientId: my-app-id diff --git a/packages/catalog-model/src/EntityPolicies.ts b/packages/catalog-model/src/EntityPolicies.ts index 3dc7deae7c..6bebd877d7 100644 --- a/packages/catalog-model/src/EntityPolicies.ts +++ b/packages/catalog-model/src/EntityPolicies.ts @@ -23,6 +23,7 @@ import { SchemaValidEntityPolicy, } from './entity'; import { + ApiEntityV1alpha1Policy, ComponentEntityV1alpha1Policy, LocationEntityV1alpha1Policy, TemplateEntityV1alpha1Policy, @@ -76,6 +77,7 @@ export class EntityPolicies implements EntityPolicy { new ComponentEntityV1alpha1Policy(), new LocationEntityV1alpha1Policy(), new TemplateEntityV1alpha1Policy(), + new ApiEntityV1alpha1Policy(), ]), ]); } diff --git a/packages/catalog-model/src/kinds/ApiEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ApiEntityV1alpha1.test.ts new file mode 100644 index 0000000000..48de569213 --- /dev/null +++ b/packages/catalog-model/src/kinds/ApiEntityV1alpha1.test.ts @@ -0,0 +1,126 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { EntityPolicy } from '../types'; +import { + ApiEntityV1alpha1, + ApiEntityV1alpha1Policy, +} from './ApiEntityV1alpha1'; + +describe('ApiV1alpha1Policy', () => { + let entity: ApiEntityV1alpha1; + let policy: EntityPolicy; + + beforeEach(() => { + entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'test', + }, + spec: { + type: 'openapi', + definition: ` +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore +paths: + /pets: + get: + summary: List all pets + operationId: listPets + responses: + '200': + description: A paged array of pets + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" +components: + schemas: + Pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Pets: + type: array + items: + $ref: "#/components/schemas/Pet" +`, + }, + }; + policy = new ApiEntityV1alpha1Policy(); + }); + + it('happy path: accepts valid data', async () => { + await expect(policy.enforce(entity)).resolves.toBe(entity); + }); + + it('silently accepts v1beta1 as well', async () => { + (entity as any).apiVersion = 'backstage.io/v1beta1'; + await expect(policy.enforce(entity)).resolves.toBe(entity); + }); + + it('rejects unknown apiVersion', async () => { + (entity as any).apiVersion = 'backstage.io/v1beta0'; + await expect(policy.enforce(entity)).rejects.toThrow(/apiVersion/); + }); + + it('rejects unknown kind', async () => { + (entity as any).kind = 'Wizard'; + await expect(policy.enforce(entity)).rejects.toThrow(/kind/); + }); + + it('rejects missing type', async () => { + delete (entity as any).spec.type; + await expect(policy.enforce(entity)).rejects.toThrow(/type/); + }); + + it('rejects wrong type', async () => { + (entity as any).spec.type = 7; + await expect(policy.enforce(entity)).rejects.toThrow(/type/); + }); + + it('rejects empty type', async () => { + (entity as any).spec.type = ''; + await expect(policy.enforce(entity)).rejects.toThrow(/type/); + }); + + it('rejects missing definition', async () => { + delete (entity as any).spec.definition; + await expect(policy.enforce(entity)).rejects.toThrow(/definition/); + }); + + it('rejects wrong definition', async () => { + (entity as any).spec.definition = 7; + await expect(policy.enforce(entity)).rejects.toThrow(/definition/); + }); + + it('rejects empty definition', async () => { + (entity as any).spec.definition = ''; + await expect(policy.enforce(entity)).rejects.toThrow(/definition/); + }); +}); diff --git a/packages/catalog-model/src/kinds/ApiEntityV1alpha1.ts b/packages/catalog-model/src/kinds/ApiEntityV1alpha1.ts new file mode 100644 index 0000000000..59e16df9a7 --- /dev/null +++ b/packages/catalog-model/src/kinds/ApiEntityV1alpha1.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as yup from 'yup'; +import type { Entity } from '../entity/Entity'; +import type { EntityPolicy } from '../types'; + +const API_VERSION = ['backstage.io/v1alpha1', 'backstage.io/v1beta1'] as const; +const KIND = 'API' as const; + +export interface ApiEntityV1alpha1 extends Entity { + apiVersion: typeof API_VERSION[number]; + kind: typeof KIND; + spec: { + type: string; + definition: string; + }; +} + +export class ApiEntityV1alpha1Policy implements EntityPolicy { + private schema: yup.Schema; + + constructor() { + this.schema = yup.object>({ + apiVersion: yup.string().required().oneOf(API_VERSION), + kind: yup.string().required().equals([KIND]), + spec: yup + .object({ + type: yup.string().required().min(1), + definition: yup.string().required().min(1), + }) + .required(), + }); + } + + async enforce(envelope: Entity): Promise { + return await this.schema.validate(envelope, { strict: true }); + } +} diff --git a/packages/catalog-model/src/kinds/index.ts b/packages/catalog-model/src/kinds/index.ts index b5fad184d4..2ecddcbf85 100644 --- a/packages/catalog-model/src/kinds/index.ts +++ b/packages/catalog-model/src/kinds/index.ts @@ -29,3 +29,8 @@ export type { TemplateEntityV1alpha1 as TemplateEntity, TemplateEntityV1alpha1, } from './TemplateEntityV1alpha1'; +export { ApiEntityV1alpha1Policy } from './ApiEntityV1alpha1'; +export type { + ApiEntityV1alpha1 as ApiEntity, + ApiEntityV1alpha1, +} from './ApiEntityV1alpha1'; From 7c9e84bd1d8db592c657bdc3e619ebe0ffa28e87 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 09:06:09 +0200 Subject: [PATCH 02/26] feat(catalog): add field to the component entity to specify implemented apis per component --- docs/features/software-catalog/descriptor-format.md | 10 ++++++++++ .../catalog-model/examples/petstore-component.yaml | 13 +++++++++++++ .../src/kinds/ComponentEntityV1alpha1.test.ts | 1 + .../src/kinds/ComponentEntityV1alpha1.ts | 2 ++ 4 files changed, 26 insertions(+) create mode 100644 packages/catalog-model/examples/petstore-component.yaml diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index a99ce40e25..ba542d0fd1 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -254,6 +254,8 @@ spec: type: website lifecycle: production owner: artist-relations@example.com + implementsApis: + - artist-api ``` In addition to the [common envelope metadata](#common-to-all-kinds-the-metadata) @@ -314,6 +316,14 @@ Apart from being a string, the software catalog leaves the format of this field open to implementers to choose. Most commonly, it is set to the ID or email of a group of people in an organizational structure. +### `spec.implementsApis` [optional] + +Links APIs that are implemented by the component, e.g. `artist-api`. This field +is optional. + +The software catalog expects a list of one or more strings that references the +names of other entities of the `kind` `API`. + ## Kind: Template Describes the following entity kind: diff --git a/packages/catalog-model/examples/petstore-component.yaml b/packages/catalog-model/examples/petstore-component.yaml new file mode 100644 index 0000000000..5cf0d1f270 --- /dev/null +++ b/packages/catalog-model/examples/petstore-component.yaml @@ -0,0 +1,13 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: petstore + description: Petstore +spec: + type: service + lifecycle: experimental + owner: pets@example.com + implementedApis: + - petstore + - streetlights + - hello-world diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts index a60bb2606b..e784934d48 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.test.ts @@ -35,6 +35,7 @@ describe('ComponentV1alpha1Policy', () => { type: 'service', lifecycle: 'production', owner: 'me', + implementsApis: ['api-0'], }, }; policy = new ComponentEntityV1alpha1Policy(); diff --git a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts index 68cf0c61bb..38b9c27720 100644 --- a/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts +++ b/packages/catalog-model/src/kinds/ComponentEntityV1alpha1.ts @@ -28,6 +28,7 @@ export interface ComponentEntityV1alpha1 extends Entity { type: string; lifecycle: string; owner: string; + implementsApis?: string[]; }; } @@ -43,6 +44,7 @@ export class ComponentEntityV1alpha1Policy implements EntityPolicy { type: yup.string().required().min(1), lifecycle: yup.string().required().min(1), owner: yup.string().required().min(1), + implementsApis: yup.array(yup.string()).notRequired(), }) .required(), }); From f33c3dba214a948cf83bf5cfb221fb9cf7eb8472 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Fri, 24 Jul 2020 12:04:02 +0200 Subject: [PATCH 03/26] chore(catalog): add script to add the example entities --- plugins/catalog-backend/package.json | 3 ++- plugins/catalog-backend/scripts/mock-data-local.sh | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100755 plugins/catalog-backend/scripts/mock-data-local.sh diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 2445ee206e..0fd55126d8 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -18,7 +18,8 @@ "prepack": "backstage-cli prepack", "postpack": "backstage-cli postpack", "clean": "backstage-cli clean", - "mock-data": "./scripts/mock-data.sh" + "mock-data": "./scripts/mock-data.sh", + "mock-data:local": "./scripts/mock-data-local.sh" }, "dependencies": { "@backstage/backend-common": "^0.1.1-alpha.18", diff --git a/plugins/catalog-backend/scripts/mock-data-local.sh b/plugins/catalog-backend/scripts/mock-data-local.sh new file mode 100755 index 0000000000..3bea819319 --- /dev/null +++ b/plugins/catalog-backend/scripts/mock-data-local.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +for FILE in \ + ../../packages/catalog-model/examples/*.yaml \ +; do \ + curl \ + --location \ + --request POST 'localhost:7000/catalog/locations' \ + --header 'Content-Type: application/json' \ + --data-raw "{\"type\": \"file\", \"target\": \"../catalog-model/${FILE}\"}" + echo +done From 812659c024ba06fbe8c277519cae2b2517f4ad99 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 16:10:32 +0200 Subject: [PATCH 04/26] feat(api-docs): add plugin that provides widgets that display api docs --- plugins/api-docs/.eslintrc.js | 3 + plugins/api-docs/README.md | 9 +++ plugins/api-docs/dev/index.tsx | 20 +++++++ plugins/api-docs/package.json | 53 ++++++++++++++++++ .../ApiDefinitionCard/ApiDefinitionCard.tsx | 34 +++++++++++ .../ApiDefinitionWidget.tsx | 32 +++++++++++ .../CatalogApiPluginPage.test.tsx | 34 +++++++++++ .../CatalogApiPluginPage.tsx | 56 +++++++++++++++++++ .../components/CatalogApiPluginPage/index.ts | 17 ++++++ .../OpenApiDefinitionWidget.tsx | 41 ++++++++++++++ .../PlainApiDefinitionWidget.tsx | 24 ++++++++ plugins/api-docs/src/index.ts | 18 ++++++ plugins/api-docs/src/plugin.test.ts | 23 ++++++++ plugins/api-docs/src/plugin.ts | 30 ++++++++++ plugins/api-docs/src/setupTests.ts | 19 +++++++ 15 files changed, 413 insertions(+) create mode 100644 plugins/api-docs/.eslintrc.js create mode 100644 plugins/api-docs/README.md create mode 100644 plugins/api-docs/dev/index.tsx create mode 100644 plugins/api-docs/package.json create mode 100644 plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx create mode 100644 plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx create mode 100644 plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.test.tsx create mode 100644 plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx create mode 100644 plugins/api-docs/src/components/CatalogApiPluginPage/index.ts create mode 100644 plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx create mode 100644 plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx create mode 100644 plugins/api-docs/src/index.ts create mode 100644 plugins/api-docs/src/plugin.test.ts create mode 100644 plugins/api-docs/src/plugin.ts create mode 100644 plugins/api-docs/src/setupTests.ts diff --git a/plugins/api-docs/.eslintrc.js b/plugins/api-docs/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/plugins/api-docs/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md new file mode 100644 index 0000000000..7ea87004c3 --- /dev/null +++ b/plugins/api-docs/README.md @@ -0,0 +1,9 @@ +# API Documentation + +WORK IN PROGRESS + +This is an extension for the catalog plugin that provides components to discover and display API entities. + +## Links + +- (The Backstage homepage)[https://backstage.io] diff --git a/plugins/api-docs/dev/index.tsx b/plugins/api-docs/dev/index.tsx new file mode 100644 index 0000000000..812a5585d4 --- /dev/null +++ b/plugins/api-docs/dev/index.tsx @@ -0,0 +1,20 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createDevApp } from '@backstage/dev-utils'; +import { plugin } from '../src/plugin'; + +createDevApp().registerPlugin(plugin).render(); diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json new file mode 100644 index 0000000000..9b7f519f59 --- /dev/null +++ b/plugins/api-docs/package.json @@ -0,0 +1,53 @@ +{ + "name": "@backstage/plugin-api-docs", + "version": "0.1.1-alpha.18", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": true, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "build": "backstage-cli plugin:build", + "start": "backstage-cli plugin:serve", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "diff": "backstage-cli plugin:diff", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/catalog-model": "^0.1.1-alpha.18", + "@backstage/core": "^0.1.1-alpha.18", + "@backstage/plugin-catalog": "^0.1.1-alpha.18", + "@backstage/theme": "^0.1.1-alpha.18", + "@material-icons/font": "^1.0.2", + "@material-ui/core": "^4.9.1", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.45", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-router-dom": "6.0.0-beta.0", + "react-use": "^15.3.3", + "swagger-ui-react": "^3.31.1" + }, + "devDependencies": { + "@backstage/cli": "^0.1.1-alpha.18", + "@backstage/dev-utils": "^0.1.1-alpha.18", + "@backstage/test-utils": "^0.1.1-alpha.18", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^10.4.1", + "@testing-library/user-event": "^12.0.7", + "@types/jest": "^26.0.7", + "@types/node": "^12.0.0", + "@types/swagger-ui-react": "^3.23.2", + "jest-fetch-mock": "^3.0.3" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx new file mode 100644 index 0000000000..af101f0194 --- /dev/null +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx @@ -0,0 +1,34 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ApiEntityV1alpha1 } from '@backstage/catalog-model'; +import { InfoCard } from '@backstage/core'; +import React, { FC } from 'react'; +import { ApiDefinitionWidget } from '../ApiDefinitionWidget/ApiDefinitionWidget'; + +export const ApiDefinitionCard: FC<{ + title?: string; + apiEntity: ApiEntityV1alpha1; +}> = ({ title, apiEntity }) => { + const type = apiEntity?.spec?.type || ''; + const definition = apiEntity?.spec?.definition || ''; + + return ( + + + + ); +}; diff --git a/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx b/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx new file mode 100644 index 0000000000..ac54793b6d --- /dev/null +++ b/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx @@ -0,0 +1,32 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { FC } from 'react'; +import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget/OpenApiDefinitionWidget'; +import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget/PlainApiDefinitionWidget'; + +export const ApiDefinitionWidget: FC<{ + type: string; + definition: string; +}> = ({ type, definition }) => { + switch (type) { + case 'openapi': + return ; + + default: + return ; + } +}; diff --git a/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.test.tsx b/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.test.tsx new file mode 100644 index 0000000000..4bb39b6e8c --- /dev/null +++ b/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.test.tsx @@ -0,0 +1,34 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { lightTheme } from '@backstage/theme'; +import { ThemeProvider } from '@material-ui/core'; +import { render } from '@testing-library/react'; +import mockFetch from 'jest-fetch-mock'; +import React from 'react'; +import CatalogApiPluginPage from './CatalogApiPluginPage'; + +describe('CatalogApiPluginPage', () => { + it('should render', () => { + mockFetch.mockResponse(() => new Promise(() => {})); + const rendered = render( + + + , + ); + expect(rendered.getByText('Welcome to catalog-api!')).toBeInTheDocument(); + }); +}); diff --git a/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx b/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx new file mode 100644 index 0000000000..dc47a74052 --- /dev/null +++ b/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx @@ -0,0 +1,56 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Content, + ContentHeader, + Header, + HeaderLabel, + InfoCard, + Page, + pageTheme, + SupportButton, +} from '@backstage/core'; +import { Grid, Typography } from '@material-ui/core'; +import React, { FC } from 'react'; + +const CatalogApiPluginPage: FC<{}> = () => ( + +
+ + +
+ + + A description of your plugin goes here. + + + + + + All content should be wrapped in a card like this. + + + + +

API Catalog

+
+
+
+
+); + +export default CatalogApiPluginPage; diff --git a/plugins/api-docs/src/components/CatalogApiPluginPage/index.ts b/plugins/api-docs/src/components/CatalogApiPluginPage/index.ts new file mode 100644 index 0000000000..7021d2bf9f --- /dev/null +++ b/plugins/api-docs/src/components/CatalogApiPluginPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { default } from './CatalogApiPluginPage'; diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx new file mode 100644 index 0000000000..c06c90e67f --- /dev/null +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { FC, useEffect, useState } from 'react'; +import SwaggerUI from 'swagger-ui-react'; +import 'swagger-ui-react/swagger-ui.css'; + +export const OpenApiDefinitionWidget: FC<{ + definition: any; +}> = ({ definition }) => { + // Due to a bug in the swagger-ui-react component, the component needs + // to be created without content first. + const [def, setDef] = useState(''); + + useEffect(() => { + const timer = setTimeout(() => setDef(definition), 0); + return () => clearTimeout(timer); + }, [definition, setDef]); + + // TODO: This looks fine in the light theme, but wrong in dark mode. We need a custom stylesheet for swagger-ui. + // Till then, we add a white background to the swagger-ui to make it usable in dark mode. + // TODO: the typings do not allow a string while the component does (https://github.com/DefinitelyTyped/DefinitelyTyped/pull/46654) + return ( +
+ +
+ ); +}; diff --git a/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx b/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx new file mode 100644 index 0000000000..4ceeed06e1 --- /dev/null +++ b/plugins/api-docs/src/components/PlainApiDefinitionWidget/PlainApiDefinitionWidget.tsx @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CodeSnippet } from '@backstage/core'; +import React, { FC } from 'react'; + +export const PlainApiDefinitionWidget: FC<{ + definition: any; +}> = ({ definition }) => { + return ; +}; diff --git a/plugins/api-docs/src/index.ts b/plugins/api-docs/src/index.ts new file mode 100644 index 0000000000..c82a2c263b --- /dev/null +++ b/plugins/api-docs/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ApiDefinitionCard } from './components/ApiDefinitionCard/ApiDefinitionCard'; +export { plugin } from './plugin'; diff --git a/plugins/api-docs/src/plugin.test.ts b/plugins/api-docs/src/plugin.test.ts new file mode 100644 index 0000000000..054e804382 --- /dev/null +++ b/plugins/api-docs/src/plugin.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { plugin } from './plugin'; + +describe('api-docs', () => { + it('should export plugin', () => { + expect(plugin).toBeDefined(); + }); +}); diff --git a/plugins/api-docs/src/plugin.ts b/plugins/api-docs/src/plugin.ts new file mode 100644 index 0000000000..90d8990aaa --- /dev/null +++ b/plugins/api-docs/src/plugin.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createPlugin, createRouteRef } from '@backstage/core'; +import CatalogApiPluginPage from './components/CatalogApiPluginPage'; + +export const rootRouteRef = createRouteRef({ + path: '/api-docs', + title: 'api-docs', +}); + +export const plugin = createPlugin({ + id: 'api-docs', + register({ router }) { + router.addRoute(rootRouteRef, CatalogApiPluginPage); + }, +}); diff --git a/plugins/api-docs/src/setupTests.ts b/plugins/api-docs/src/setupTests.ts new file mode 100644 index 0000000000..8553642152 --- /dev/null +++ b/plugins/api-docs/src/setupTests.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import '@testing-library/jest-dom'; + +require('jest-fetch-mock').enableMocks(); From 9a23ea8bdab9ec70523eeec6d14b1f648f49fab3 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 11:54:46 +0200 Subject: [PATCH 05/26] feat(catalog): add trivial tab implementation and add a tab to display all implemented apis --- plugins/catalog/package.json | 1 + .../EntityPageApi/EntityPageApi.tsx | 72 +++++++++++++++++++ .../EntityPageOverview/EntityPageOverview.tsx | 61 ++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 plugins/catalog/src/components/EntityPageApi/EntityPageApi.tsx create mode 100644 plugins/catalog/src/components/EntityPageOverview/EntityPageOverview.tsx diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 4f0e5df322..d91b8c03cc 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -23,6 +23,7 @@ "dependencies": { "@backstage/catalog-model": "^0.1.1-alpha.18", "@backstage/core": "^0.1.1-alpha.18", + "@backstage/plugin-api-docs": "^0.1.1-alpha.18", "@backstage/plugin-github-actions": "^0.1.1-alpha.18", "@backstage/plugin-jenkins": "^0.1.1-alpha.18", "@backstage/plugin-scaffolder": "^0.1.1-alpha.18", diff --git a/plugins/catalog/src/components/EntityPageApi/EntityPageApi.tsx b/plugins/catalog/src/components/EntityPageApi/EntityPageApi.tsx new file mode 100644 index 0000000000..b115539366 --- /dev/null +++ b/plugins/catalog/src/components/EntityPageApi/EntityPageApi.tsx @@ -0,0 +1,72 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ApiEntityV1alpha1, Entity } from '@backstage/catalog-model'; +import { Content, Progress, useApi } from '@backstage/core'; +import { ApiDefinitionCard } from '@backstage/plugin-api-docs'; +import { Grid } from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import React, { FC } from 'react'; +import { useAsync } from 'react-use'; +import { catalogApiRef } from '../..'; + +export const EntityPageApi: FC<{ entity: Entity }> = ({ entity }) => { + const catalogApi = useApi(catalogApiRef); + + const { value: apiEntities, loading } = useAsync(async () => { + const a = await Promise.all( + ((entity?.spec?.implementedApis as string[]) || []).map(api => + catalogApi.getEntityByName({ + kind: 'API', + name: api, + }), + ), + ); + const b = new Map(); + + a.filter(api => !!api).forEach(api => { + b.set(api?.metadata?.name!, api as ApiEntityV1alpha1); + }); + return b; + }, [catalogApi, entity]); + + return ( + + {loading && } + {!loading && ( + + {((entity?.spec?.implementedApis as string[]) || []).map(api => { + const apiEntity = apiEntities && apiEntities.get(api); + + return ( + + {!apiEntity && ( + + Error on fetching the API: {api} + + )} + + {apiEntity && ( + + )} + + ); + })} + + )} + + ); +}; diff --git a/plugins/catalog/src/components/EntityPageOverview/EntityPageOverview.tsx b/plugins/catalog/src/components/EntityPageOverview/EntityPageOverview.tsx new file mode 100644 index 0000000000..f4faa8c574 --- /dev/null +++ b/plugins/catalog/src/components/EntityPageOverview/EntityPageOverview.tsx @@ -0,0 +1,61 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { Content } from '@backstage/core'; +import { SentryIssuesWidget } from '@backstage/plugin-sentry'; +import { Widget as GithubActionsWidget } from '@backstage/plugin-github-actions'; +import { JenkinsBuildsWidget, JenkinsLastBuildWidget, } from '@backstage/plugin-jenkins'; +import { Grid } from '@material-ui/core'; +import React, { FC } from 'react'; +import { EntityMetadataCard } from '../EntityMetadataCard/EntityMetadataCard'; + +export const EntityPageOverview: FC<{ entity: Entity }> = ({ entity }) => { + return ( + + + + + + {entity.metadata?.annotations?.[ + 'backstage.io/jenkins-github-folder' + ] && ( + + + + )} + {entity.metadata?.annotations?.[ + 'backstage.io/jenkins-github-folder' + ] && ( + + + + )} + {entity.metadata?.annotations?.['backstage.io/github-actions-id'] && ( + + + + )} + + + + + + ); +}; From 58f86f992a195f46c3bc7cbd0c48350f6c05e3c0 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 14:09:02 +0200 Subject: [PATCH 06/26] feat(app): add api-docs plugin to the navigation --- packages/app/package.json | 1 + packages/app/src/components/Root/Root.tsx | 2 ++ packages/app/src/plugins.ts | 1 + 3 files changed, 4 insertions(+) diff --git a/packages/app/package.json b/packages/app/package.json index f42456709c..0e2cb677a4 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -5,6 +5,7 @@ "dependencies": { "@backstage/cli": "^0.1.1-alpha.18", "@backstage/core": "^0.1.1-alpha.18", + "@backstage/plugin-api-docs": "^0.1.1-alpha.18", "@backstage/plugin-catalog": "^0.1.1-alpha.18", "@backstage/plugin-circleci": "^0.1.1-alpha.18", "@backstage/plugin-explore": "^0.1.1-alpha.18", diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index a86b92ab43..1d32b6e16e 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -19,6 +19,7 @@ import PropTypes from 'prop-types'; import { Link, makeStyles } from '@material-ui/core'; import HomeIcon from '@material-ui/icons/Home'; import ExploreIcon from '@material-ui/icons/Explore'; +import ExtensionIcon from '@material-ui/icons/Extension'; import BuildIcon from '@material-ui/icons/BuildRounded'; import RuleIcon from '@material-ui/icons/AssignmentTurnedIn'; import MapIcon from '@material-ui/icons/MyLocation'; @@ -90,6 +91,7 @@ const Root: FC<{}> = ({ children }) => ( {/* Global nav, not org-specific */} + {/* End global nav */} diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts index 7e803698fe..4ec19c74f3 100644 --- a/packages/app/src/plugins.ts +++ b/packages/app/src/plugins.ts @@ -30,3 +30,4 @@ export { plugin as Rollbar } from '@backstage/plugin-rollbar'; export { plugin as Newrelic } from '@backstage/plugin-newrelic'; export { plugin as TravisCI } from '@roadiehq/backstage-plugin-travis-ci'; export { plugin as Jenkins } from '@backstage/plugin-jenkins'; +export { plugin as ApiDocs } from '@backstage/plugin-api-docs'; From 3534c0804c021514009542e09848ec7e0000512f Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 15:36:04 +0200 Subject: [PATCH 07/26] feat(api-docs): add routes to display all api entities --- .../ApiCatalogLayout.tsx} | 35 ++--- .../ApiCatalogPage/ApiCatalogPage.test.tsx | 70 ++++++++++ .../ApiCatalogPage/ApiCatalogPage.tsx | 45 ++++++ .../ApiCatalogTable/ApiCatalogTable.test.tsx | 74 ++++++++++ .../ApiCatalogTable/ApiCatalogTable.tsx | 89 ++++++++++++ .../ApiEntityPage/ApiEntityPage.test.tsx | 102 ++++++++++++++ .../ApiEntityPage/ApiEntityPage.tsx | 131 ++++++++++++++++++ .../CatalogApiPluginPage.tsx | 56 -------- plugins/api-docs/src/plugin.ts | 14 +- .../index.ts => routes.ts} | 15 +- 10 files changed, 550 insertions(+), 81 deletions(-) rename plugins/api-docs/src/components/{CatalogApiPluginPage/CatalogApiPluginPage.test.tsx => ApiCatalogPage/ApiCatalogLayout.tsx} (51%) create mode 100644 plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.test.tsx create mode 100644 plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.tsx create mode 100644 plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.test.tsx create mode 100644 plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.tsx create mode 100644 plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.test.tsx create mode 100644 plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.tsx delete mode 100644 plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx rename plugins/api-docs/src/{components/CatalogApiPluginPage/index.ts => routes.ts} (65%) diff --git a/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.test.tsx b/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogLayout.tsx similarity index 51% rename from plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.test.tsx rename to plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogLayout.tsx index 4bb39b6e8c..d846e2b0e2 100644 --- a/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.test.tsx +++ b/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogLayout.tsx @@ -14,21 +14,24 @@ * limitations under the License. */ -import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core'; -import { render } from '@testing-library/react'; -import mockFetch from 'jest-fetch-mock'; +import { Header, Page, pageTheme } from '@backstage/core'; import React from 'react'; -import CatalogApiPluginPage from './CatalogApiPluginPage'; -describe('CatalogApiPluginPage', () => { - it('should render', () => { - mockFetch.mockResponse(() => new Promise(() => {})); - const rendered = render( - - - , - ); - expect(rendered.getByText('Welcome to catalog-api!')).toBeInTheDocument(); - }); -}); +type Props = { + children?: React.ReactNode; +}; + +const ApiCatalogLayout = ({ children }: Props) => { + return ( + +
+ {children} + + ); +}; + +export default ApiCatalogLayout; diff --git a/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.test.tsx b/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.test.tsx new file mode 100644 index 0000000000..19cbaf6038 --- /dev/null +++ b/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.test.tsx @@ -0,0 +1,70 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry, storageApiRef } from '@backstage/core'; +// TODO: Circular ref! +import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog'; +import { MockStorageApi, wrapInTestApp } from '@backstage/test-utils'; +import { render } from '@testing-library/react'; +import React from 'react'; +import { ApiCatalogPage } from './ApiCatalogPage'; + +describe('ApiCatalogPage', () => { + const catalogApi: Partial = { + getEntities: () => + Promise.resolve([ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'Entity1', + }, + }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'Entity2', + }, + }, + ] as Entity[]), + getLocationByEntity: () => + Promise.resolve({ id: 'id', type: 'github', target: 'url' }), + }; + + const renderWrapped = (children: React.ReactNode) => + render( + wrapInTestApp( + + {children} + , + ), + ); + + // this test right now causes some red lines in the log output when running tests + // related to some theme issues in mui-table + // https://github.com/mbrn/material-table/issues/1293 + it('should render', async () => { + const { findByText } = renderWrapped(); + expect(await findByText(/APIs \(2\)/)).toBeInTheDocument(); + }); +}); diff --git a/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.tsx b/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.tsx new file mode 100644 index 0000000000..f624ec9f92 --- /dev/null +++ b/plugins/api-docs/src/components/ApiCatalogPage/ApiCatalogPage.tsx @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Content, useApi } from '@backstage/core'; +// TODO: Circular ref +import { catalogApiRef } from '@backstage/plugin-catalog'; +import React from 'react'; +import { useAsync } from 'react-use'; +import { ApiCatalogTable } from '../ApiCatalogTable/ApiCatalogTable'; +import ApiCatalogLayout from './ApiCatalogLayout'; + +const CatalogPageContents = () => { + const catalogApi = useApi(catalogApiRef); + const { loading, error, value: matchingEntities } = useAsync(() => { + return catalogApi.getEntities({ kind: 'API' }); + }, [catalogApi]); + + return ( + + + + + + ); +}; + +export const ApiCatalogPage = () => ; diff --git a/plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.test.tsx b/plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.test.tsx new file mode 100644 index 0000000000..67f6562a56 --- /dev/null +++ b/plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { render } from '@testing-library/react'; +import * as React from 'react'; +import { ApiCatalogTable } from './ApiCatalogTable'; + +const entites: Entity[] = [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { name: 'api1' }, + }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { name: 'api2' }, + }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { name: 'api3' }, + }, +]; + +describe('ApiCatalogTable component', () => { + it('should render error message when error is passed in props', async () => { + const rendered = render( + wrapInTestApp( + , + ), + ); + const errorMessage = await rendered.findByText( + /Error encountered while fetching catalog entities./, + ); + expect(errorMessage).toBeInTheDocument(); + }); + + it('should display entity names when loading has finished and no error occurred', async () => { + const rendered = render( + wrapInTestApp( + , + ), + ); + expect(rendered.getByText(/APIs \(3\)/)).toBeInTheDocument(); + expect(rendered.getByText(/api1/)).toBeInTheDocument(); + expect(rendered.getByText(/api2/)).toBeInTheDocument(); + expect(rendered.getByText(/api3/)).toBeInTheDocument(); + }); +}); diff --git a/plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.tsx b/plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.tsx new file mode 100644 index 0000000000..e30583caed --- /dev/null +++ b/plugins/api-docs/src/components/ApiCatalogTable/ApiCatalogTable.tsx @@ -0,0 +1,89 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Entity } from '@backstage/catalog-model'; +import { Table, TableColumn } from '@backstage/core'; +import { Link } from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import React from 'react'; +import { generatePath, Link as RouterLink } from 'react-router-dom'; +import { entityRoute } from '../../routes'; + +const columns: TableColumn[] = [ + { + title: 'Name', + field: 'metadata.name', + highlight: true, + render: (entity: any) => ( + + {entity.metadata.name} + + ), + }, + { + title: 'Description', + field: 'metadata.description', + }, +]; + +type CatalogTableProps = { + entities: Entity[]; + titlePreamble: string; + loading: boolean; + error?: any; +}; + +export const ApiCatalogTable = ({ + entities, + loading, + error, + titlePreamble, +}: CatalogTableProps) => { + if (error) { + return ( +
+ + Error encountered while fetching catalog entities. {error.toString()} + +
+ ); + } + + return ( + + isLoading={loading} + columns={columns} + options={{ + paging: false, + actionsColumnIndex: -1, + loadingType: 'linear', + showEmptyDataSourceMessage: !loading, + }} + title={`${titlePreamble} (${(entities && entities.length) || 0})`} + data={entities} + /> + ); +}; diff --git a/plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.test.tsx b/plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.test.tsx new file mode 100644 index 0000000000..af5213e3f1 --- /dev/null +++ b/plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.test.tsx @@ -0,0 +1,102 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from '@backstage/catalog-model'; +import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core'; +import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog'; +import { wrapInTestApp } from '@backstage/test-utils'; +import { render, waitFor } from '@testing-library/react'; +import * as React from 'react'; +import { ApiEntityPage, getPageTheme } from './ApiEntityPage'; + +jest.mock('react-router-dom', () => { + const actual = jest.requireActual('react-router-dom'); + const mockNavigate = jest.fn(); + return { + ...actual, + useNavigate: jest.fn(() => mockNavigate), + useParams: jest.fn(), + }; +}); + +const { + useParams, + useNavigate, +}: { useParams: jest.Mock; useNavigate: () => jest.Mock } = jest.requireMock( + 'react-router-dom', +); + +const errorApi = { post: () => {} }; + +describe('ApiEntityPage', () => { + it('should redirect to catalog page when name is not provided', async () => { + useParams.mockReturnValue({ + kind: 'Component', + optionalNamespaceAndName: '', + }); + + render( + wrapInTestApp( + ) as CatalogApi, + ], + ])} + > + + , + ), + ); + + await waitFor(() => + expect(useNavigate()).toHaveBeenCalledWith('/api-docs'), + ); + }); +}); + +describe('getPageTheme', () => { + const defaultPageTheme = getPageTheme(); + it.each(['service', 'app', 'library', 'tool', 'documentation', 'website'])( + 'should select right theme for predefined type: %p ̰ ', + type => { + const theme = getPageTheme(({ + spec: { + type, + }, + } as any) as Entity); + expect(theme).toBeDefined(); + expect(theme).not.toBe(defaultPageTheme); + }, + ); + + it('should select default theme for unknown/unspecified types', () => { + const theme1 = getPageTheme(({ + spec: { + type: 'unknown-type', + }, + } as any) as Entity); + const theme2 = getPageTheme(({ + spec: {}, + } as any) as Entity); + expect(theme1).toBe(defaultPageTheme); + expect(theme2).toBe(defaultPageTheme); + }); +}); diff --git a/plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.tsx b/plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.tsx new file mode 100644 index 0000000000..5e08af7e8e --- /dev/null +++ b/plugins/api-docs/src/components/ApiEntityPage/ApiEntityPage.tsx @@ -0,0 +1,131 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ApiEntityV1alpha1, Entity } from '@backstage/catalog-model'; +import { + Content, + errorApiRef, + Header, + Page, + pageTheme, + PageTheme, + Progress, + useApi, +} from '@backstage/core'; +// TODO: Circular ref +import { catalogApiRef } from '@backstage/plugin-catalog'; +import { Box } from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import React, { FC, useEffect } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { useAsync } from 'react-use'; +import { ApiDefinitionCard } from '../ApiDefinitionCard/ApiDefinitionCard'; + +const REDIRECT_DELAY = 1000; +function headerProps( + kind: string, + namespace: string | undefined, + name: string, + entity: Entity | undefined, +): { headerTitle: string; headerType: string } { + return { + headerTitle: `${name}${namespace ? ` in ${namespace}` : ''}`, + headerType: (() => { + let t = kind.toLowerCase(); + if (entity && entity.spec && 'type' in entity.spec) { + t += ' — '; + t += (entity.spec as { type: string }).type.toLowerCase(); + } + return t; + })(), + }; +} + +export const getPageTheme = (entity?: Entity): PageTheme => { + const themeKey = entity?.spec?.type?.toString() ?? 'home'; + return pageTheme[themeKey] ?? pageTheme.home; +}; + +const EntityPageTitle: FC<{ title: string; entity: Entity | undefined }> = ({ + title, +}) => ( + + {title} + +); + +export const ApiEntityPage: FC<{}> = () => { + const { optionalNamespaceAndName } = useParams() as { + optionalNamespaceAndName: string; + }; + const navigate = useNavigate(); + const [name, namespace] = optionalNamespaceAndName.split(':').reverse(); + + const errorApi = useApi(errorApiRef); + const catalogApi = useApi(catalogApiRef); + + const { value: entity, error, loading } = useAsync( + () => catalogApi.getEntityByName({ kind: 'API', namespace, name }), + [catalogApi, namespace, name], + ); + + useEffect(() => { + if (!error && !loading && !entity) { + errorApi.post(new Error('Entity not found!')); + setTimeout(() => { + navigate('/'); + }, REDIRECT_DELAY); + } + }, [errorApi, navigate, error, loading, entity]); + + if (!name) { + navigate('/api-docs'); + return null; + } + + const { headerTitle, headerType } = headerProps( + 'API', + namespace, + name, + entity, + ); + + return ( + +
} + pageTitleOverride={headerTitle} + type={headerType} + /> + + {loading && } + + {error && ( + + {error.toString()} + + )} + + {entity && ( + <> + + + + + )} + + ); +}; diff --git a/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx b/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx deleted file mode 100644 index dc47a74052..0000000000 --- a/plugins/api-docs/src/components/CatalogApiPluginPage/CatalogApiPluginPage.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - Content, - ContentHeader, - Header, - HeaderLabel, - InfoCard, - Page, - pageTheme, - SupportButton, -} from '@backstage/core'; -import { Grid, Typography } from '@material-ui/core'; -import React, { FC } from 'react'; - -const CatalogApiPluginPage: FC<{}> = () => ( - -
- - -
- - - A description of your plugin goes here. - - - - - - All content should be wrapped in a card like this. - - - - -

API Catalog

-
-
-
-
-); - -export default CatalogApiPluginPage; diff --git a/plugins/api-docs/src/plugin.ts b/plugins/api-docs/src/plugin.ts index 90d8990aaa..db58538b67 100644 --- a/plugins/api-docs/src/plugin.ts +++ b/plugins/api-docs/src/plugin.ts @@ -14,17 +14,15 @@ * limitations under the License. */ -import { createPlugin, createRouteRef } from '@backstage/core'; -import CatalogApiPluginPage from './components/CatalogApiPluginPage'; - -export const rootRouteRef = createRouteRef({ - path: '/api-docs', - title: 'api-docs', -}); +import { createPlugin } from '@backstage/core'; +import { ApiCatalogPage } from './components/ApiCatalogPage/ApiCatalogPage'; +import { ApiEntityPage } from './components/ApiEntityPage/ApiEntityPage'; +import { entityRoute, rootRoute } from './routes'; export const plugin = createPlugin({ id: 'api-docs', register({ router }) { - router.addRoute(rootRouteRef, CatalogApiPluginPage); + router.addRoute(rootRoute, ApiCatalogPage); + router.addRoute(entityRoute, ApiEntityPage); }, }); diff --git a/plugins/api-docs/src/components/CatalogApiPluginPage/index.ts b/plugins/api-docs/src/routes.ts similarity index 65% rename from plugins/api-docs/src/components/CatalogApiPluginPage/index.ts rename to plugins/api-docs/src/routes.ts index 7021d2bf9f..48c530d4b5 100644 --- a/plugins/api-docs/src/components/CatalogApiPluginPage/index.ts +++ b/plugins/api-docs/src/routes.ts @@ -14,4 +14,17 @@ * limitations under the License. */ -export { default } from './CatalogApiPluginPage'; +import { createRouteRef } from '@backstage/core'; + +const NoIcon = () => null; + +export const rootRoute = createRouteRef({ + icon: NoIcon, + path: '/api-docs', + title: 'APIs', +}); +export const entityRoute = createRouteRef({ + icon: NoIcon, + path: '/api-docs/:optionalNamespaceAndName/', + title: 'API', +}); From 5a023c3c49f5864949b0798242e9c7de97ebb9d1 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 16:15:48 +0200 Subject: [PATCH 08/26] feat(api-docs): render documentation of type asyncapi --- plugins/api-docs/package.json | 1 + .../ApiDefinitionWidget.tsx | 4 + .../AsyncApiDefinitionWidget.tsx | 25 + .../AsyncApiDefinitionWidget/style.css | 1273 +++++++++++++++++ 4 files changed, 1303 insertions(+) create mode 100644 plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx create mode 100644 plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 9b7f519f59..3d938a3118 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -25,6 +25,7 @@ "@backstage/core": "^0.1.1-alpha.18", "@backstage/plugin-catalog": "^0.1.1-alpha.18", "@backstage/theme": "^0.1.1-alpha.18", + "@kyma-project/asyncapi-react": "^0.6.1", "@material-icons/font": "^1.0.2", "@material-ui/core": "^4.9.1", "@material-ui/icons": "^4.9.1", diff --git a/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx b/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx index ac54793b6d..5b1ddd7880 100644 --- a/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionWidget/ApiDefinitionWidget.tsx @@ -15,6 +15,7 @@ */ import React, { FC } from 'react'; +import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget/AsyncApiDefinitionWidget'; import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget/OpenApiDefinitionWidget'; import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget/PlainApiDefinitionWidget'; @@ -26,6 +27,9 @@ export const ApiDefinitionWidget: FC<{ case 'openapi': return ; + case 'asyncapi': + return ; + default: return ; } diff --git a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx new file mode 100644 index 0000000000..2b5e697e51 --- /dev/null +++ b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinitionWidget.tsx @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AsyncApi from '@kyma-project/asyncapi-react'; +import React, { FC } from 'react'; +import './style.css'; + +export const AsyncApiDefinitionWidget: FC<{ + definition: any; +}> = ({ definition }) => { + return ; +}; diff --git a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css new file mode 100644 index 0000000000..085e056da6 --- /dev/null +++ b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css @@ -0,0 +1,1273 @@ +/* + * Copyright (c) 2018-2019 SAP SE or an SAP affiliate company. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.asyncapi { + font-family: '72'; + font-size: 14px; + line-height: 20px; + font-weight: 400; + -webkit-font-smoothing: antialiased; + font-smoothing: antialiased; + background: #f3f4f5; +} + +.asyncapi__toggle { + cursor: pointer; +} +.asyncapi__toggle > .asyncapi__toggle-body { + display: none; +} + +.asyncapi__toggle--expanded { + cursor: default; +} +.asyncapi__toggle--expanded > .asyncapi__toggle-body { + display: block; +} + +.asyncapi__toggle--no-children { +} +.asyncapi__toggle--no-children > .asyncapi__toggle-header { + cursor: default; +} + +.asyncapi__toggle-header { + position: relative; + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.asyncapi__toggle-header-content { + flex-grow: 1; + padding: 12px; +} +.asyncapi__toggle-header-content > h1, +.asyncapi__toggle-header-content > h2, +.asyncapi__toggle-header-content > h3, +.asyncapi__toggle-header-content > h4 { + margin: 0; + padding: 0; + display: flex; +} + +.asyncapi__toggle-button { + border: none; + height: 100%; + cursor: pointer; +} + +.asyncapi__toggle-arrow { + display: inline-block; + position: relative; + transform-origin: 50% 50%; + transition: 0.35s ease; + cursor: pointer; +} +.asyncapi__toggle-arrow:before { + content: '\e0e3'; + font-family: 'SAP-icons'; + font-size: 14px; +} +.asyncapi__toggle-arrow--expanded { + transform: rotate(-90deg); +} + +.asyncapi__components { +} + +.asyncapi__anchor { +} +.asyncapi__anchor:hover > .asyncapi__anchor-content { + text-decoration: underline; +} + +.asyncapi__anchor-content { + display: inline-block; +} + +.asyncapi__anchor-icon { + display: inline-block; + margin-left: 6px; +} +.asyncapi__anchor-icon:before { + content: '\e0ac'; + font-family: 'SAP-icons'; +} + +.asyncapi__markdown { +} +.asyncapi__markdown > div > ul { + margin: 0; + padding-left: 16px; +} +.asyncapi__markdown > div > ul { + margin: 0; + padding-left: 16px; +} +.asyncapi__markdown > div > p { + margin: 0; +} +.asyncapi__markdown > div > p > code { + display: inline-block; + font-weight: bold; + font-size: 10px; + line-height: 14px; + border-radius: 3px; + padding: 0px 5px; + text-align: center; + background: #e2eaf2; + color: #18873d; +} + +.asyncapi__table { + margin: 0 0 20px 0; + width: 100%; + border-spacing: 0; + font-size: 13px; +} + +.asyncapi__table--nested { + margin: 10px 10px 10px auto; + width: calc(100% - 45px); + border-spacing: 0; + font-size: 13px; + border-radius: 5px; + border: solid 1px #d4d4d4; + background-color: #f9fafa; +} + +.asyncapi__table-header { + width: 100%; + color: #939698; + background: #f9fafa; + text-transform: uppercase; +} + +.asyncapi__table-header--nested { + color: #939698; + border-bottom: solid 1px #d4d4d4; + font-weight: bold; + text-align: left; + padding: 6px 0; + font-size: 12px; +} + +.asyncapi__table-header-title { + line-height: 30px; +} + +.asyncapi__table-header-title--nested { + color: #939698; +} +.asyncapi__table-header-title--nested > td { + border-bottom: solid 1px #d4d4d4; + padding: 8px 20px; + font-size: 12px; + color: #818487; +} + +.asyncapi__table-header-columns { + font-weight: lighter; + font-size: 11px; +} + +.asyncapi__table-header-columns--nested { + color: #939698; +} + +.asyncapi__table-header-column { + padding: 12px; + text-align: left; +} + +.asyncapi__table-header-column--nested { + width: 20%; + padding: 8px 20px; + font-size: 12px; + border-bottom: solid 1px #d4d4d4; +} + +.asyncapi__table-body { + color: #000; +} + +.asyncapi__table-body--nested { + color: #000; +} + +.asyncapi__table-row { +} + +.asyncapi__table-row--nested { + color: #333; + border-bottom: solid 1px #d4d4d4; +} +.asyncapi__table-row--nested:last-child > td { + border-bottom: none; +} + +.asyncapi__table-row-accordion { + display: none; +} + +.asyncapi__table-row-accordion--open { + display: table-row; +} + +.asyncapi__table-cell { + padding: 12px; + vertical-align: top; + border-bottom: 1px solid #efeff0; +} +.asyncapi__table-cell > p { + margin-top: 0; +} + +.asyncapi__table-cell--nested { + padding: 8px 20px; + vertical-align: top; + font-size: 13px; + border-bottom: solid 1px #d4d4d4; +} + +.asyncapi__tree-space { + display: inline-block; + width: 20px; +} + +.asyncapi__tree-leaf { + display: inline-block; + position: relative; + width: 25px; +} + +.asyncapi__tree-leaf:before { + content: ''; + position: absolute; + top: -15px; + width: 13px; + height: 10px; + border-left: #aaa 2px solid; + border-bottom: #aaa 2px solid; + border-radius: 0 0 0 70%; +} + +.asyncapi__badge { + display: inline-block; + font-weight: bold; + font-size: 11px; + line-height: 18px; + border-radius: 3px; + padding: 0px 5px; + text-align: center; + text-transform: uppercase; + background: #e2eaf2; +} + +.asyncapi__badge--publish { + color: #18873d; +} + +.asyncapi__badge--subscribe { + color: #107ee3; +} + +.asyncapi__badge--deprecated { + margin-left: 10px; + color: #f59702; +} + +.asyncapi__badge--required { + font-size: 9px; + line-height: 14px; + color: #f59702; + border-radius: 3px; + margin-left: 10px; +} + +.asyncapi__badge--generated { + font-size: 9px; + line-height: 14px; + color: #18873d; + border-radius: 3px; + margin-left: 10px; +} + +.asyncapi__tag { + display: inline-block; + mix-blend-mode: multiply; + border-radius: 4px; + background-color: #e2eaf2; + font-size: 11px; + font-family: 72; + font-weight: 300; + text-transform: uppercase; + font-weight: normal; + font-style: normal; + font-stretch: normal; + line-height: normal; + letter-spacing: normal; + color: #73787d; + padding: 3px 8px; + margin: 0 5px 0 0; +} + +.asyncapi__code { + border: solid 1px rgba(137, 145, 154, 0.675); + border-radius: 5px; + background: #fff; +} + +.asyncapi__code-header { + padding: 12px 20px; + border-bottom: 1px solid rgba(137, 145, 154, 0.675); +} + +.asyncapi__code-header > h4 { + margin: 0; + color: #32363a; + font-size: 13px; +} + +.asyncapi__code-pre { + margin: 0; + font-size: 13px; + padding: 12px; + background: #fafafa; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; +} + +.asyncapi__code-body { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; + margin: 0; + font-size: 12px; +} + +.asyncapi__info { + background: #fff; + border-radius: 5px; + padding: 16px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); +} + +.asyncapi__info-header-main { + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: center; +} +.asyncapi__info-header-main > h1 { + flex-grow: 1; + margin-top: 10px; + margin-bottom: 10px; +} + +.asyncapi__collapse-button { + border-radius: 0.25rem; + border: 1px solid #0071d4; + display: inline-block; + color: #0b74de; + font-weight: 700; + transition: all 0.125s ease-in; + padding: 10px 12px; + font-size: 14px; + cursor: pointer; +} +.asyncapi__collapse-button:hover { + background-color: #085caf; + color: #fff; +} +.asyncapi__collapse-button:focus { + outline: none; +} + +.asyncapi__info-header-version { + display: inline-block; + margin-left: 6px; +} + +.asyncapi__info-description { +} + +.asyncapi__info-list { + margin: 0 0 20px 0; + padding: 0; + list-style-type: none; +} +.asyncapi__info-list > li { + border-radius: 0.25rem; + border: 1px solid #0071d4; + margin: 6px 6px 0 0; + display: inline-block; + color: #0b74de; + font-weight: 500; + transition: all 0.125s ease-in; +} +.asyncapi__info-list > li:hover { + background-color: #085caf; +} +.asyncapi__info-list > li a { + padding: 3px 12px; + display: inline-block; + text-decoration: none; + color: #0b74de; + transition: all 0.125s ease-in; +} +.asyncapi__info-list > li:hover, +.asyncapi__info-list > li:hover a { + color: #fff; +} +.asyncapi__info-list .asyncapi__anchor:hover > .asyncapi__anchor-content { + text-decoration: none; +} + +.asyncapi__messages { +} +.asyncapi__messages > div { + margin-top: 24px; + background: #fff; + border-radius: 5px; + padding: 16px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); +} + +.asyncapi__messages-toggle .asyncapi__toggle-header-content { + padding: 0; +} +.asyncapi__messages-toggle--expanded > .asyncapi__toggle-header { + padding-bottom: 12px; +} + +.asyncapi__messages-header { +} +.asyncapi__messages-header > h2 { + margin: 0 0 24px 0; +} + +.asyncapi__messages-list { + margin: 0; + padding: 0; + list-style-type: none; +} + +.asyncapi__messages-list-item { + margin-bottom: 16px; +} +.asyncapi__messages-list-item:last-child { + margin-bottom: 0; +} + +.asyncapi__messages-oneOf-list { + margin: 0; + padding: 0; + list-style-type: none; +} + +.asyncapi__messages-oneOf-list-item { +} + +.asyncapi__message { + position: relative; + border-radius: 4px; + border: solid 1px rgba(151, 151, 151, 0.26); + background-color: #ffffff; +} +.asyncapi__message:last-child { + margin-bottom: 0; +} + +.asyncapi__message-header { + padding: 12px; +} +.asyncapi__message-header > h3 { + color: #0b74de; + font-size: 14px; +} + +.asyncapi__message-header-title { + font-size: 14px; + margin-right: 10px; +} + +.asyncapi__message-header-summary { + font-size: 14px; + font-weight: 500; +} + +.asyncapi__message-header-deprecated-badge { +} + +.asyncapi__message-summary { +} + +.asyncapi__message-description { + padding: 12px; + font-size: 14px; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} + +.asyncapi__message-headers { +} + +.asyncapi__message-headers-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__message-headers-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__message-headers-schema { + margin: 0; +} +.asyncapi__message-headers-schema > .asyncapi__schema { + padding: 0; + border: none; +} +.asyncapi__message-headers-schema > .asyncapi__schema:before { + content: ''; + position: relative; + border: none; +} + +.asyncapi__message-payload-oneOf { +} + +.asyncapi__message-payload-toggle > .asyncapi__message-payload-header { + padding: 12px; + border: none; +} +.asyncapi__message-payload-toggle .asyncapi__message-payload-header h4 { + padding: 0; +} +.asyncapi__message-payload-toggle .asyncapi__message-payload-header { + border: none; + background-color: inherit; +} + +.asyncapi__message-payload-oneOf-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__message-payload-oneOf-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__message-payload-oneOf-list { + margin: 0; + padding: 16px; + list-style-type: none; +} + +.asyncapi__message-payload-oneOf-list-item { + margin-bottom: 16px; +} +.asyncapi__message-payload-oneOf-list-item:last-child { + margin-bottom: 0; +} +.asyncapi__message-payload-oneOf-list-item .asyncapi__message-payload { + position: relative; + border-radius: 4px; + border: solid 1px rgba(151, 151, 151, 0.26); + background-color: #ffffff; +} +.asyncapi__message-payload-oneOf-list-item + .asyncapi__message-payload:last-child { + margin-bottom: 0; +} + +.asyncapi__message-payload-anyOf { +} + +.asyncapi__message-payload-anyOf-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__message-payload-anyOf-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__message-payload-anyOf-list { + margin: 0; + padding: 16px; + list-style-type: none; +} + +.asyncapi__message-payload-anyOf-list-item { + margin-bottom: 16px; +} +.asyncapi__message-payload-anyOf-list-item:last-child { + margin-bottom: 0; +} +.asyncapi__message-payload-anyOf-list-item .asyncapi__message-payload { + position: relative; + border-radius: 4px; + border: solid 1px rgba(151, 151, 151, 0.26); + background-color: #ffffff; +} +.asyncapi__message-payload-anyOf-list-item + .asyncapi__message-payload:last-child { + margin-bottom: 0; +} + +.asyncapi__message-payload { + margin: 0; +} + +.asyncapi__message-payload-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__message-payload-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__message-payload-schema { + margin: 0; +} +.asyncapi__message-payload-schema > .asyncapi__schema { + padding: 0; + border: none; +} +.asyncapi__message-payload-schema > .asyncapi__schema:before { + content: ''; + position: relative; + border: none; +} + +.asyncapi__message-tags { + margin: 20px 0; +} + +.asyncapi__message-tags-header { + color: #32363a; +} +.asyncapi__message-tags-header > h4 { + margin: 0 0 8px 0; +} + +.asyncapi__message-tags-list { +} + +.asyncapi__message-tags-list-item { +} + +.asyncapi__schemas { +} +.asyncapi__schemas > div { + margin-top: 24px; + background: #fff; + border-radius: 5px; + padding: 16px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); +} + +.asyncapi__schemas-header { +} + +.asyncapi__schemas-toggle .asyncapi__toggle-header-content { + padding: 0; +} +.asyncapi__schemas-toggle--expanded .asyncapi__toggle-header { + padding-bottom: 12px; +} + +.asyncapi__schemas-list { + margin: 0; + padding: 0; + list-style-type: none; +} + +.asyncapi__schemas-list-item { + margin-bottom: 16px; +} +.asyncapi__schemas-list-item:last-child { + margin-bottom: 0; +} + +.asyncapi__schema { + position: relative; + border-radius: 4px; + border: solid 1px rgba(151, 151, 151, 0.26); + background-color: #ffffff; +} +.asyncapi__schema:last-child { + margin-bottom: 0; +} + +.asyncapi__schema-header { + padding: 12px; +} + +.asyncapi__schema-header-title { + font-size: 14px; +} + +.asyncapi__schema-table { + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__schema-table > table { + margin: 0; +} + +.asyncapi__schema-example { + padding: 16px; +} + +.asyncapi__schema-example-header { +} + +.asyncapi__schema-example-header-title { +} + +.asyncapi__schema-example-header-generated-badge { + display: inline-block; +} + +.asyncapi__security { + margin-top: 24px; + background: #fff; + border-radius: 5px; + padding: 16px; +} + +.asyncapi__security-header { +} +.asyncapi__security-header > h2 { + margin: 0 0 24px 0; +} + +.asyncapi__security-table { + margin: 0; +} + +.asyncapi__servers { +} +.asyncapi__servers > div { + margin-top: 24px; + background: #fff; + border-radius: 5px; + padding: 16px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); +} + +.asyncapi__servers-toggle .asyncapi__toggle-header-content { + padding: 0; +} +.asyncapi__servers-toggle--expanded .asyncapi__toggle-header { + padding-bottom: 12px; +} + +.asyncapi__servers-header { +} +.asyncapi__servers-header > h2 { + margin: 0 0 24px 0; +} + +.asyncapi__servers-list { + margin: 0; + padding: 0; + list-style-type: none; +} + +.asyncapi__servers-list-item { + margin-bottom: 16px; +} +.asyncapi__servers-list-item:last-child { + margin-bottom: 0; +} + +.asyncapi__server { + position: relative; + border-radius: 4px; + border: solid 1px rgba(151, 151, 151, 0.26); + background-color: #ffffff; +} + +.asyncapi__server-header { + padding: 12px; +} + +.asyncapi__server-header-stage { + color: #107ee3; + margin-right: 6px; +} + +.asyncapi__server-header-protocol { + color: #18873d; + margin-right: 6px; +} + +.asyncapi__server-description { + border-top: solid 1px rgba(151, 151, 151, 0.26); + padding: 12px; +} + +.asyncapi__servers-table { + margin-bottom: 0; +} +.asyncapi__servers-table > .asyncapi__table { + margin: 0; +} + +.asyncapi__server-variables { +} + +.asyncapi__server-variables-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__server-variables-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__server-variables-table { + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__server-variables-table > table { + margin: 0; +} +.asyncapi__server-variables-table .asyncapi__table-body > tr:last-child td { + border-bottom: none; +} + +.asyncapi__server-variables-table-cell { + padding: 0; + border-bottom: none; +} + +.asyncapi__server-expand-icon { + display: inline-block; + position: relative; + width: 10px; + height: 10px; + margin-right: 10px; + transform-origin: 50% 50%; + transition: 0.5s ease; + cursor: pointer; +} +.asyncapi__server-expand-icon:before { + content: ''; + font-family: 'SAP-icons'; + position: absolute; + color: #0071d4; + font-size: 12px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.asyncapi__server-expand-icon--open { + transform: rotate(90deg); +} + +.asyncapi__server-variables-enum-list { + margin: 0 0 0 15px; + padding: 0; +} + +.asyncapi__server-variables-enum-list-item { +} + +.asyncapi__server-security { +} + +.asyncapi__server-security-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__server-security-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__server-security-table { + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__server-security-table > table { + margin: 0; +} +.asyncapi__server-security-table .asyncapi__table-body > tr:last-child td { + border-bottom: none; +} + +.asyncapi__server-security-table-cell { + padding: 0; + border-bottom: none; +} + +.asyncapi__server-security-flows-list { + margin: 0; + padding: 0; + list-style-type: none; +} +.asyncapi__server-security-flows-list a { + color: #0b74de; +} + +.asyncapi__server-security-flows-list-item { + margin-top: 12px; +} +.asyncapi__server-security-flows-list-item:first-child { + margin-top: 0; +} + +.asyncapi__server-security-flow { + background: #fafafa; + border: 1px solid #dae1e7; + padding: 12px; + border-radius: 5px; +} + +.asyncapi__server-security-flow-list { + margin: 0; + padding: 0; + list-style-type: none; +} + +.asyncapi__server-security-flow-list-item { + padding: 3px 0; +} +.asyncapi__server-security-flow-list-item > span { + margin-left: 12px; +} +.asyncapi__server-security-flow-list-item > a { + margin-left: 12px; +} + +.asyncapi__server-security-flows-table-cell { + border-bottom: solid 1px #d4d4d4; + padding: 12px; +} + +.asyncapi__server-security-oauth2 { + border-bottom: none; +} +.asyncapi__server-security-oauth2 > td { + border-bottom: none; +} + +.asyncapi__server-security-scopes-list { + margin: 0; + padding: 0; + list-style-type: none; + display: inline-block; + margin-left: 6px; +} + +.asyncapi__server-security-scopes-list-item { + display: inline-block; + margin-right: 6px; +} + +.asyncapi__server-security-scope { + display: inline-block; + font-weight: bold; + font-size: 11px; + line-height: 18px; + border-radius: 3px; + padding: 0px 5px; + text-align: center; + text-transform: uppercase; + background: #e2eaf2; + color: #18873d; +} + +.asyncapi__channels { +} +.asyncapi__channels > div { + margin-top: 24px; + background: #fff; + border-radius: 5px; + padding: 16px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); +} + +.asyncapi__channels-toggle .asyncapi__toggle-header-content { + padding: 0; +} +.asyncapi__channels-toggle--expanded .asyncapi__toggle-header { + padding-bottom: 12px; +} + +.asyncapi__channels-header { +} +.asyncapi__channels-header > h2 { + margin: 0 0 24px 0; +} + +.asyncapi__channels-list { + padding: 0; + margin: 0; + list-style-type: none; +} + +.asyncapi__channels-list-item { + margin-bottom: 16px; +} +.asyncapi__channels-list-item:last-child { + margin-bottom: 0; +} + +.asyncapi__channel { + position: relative; + border-radius: 4px; + border: solid 1px rgba(151, 151, 151, 0.26); + background-color: #ffffff; +} + +.asyncapi__channel-header { + padding: 12px; +} +.asyncapi__channel-header > h3 { + color: #0b74de; + font-size: 15px; +} + +.asyncapi__channel-header-badges { + margin: 0; + padding: 0; + list-style-type: none; + display: inline-block; +} + +.asyncapi__channel-header-badges > li { + display: inline-block; + margin-right: 6px; +} + +.asyncapi__channel-header-badges-deprecated-badge { + display: inline-block; + margin-right: 6px; +} + +.asyncapi__channel-header-badges-publish-badge { + display: inline-block; + margin-right: 6px; +} + +.asyncapi__channel-header-badges-subscribe-badge { + display: inline-block; + margin-right: 6px; +} + +.asyncapi__channel-header-title { + font-size: 14px; +} + +.asyncapi__channel-operations { +} +.asyncapi__channel-operations .asyncapi__message { + border: none; +} + +.asyncapi__channel-operations-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__channel-operations-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__channel-operations-header-oneOf { + border-top: solid 1px rgba(151, 151, 151, 0.26); +} + +.asyncapi__channel-operations-list { + margin: 0; + padding: 0; + list-style-type: none; +} +.asyncapi__channel-operations-list .asyncapi__messages { + padding: 16px; +} +.asyncapi__channel-operations-list .asyncapi__messages-list { + margin: 0; + padding: 0; + list-style-type: none; +} +.asyncapi__channel-operations-list .asyncapi__messages-list-item { + margin-bottom: 16px; +} +.asyncapi__channel-operations-list .asyncapi__messages-list-item:last-child { + margin-bottom: 0; +} +.asyncapi__channel-operations-list + .asyncapi__messages-list-item + .asyncapi__message { + position: relative; + border-radius: 4px; + border: solid 1px rgba(151, 151, 151, 0.26); + background-color: #ffffff; +} + +.asyncapi__channel-operations-list-item { +} + +.asyncapi__channel-operation-oneOf-subscribe-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); + border-bottom: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__channel-operation-oneOf-subscribe-header > h4 { + padding: 12px; + margin: 0; +} +.asyncapi__channel-operation-oneOf-subscribe-header > h4 > .asyncapi__badge { + margin-right: 6px; +} + +.asyncapi__channel-operation-oneOf-publish-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); + border-bottom: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__channel-operation-oneOf-publish-header > h4 { + padding: 12px; + margin: 0; +} +.asyncapi__channel-operation-oneOf-publish-header > h4 > .asyncapi__badge { + margin-right: 6px; +} + +.asyncapi__channel-operation { +} + +.asyncapi__channel-parameters { +} + +.asyncapi__channel-parameters-header { + color: #32363a; + background-color: #fafafa; + border-top: solid 1px rgba(151, 151, 151, 0.26); +} +.asyncapi__channel-parameters-header > h4 { + padding: 12px; + margin: 0; +} + +.asyncapi__channel-parameters-list { + margin: 0; + padding: 0; + list-style-type: none; +} + +.asyncapi__channel-parameters-list-item { +} + +.asyncapi__channel-parameter { + position: relative; +} + +.asyncapi__channel-parameter-header { +} + +.asyncapi__channel-parameter-header-description { +} + +.asyncapi__channel-parameter-schema { +} +.asyncapi__channel-parameter-schema > .asyncapi__schema { + padding: 0; + border: none; +} +.asyncapi__channel-parameter-schema > .asyncapi__schema:before { + content: ''; + position: relative; + border: none; +} + +.asyncapi__error { + background-color: #ffffff; + border-left: 6px solid #f44336; + border-radius: 4px; + color: #32363a; + font-family: '72'; + font-size: 13px; + margin-bottom: 24px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); +} + +.asyncapi__error-header { + padding: 16px; + box-shadow: inset 0 -1px 0 0 rgba(115, 121, 128, 0.15); + font-weight: bold; + position: relative; + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: center; +} +.asyncapi__error-header h2 { + flex-grow: 1; + padding: 0; + margin: 0; +} +.asyncapi__error-header > .asyncapi__toggle-header-content { + padding: 0; +} + +.asyncapi__error-body { + font-weight: normal; + position: relative; +} + +.asyncapi__error-body-pre { + margin: 0; + padding: 12px; + background-color: #263238; + white-space: pre-wrap; + word-break: break-word; + color: #fff; + border-bottom-right-radius: 4px; + font-size: 11px; +} + +.asyncapi__error-body-code { + font-family: monospace; + display: block; +} + +.asyncapi__enum { + line-height: 2; + border-style: solid; + border-color: #dae1e7; + border-radius: 0.25rem; + border-width: 1px; + margin-left: 0.25rem; + padding: 0 0.5rem; + color: #f6993f; +} From 237595f3b45b98eb75573e156c07a2f1946a69e2 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 11:57:14 +0200 Subject: [PATCH 09/26] fix(api-docs): improve the styling of the asyncapi documentation in dark mode --- .../AsyncApiDefinitionWidget/style.css | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css index 085e056da6..0237c24d52 100644 --- a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css +++ b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/style.css @@ -15,13 +15,13 @@ */ .asyncapi { - font-family: '72'; + /*font-family: '72';*/ font-size: 14px; line-height: 20px; font-weight: 400; -webkit-font-smoothing: antialiased; font-smoothing: antialiased; - background: #f3f4f5; + /*background: #f3f4f5;*/ } .asyncapi__toggle { @@ -80,8 +80,8 @@ cursor: pointer; } .asyncapi__toggle-arrow:before { - content: '\e0e3'; - font-family: 'SAP-icons'; + content: '>'; + /*font-family: 'SAP-icons';*/ font-size: 14px; } .asyncapi__toggle-arrow--expanded { @@ -106,8 +106,8 @@ margin-left: 6px; } .asyncapi__anchor-icon:before { - content: '\e0ac'; - font-family: 'SAP-icons'; + content: 'šŸ”—'; + /*font-family: 'SAP-icons';*/ } .asyncapi__markdown { @@ -131,7 +131,7 @@ border-radius: 3px; padding: 0px 5px; text-align: center; - background: #e2eaf2; + /*background: #e2eaf2;*/ color: #18873d; } @@ -149,13 +149,13 @@ font-size: 13px; border-radius: 5px; border: solid 1px #d4d4d4; - background-color: #f9fafa; + /*background-color: #f9fafa;*/ } .asyncapi__table-header { width: 100%; color: #939698; - background: #f9fafa; + /*background: #f9fafa;*/ text-transform: uppercase; } @@ -277,7 +277,7 @@ padding: 0px 5px; text-align: center; text-transform: uppercase; - background: #e2eaf2; + /*background: #e2eaf2;*/ } .asyncapi__badge--publish { @@ -313,7 +313,7 @@ display: inline-block; mix-blend-mode: multiply; border-radius: 4px; - background-color: #e2eaf2; + /*background-color: #e2eaf2;*/ font-size: 11px; font-family: 72; font-weight: 300; @@ -331,7 +331,7 @@ .asyncapi__code { border: solid 1px rgba(137, 145, 154, 0.675); border-radius: 5px; - background: #fff; + /*background: #fff;*/ } .asyncapi__code-header { @@ -349,7 +349,7 @@ margin: 0; font-size: 13px; padding: 12px; - background: #fafafa; + /*background: #fafafa;*/ border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; } @@ -362,7 +362,7 @@ } .asyncapi__info { - background: #fff; + /*background: #fff;*/ border-radius: 5px; padding: 16px; box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); @@ -443,7 +443,7 @@ } .asyncapi__messages > div { margin-top: 24px; - background: #fff; + /*background: #fff;*/ border-radius: 5px; padding: 16px; box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); @@ -488,7 +488,7 @@ position: relative; border-radius: 4px; border: solid 1px rgba(151, 151, 151, 0.26); - background-color: #ffffff; + /*background-color: #ffffff;*/ } .asyncapi__message:last-child { margin-bottom: 0; @@ -529,7 +529,7 @@ .asyncapi__message-headers-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__message-headers-header > h4 { @@ -567,7 +567,7 @@ .asyncapi__message-payload-oneOf-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__message-payload-oneOf-header > h4 { @@ -591,7 +591,7 @@ position: relative; border-radius: 4px; border: solid 1px rgba(151, 151, 151, 0.26); - background-color: #ffffff; + /*background-color: #ffffff;*/ } .asyncapi__message-payload-oneOf-list-item .asyncapi__message-payload:last-child { @@ -603,7 +603,7 @@ .asyncapi__message-payload-anyOf-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__message-payload-anyOf-header > h4 { @@ -627,7 +627,7 @@ position: relative; border-radius: 4px; border: solid 1px rgba(151, 151, 151, 0.26); - background-color: #ffffff; + /*background-color: #ffffff;*/ } .asyncapi__message-payload-anyOf-list-item .asyncapi__message-payload:last-child { @@ -640,7 +640,7 @@ .asyncapi__message-payload-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__message-payload-header > h4 { @@ -682,7 +682,7 @@ } .asyncapi__schemas > div { margin-top: 24px; - background: #fff; + /*background: #fff;*/ border-radius: 5px; padding: 16px; box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); @@ -715,7 +715,7 @@ position: relative; border-radius: 4px; border: solid 1px rgba(151, 151, 151, 0.26); - background-color: #ffffff; + /*background-color: #ffffff;*/ } .asyncapi__schema:last-child { margin-bottom: 0; @@ -752,7 +752,7 @@ .asyncapi__security { margin-top: 24px; - background: #fff; + /*background: #fff;*/ border-radius: 5px; padding: 16px; } @@ -771,7 +771,7 @@ } .asyncapi__servers > div { margin-top: 24px; - background: #fff; + /*background: #fff;*/ border-radius: 5px; padding: 16px; box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); @@ -807,7 +807,7 @@ position: relative; border-radius: 4px; border: solid 1px rgba(151, 151, 151, 0.26); - background-color: #ffffff; + /*background-color: #ffffff;*/ } .asyncapi__server-header { @@ -841,7 +841,7 @@ .asyncapi__server-variables-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__server-variables-header > h4 { @@ -875,8 +875,8 @@ cursor: pointer; } .asyncapi__server-expand-icon:before { - content: ''; - font-family: 'SAP-icons'; + content: '>'; + /*font-family: 'SAP-icons';*/ position: absolute; color: #0071d4; font-size: 12px; @@ -902,7 +902,7 @@ .asyncapi__server-security-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__server-security-header > h4 { @@ -942,7 +942,7 @@ } .asyncapi__server-security-flow { - background: #fafafa; + /*background: #fafafa;*/ border: 1px solid #dae1e7; padding: 12px; border-radius: 5px; @@ -998,7 +998,7 @@ padding: 0px 5px; text-align: center; text-transform: uppercase; - background: #e2eaf2; + /*background: #e2eaf2;*/ color: #18873d; } @@ -1006,7 +1006,7 @@ } .asyncapi__channels > div { margin-top: 24px; - background: #fff; + /*background: #fff;*/ border-radius: 5px; padding: 16px; box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.16); @@ -1042,7 +1042,7 @@ position: relative; border-radius: 4px; border: solid 1px rgba(151, 151, 151, 0.26); - background-color: #ffffff; + /*background-color: #ffffff;*/ } .asyncapi__channel-header { @@ -1092,7 +1092,7 @@ .asyncapi__channel-operations-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__channel-operations-header > h4 { @@ -1129,7 +1129,7 @@ position: relative; border-radius: 4px; border: solid 1px rgba(151, 151, 151, 0.26); - background-color: #ffffff; + /*background-color: #ffffff;*/ } .asyncapi__channel-operations-list-item { @@ -1137,7 +1137,7 @@ .asyncapi__channel-operation-oneOf-subscribe-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); border-bottom: solid 1px rgba(151, 151, 151, 0.26); } @@ -1151,7 +1151,7 @@ .asyncapi__channel-operation-oneOf-publish-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); border-bottom: solid 1px rgba(151, 151, 151, 0.26); } @@ -1171,7 +1171,7 @@ .asyncapi__channel-parameters-header { color: #32363a; - background-color: #fafafa; + /*background-color: #fafafa;*/ border-top: solid 1px rgba(151, 151, 151, 0.26); } .asyncapi__channel-parameters-header > h4 { @@ -1211,7 +1211,7 @@ } .asyncapi__error { - background-color: #ffffff; + /*background-color: #ffffff;*/ border-left: 6px solid #f44336; border-radius: 4px; color: #32363a; From bd68004d83ac073d03f7a0c667b17e5c9dfc2fa4 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Fri, 24 Jul 2020 16:27:06 +0200 Subject: [PATCH 10/26] chore: update yarn.lock --- yarn.lock | 549 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 523 insertions(+), 26 deletions(-) diff --git a/yarn.lock b/yarn.lock index 557ced9add..816f65f86c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,6 +40,18 @@ resolved "https://registry.npmjs.org/@ardatan/aggregate-error/-/aggregate-error-0.0.1.tgz#1403ac5de10d8ca689fc1f65844c27179ae1d44f" integrity sha512-UQ9BequOTIavs0pTHLMwQwKQF8tTV1oezY/H2O9chA+JNPFZSua55xpU5dPSjAU9/jLJ1VwU+HJuTVN8u7S6Fg== +"@asyncapi/parser@0.16.2": + version "0.16.2" + resolved "https://registry.npmjs.org/@asyncapi/parser/-/parser-0.16.2.tgz#6e0806d0a751e999499212e52926a6dc6ec251fe" + integrity sha512-dagGD6VFAgl/zLQuoWAfi48i74wv32naV6WcvazcpvEXshW3Q//OrUyRFa6EbY0lmIMXeasc7HKm40AUJ920ug== + dependencies: + ajv "^6.10.1" + asyncapi "^2.6.1" + js-yaml "^3.13.1" + json-schema-ref-parser "^7.1.0" + node-fetch "^2.6.0" + tiny-merge-patch "^0.1.2" + "@babel/code-frame@7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" @@ -1137,6 +1149,14 @@ "@babel/plugin-transform-react-jsx-source" "^7.10.4" "@babel/plugin-transform-react-pure-annotations" "^7.10.4" +"@babel/runtime-corejs2@^7.10.4": + version "7.11.2" + resolved "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.11.2.tgz#700a03945ebad0d31ba6690fc8a6bcc9040faa47" + integrity sha512-AC/ciV28adSSpEkBglONBWq4/Lvm6GAZuxIoyVtsnUpZMl0bxLtoChEnYAkP+47KyOCayZanojtflUEUJtR/6Q== + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.4" + "@babel/runtime-corejs2@^7.8.7": version "7.10.3" resolved "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.10.3.tgz#81bc99a96bfcb6db3f0dcf73fdc577cc554d341b" @@ -1239,6 +1259,11 @@ resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@braintree/sanitize-url@^4.0.0": + version "4.1.1" + resolved "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-4.1.1.tgz#671b3cfdbcc40d1449036ce586e882ab6150828e" + integrity sha512-epVksusKVEpwBs2vRg3SWssxn9KXs9CxEYNOcgeSRLRjq070ABj5bLPxkmtQpVeSPCHj8kfAE9J6z2WsLr4wZg== + "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -1832,6 +1857,31 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@kyleshockey/object-assign-deep@^0.4.2": + version "0.4.2" + resolved "https://registry.npmjs.org/@kyleshockey/object-assign-deep/-/object-assign-deep-0.4.2.tgz#84900f0eefc372798f4751b5262830b8208922ec" + integrity sha1-hJAPDu/DcnmPR1G1JigwuCCJIuw= + +"@kyleshockey/xml@^1.0.2": + version "1.0.2" + resolved "https://registry.npmjs.org/@kyleshockey/xml/-/xml-1.0.2.tgz#81fad3d7c33da2ba2639db095db3db24c2921f70" + integrity sha512-iMo32MPLcI9cPxs3YL5kmKxKgDmkSZDCFEqIT5eRk7d/Ll8r4X3SwGYSigzALd6+RHWlFEmjL1QyaQ15xDZFlw== + dependencies: + stream "^0.0.2" + +"@kyma-project/asyncapi-react@^0.6.1": + version "0.6.2" + resolved "https://registry.npmjs.org/@kyma-project/asyncapi-react/-/asyncapi-react-0.6.2.tgz#99539f630b511d4f7298805dfaf545956192141c" + integrity sha512-yGgYv0XyxI5PxNv0GzTqABsXKwFETlZwBWDqwfUtwirTOTIFyLU69lHbMtM9gn0hPFciP09uHmKt8+8gOpMKvA== + dependencies: + "@asyncapi/parser" "0.16.2" + constate "^1.2.0" + dompurify "^1.0.11" + markdown-it "^9.1.0" + merge "^1.2.1" + openapi-sampler "^1.0.0-beta.15" + react-use "^12.2.0" + "@lerna/add@3.21.0": version "3.21.0" resolved "https://registry.npmjs.org/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b" @@ -2517,6 +2567,11 @@ npmlog "^4.1.2" write-file-atomic "^2.3.0" +"@material-icons/font@^1.0.2": + version "1.0.3" + resolved "https://registry.npmjs.org/@material-icons/font/-/font-1.0.3.tgz#f722e5a69a03f20ef47d015cb69420bebeeaabe5" + integrity sha512-aIRd0Z9b/HJ/O24KOaP7dNsXypMnXhpWrpLVYvQB/JesVqXYSbioYND200sR+C14a0LSCp+qWnWCnSXmN1hWGw== + "@material-ui/core@^4.9.1": version "4.9.7" resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.9.7.tgz#0c1caf123278770f34c5d8e9ecd9e1314f87a621" @@ -4601,6 +4656,13 @@ dependencies: "@types/react" "*" +"@types/react-wait@^0.3.0": + version "0.3.1" + resolved "https://registry.npmjs.org/@types/react-wait/-/react-wait-0.3.1.tgz#193cbd8fe86baa53b6f65dfa73f03d562f462a27" + integrity sha512-BS9AEjWZItDgpx6LlICcuf53M27zBFCsHx/llCbrmrt/WI7ecG2LGquCss3n8O8bwEDiTX4yYLjy8yLeIfgYTg== + dependencies: + "@types/react" "*" + "@types/react@*", "@types/react@^16.9": version "16.9.37" resolved "https://registry.npmjs.org/@types/react/-/react-16.9.37.tgz#8fb93e7dbd5b1d3796f69aa979a7fe0439bc7bea" @@ -4609,6 +4671,13 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/react@16.4.6": + version "16.4.6" + resolved "https://registry.npmjs.org/@types/react/-/react-16.4.6.tgz#5024957c6bcef4f02823accf5974faba2e54fada" + integrity sha512-9LDZdhsuKSc+DjY65SjBkA958oBWcTWSVWAd2cD9XqKBjhGw1KzAkRhWRw2eIsXvaIE/TOTjjKMFVC+JA1iU4g== + dependencies: + csstype "^2.2.0" + "@types/recursive-readdir@^2.2.0": version "2.2.0" resolved "https://registry.npmjs.org/@types/recursive-readdir/-/recursive-readdir-2.2.0.tgz#b39cd5474fd58ea727fe434d5c68b7a20ba9121c" @@ -4716,6 +4785,13 @@ dependencies: "@types/superagent" "*" +"@types/swagger-ui-react@^3.23.2": + version "3.23.2" + resolved "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-3.23.2.tgz#153eb466785763b514459a300772a43257a3c16b" + integrity sha512-EMD/EHdGQ6rBjfKE05x2syyw4kMZiA0qRIlv0q9EpQWYWWBhHwffSR0ljSHCy+pbX8zdOct08w8hVA0V0SAo0Q== + dependencies: + "@types/react" "*" + "@types/tapable@*", "@types/tapable@^1.0.5": version "1.0.5" resolved "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.5.tgz#9adbc12950582aa65ead76bffdf39fe0c27a3c02" @@ -5273,6 +5349,16 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.5.5, ajv@^6.7.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.10.1: + version "6.12.3" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -5594,7 +5680,7 @@ arg@^4.1.0: resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== -argparse@^1.0.7: +argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -5828,6 +5914,11 @@ async@^3.2.0: resolved "https://registry.npmjs.org/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw== +asyncapi@^2.6.1: + version "2.6.1" + resolved "https://registry.npmjs.org/asyncapi/-/asyncapi-2.6.1.tgz#5e35124abfd416f050a239bf72cb8eef7ebeda66" + integrity sha512-ROszLQMYzyp/CzPyLhuT/9NpJXxI7wrjv6yW8JpA/XVMEWCqyVXr9jajJhs9d/863+ispS+ptGhg1PC17AnIzQ== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -5848,6 +5939,13 @@ atob@^2.1.2: resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +autolinker@^3.11.0: + version "3.14.1" + resolved "https://registry.npmjs.org/autolinker/-/autolinker-3.14.1.tgz#6ae4b812b6eaf42d4d68138b9e67757cbf2bc1e4" + integrity sha512-yvsRHIaY51EYDml6MGlbqyJGfl4n7zezGYf+R7gvM8c5LNpRGc4SISkvgAswSS8SWxk/OrGCylKV9mJyVstz7w== + dependencies: + tslib "^1.9.3" + autoprefixer@^9.7.2: version "9.7.4" resolved "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" @@ -6233,7 +6331,7 @@ base64-arraybuffer@^0.1.5: resolved "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.2.0: version "1.3.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== @@ -6544,6 +6642,11 @@ btoa-lite@^1.0.0: resolved "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= +btoa@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" + integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== + buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" @@ -6601,7 +6704,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.5.0: +buffer@^5.5.0, buffer@^5.6.0: version "5.6.0" resolved "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== @@ -7483,6 +7586,11 @@ constants-browserify@^1.0.0: resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= +constate@^1.2.0: + version "1.3.2" + resolved "https://registry.npmjs.org/constate/-/constate-1.3.2.tgz#fa5f0fc292207f1ec21b46a5eb81f59c8b0a8b84" + integrity sha512-aaILV4vXwGTUZaQZHS5F1xBV8wRCR0Ow1505fdkS5/BPg6hbQrhNqdHL4wgxWgaDeEj43mu/Fb+LhqOKTMcrgQ== + contains-path@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" @@ -7613,7 +7721,7 @@ cookie@0.4.0: resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== -cookie@^0.4.1: +cookie@^0.4.1, cookie@~0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== @@ -7640,7 +7748,7 @@ copy-descriptor@^0.1.0: resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -copy-to-clipboard@^3.0.8, copy-to-clipboard@^3.2.0: +copy-to-clipboard@^3, copy-to-clipboard@^3.0.8, copy-to-clipboard@^3.1.0, copy-to-clipboard@^3.2.0: version "3.3.1" resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== @@ -7660,7 +7768,7 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1: resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== -core-js@^2.4.0, core-js@^2.5.7, core-js@^2.6.5: +core-js@^2.4.0, core-js@^2.5.7, core-js@^2.6.11, core-js@^2.6.5: version "2.6.11" resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== @@ -7758,7 +7866,7 @@ cross-env@^7.0.0: dependencies: cross-spawn "^7.0.1" -cross-fetch@3.0.5: +cross-fetch@3.0.5, cross-fetch@^3.0.5: version "3.0.5" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.5.tgz#2739d2981892e7ab488a7ad03b92df2816e03f4c" integrity sha512-FFLcLtraisj5eteosnX1gf01qYDCOc4fDy0+euOt8Kn9YBY2NtXL/pCoYPavw24NIQkQqm5ZOLsGD5Zzj0gyew== @@ -7958,7 +8066,7 @@ css-what@^3.2.1: resolved "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== -css.escape@^1.5.1: +css.escape@1.5.1, css.escape@^1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= @@ -8323,7 +8431,7 @@ deep-equal@^1.0.1, deep-equal@^1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@^0.6.0: +deep-extend@0.6.0, deep-extend@^0.6.0, deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== @@ -8736,6 +8844,16 @@ domhandler@^3.0, domhandler@^3.0.0: dependencies: domelementtype "^2.0.1" +dompurify@^1.0.11: + version "1.0.11" + resolved "https://registry.npmjs.org/dompurify/-/dompurify-1.0.11.tgz#fe0f4a40d147f7cebbe31a50a1357539cfc1eb4d" + integrity sha512-XywCTXZtc/qCX3iprD1pIklRVk/uhl8BKpkTxr+ZyMVUzSUg7wkQXRBp/euJ5J5moa1QvfpvaPQVP71z1O59dQ== + +dompurify@^2.0.7: + version "2.0.12" + resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.0.12.tgz#284a2b041e1c60b8e72d7b4d2fadad36141254ae" + integrity sha512-Fl8KseK1imyhErHypFPA8qpq9gPzlsJ/EukA6yk9o0gX23p1TzC+rh9LqNg1qvErRTc0UNMYlKxEGSfSh43NDg== + domutils@1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" @@ -8892,6 +9010,11 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emitter-component@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz#065e2dbed6959bf470679edabeaf7981d1003ab6" + integrity sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY= + "emoji-regex@>=6.0.0 <=6.1.1": version "6.1.1" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" @@ -8968,7 +9091,7 @@ enquirer@^2.3.5: dependencies: ansi-colors "^3.2.1" -entities@^1.1.1, entities@^1.1.2: +entities@^1.1.1, entities@^1.1.2, entities@~1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== @@ -9063,7 +9186,7 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es5-ext@^0.10.35, es5-ext@^0.10.50: +es5-ext@^0.10.35, es5-ext@^0.10.45, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: version "0.10.53" resolved "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== @@ -9077,7 +9200,7 @@ es5-shim@^4.5.13: resolved "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.13.tgz#5d88062de049f8969f83783f4a4884395f21d28b" integrity sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw== -es6-iterator@~2.0.3: +es6-iterator@^2.0.3, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= @@ -9111,6 +9234,16 @@ es6-symbol@^3.1.1, es6-symbol@~3.1.3: d "^1.0.1" ext "^1.1.2" +es6-weak-map@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + esbuild@0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.6.3.tgz#a957e22f2503c745793514388110f9b55b3a6f83" @@ -9442,6 +9575,14 @@ etag@~1.8.1: resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + event-stream@=3.3.4: version "3.3.4" resolved "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" @@ -9737,6 +9878,13 @@ fast-glob@^3.0.3, fast-glob@^3.1.1: micromatch "^4.0.2" picomatch "^2.2.1" +fast-json-patch@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz#18150d36c9ab65c7209e7d4eb113f4f8eaabe6d9" + integrity sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -10087,6 +10235,11 @@ for-own@^1.0.0: dependencies: for-in "^1.0.1" +foreach@^2.0.4: + version "2.0.5" + resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -10133,7 +10286,7 @@ fork-ts-checker-webpack-plugin@^4.0.5: tapable "^1.0.0" worker-rpc "^0.1.0" -form-data@^2.3.1: +form-data@^2.3.1, form-data@^2.3.2: version "2.5.1" resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== @@ -11041,6 +11194,11 @@ highlight.js@~9.13.0: resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A== +highlight.js@~9.15.0, highlight.js@~9.15.1: + version "9.15.10" + resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2" + integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw== + history@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/history/-/history-5.0.0.tgz#0cabbb6c4bbf835addb874f8259f6d25101efd08" @@ -11387,7 +11545,7 @@ identity-obj-proxy@3.0.0: dependencies: harmony-reflect "^1.4.6" -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.1.13" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== @@ -11429,7 +11587,7 @@ immer@1.10.0: resolved "https://registry.npmjs.org/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== -immutable@>=3.8.2, immutable@^3.8.2: +immutable@>=3.8.2, immutable@^3.8.1, immutable@^3.8.2, immutable@^3.x.x: version "3.8.2" resolved "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= @@ -12069,6 +12227,11 @@ is-potential-custom-element-name@^1.0.0: resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= +is-promise@^2.1: + version "2.2.2" + resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + is-promise@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -12242,6 +12405,13 @@ isobject@^4.0.0: resolved "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== +isomorphic-form-data@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isomorphic-form-data/-/isomorphic-form-data-2.0.0.tgz#9f6adf1c4c61ae3aefd8f110ab60fb9b143d6cec" + integrity sha512-TYgVnXWeESVmQSg4GLVbalmQ+B4NPi/H4eWxqALKj63KsUrcu301YDjBqaOw3h+cbak7Na4Xyps3BiptHtxTfg== + dependencies: + form-data "^2.3.2" + isstream@~0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -12749,6 +12919,11 @@ js-cookie@^2.2.1: resolved "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== +js-file-download@^0.4.1: + version "0.4.12" + resolved "https://registry.npmjs.org/js-file-download/-/js-file-download-0.4.12.tgz#10c70ef362559a5b23cdbdc3bd6f399c3d91d821" + integrity sha512-rML+NkoD08p5Dllpjo0ffy4jRHeY6Zsapvr/W86N7E0yuzAO6qa5X9+xog6zQNlH102J7IXljNY2FtS6Lj3ucg== + js-string-escape@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -12772,6 +12947,14 @@ js-yaml@^3.13.1, js-yaml@^3.8.3: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.14.0: + version "3.14.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -12884,6 +13067,13 @@ json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-bet resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-pointer@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/json-pointer/-/json-pointer-0.6.0.tgz#8e500550a6aac5464a473377da57aa6cc22828d7" + integrity sha1-jlAFUKaqxUZKRzN32leqbMIoKNc= + dependencies: + foreach "^2.0.4" + json-schema-compare@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz#dd601508335a90c7f4cfadb6b2e397225c908e56" @@ -12900,6 +13090,15 @@ json-schema-merge-allof@^0.6.0: json-schema-compare "^0.2.2" lodash "^4.17.4" +json-schema-ref-parser@^7.1.0: + version "7.1.4" + resolved "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-7.1.4.tgz#abb3f2613911e9060dc2268477b40591753facf0" + integrity sha512-AD7bvav0vak1/63w3jH8F7eHId/4E4EPdMAEZhGxtjktteUv9dnNB/cJy6nVnMyoTPBJnLwFK6tiQPSTeleCtQ== + dependencies: + call-me-maybe "^1.0.1" + js-yaml "^3.13.1" + ono "^6.0.0" + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -13493,7 +13692,7 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= -lodash.debounce@^4.0.8: +lodash.debounce@^4, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= @@ -13671,6 +13870,14 @@ lowercase-keys@^2.0.0: resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lowlight@1.12.1: + version "1.12.1" + resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.12.1.tgz#014acf8dd73a370e02ff1cc61debcde3bb1681eb" + integrity sha512-OqaVxMGIESnawn+TU/QMV5BJLbUghUfjDWPAtFqDYDmDtr4FnB+op8xM+pR7nKlauHNUHXGt0VgWatFB8voS5w== + dependencies: + fault "^1.0.2" + highlight.js "~9.15.0" + lowlight@^1.14.0: version "1.14.0" resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.14.0.tgz#83ebc143fec0f9e6c0d3deffe01be129ce56b108" @@ -13694,6 +13901,13 @@ lru-cache@^5.0.0, lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-queue@0.1: + version "0.1.0" + resolved "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM= + dependencies: + es5-ext "~0.10.2" + macos-release@^2.2.0: version "2.3.0" resolved "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" @@ -13817,6 +14031,17 @@ markdown-it@^10.0.0: mdurl "^1.0.1" uc.micro "^1.0.5" +markdown-it@^9.1.0: + version "9.1.0" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-9.1.0.tgz#df9601c168568704d554b1fff9af0c5b561168d9" + integrity sha512-xHKG4C8iPriyfu/jc2hsCC045fKrMQ0VexX2F1FGYiRxDxqMB2aAhF8WauJ3fltn2kb90moGBkiiEdooGIg55w== + dependencies: + argparse "^1.0.7" + entities "~1.1.1" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + markdown-to-jsx@^6.11.4: version "6.11.4" resolved "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz#b4528b1ab668aef7fe61c1535c27e837819392c5" @@ -13884,6 +14109,20 @@ memoize-one@^5.1.1: resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== +memoizee@^0.4.12: + version "0.4.14" + resolved "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57" + integrity sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg== + dependencies: + d "1" + es5-ext "^0.10.45" + es6-weak-map "^2.0.2" + event-emitter "^0.3.5" + is-promise "^2.1" + lru-queue "0.1" + next-tick "1" + timers-ext "^0.1.5" + memoizerific@^1.11.3: version "1.11.3" resolved "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" @@ -13977,6 +14216,11 @@ merge2@^1.2.3, merge2@^1.3.0: resolved "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== +merge@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" + integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== + methods@^1.0.0, methods@^1.1.1, methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -14397,7 +14641,7 @@ nan@^2.14.0: resolved "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== -nano-css@^5.2.1: +nano-css@^5.1.0, nano-css@^5.2.1: version "5.3.0" resolved "https://registry.npmjs.org/nano-css/-/nano-css-5.3.0.tgz#9d3cd29788d48b6a07f52aa4aec7cf4da427b6b5" integrity sha512-uM/9NGK9/E9/sTpbIZ/bQ9xOLOIHZwrrb/CRlbDHBU/GFS7Gshl24v/WJhwsVViWkpOXUmiZ66XO7fSB4Wd92Q== @@ -14457,6 +14701,11 @@ neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +next-tick@1: + version "1.1.0" + resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + next-tick@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" @@ -15048,6 +15297,11 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +ono@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/ono/-/ono-6.0.1.tgz#1bc14ffb8af1e5db3f7397f75b88e4a2d64bbd71" + integrity sha512-5rdYW/106kHqLeG22GE2MHKq+FlsxMERZev9DCzQX1zwkxnFwBivSn5i17a5O/rDmOJOdf4Wyt80UZljzx9+DA== + open@^6.3.0: version "6.4.0" resolved "https://registry.npmjs.org/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" @@ -15063,6 +15317,13 @@ open@^7.0.0, open@^7.0.2: is-docker "^2.0.0" is-wsl "^2.1.1" +openapi-sampler@^1.0.0-beta.15: + version "1.0.0-beta.16" + resolved "https://registry.npmjs.org/openapi-sampler/-/openapi-sampler-1.0.0-beta.16.tgz#7813524d5b88d222efb772ceb5a809075d6d9174" + integrity sha512-05+GvwMagTY7GxoDQoWJfmAUFlxfebciiEzqKmu4iq6+MqBEn62AMUkn0CTxyKhnUGIaR2KXjTeslxIeJwVIOw== + dependencies: + json-pointer "^0.6.0" + opencollective-postinstall@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" @@ -15712,6 +15973,11 @@ pend@~1.2.0: resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU= + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -16569,7 +16835,7 @@ promzard@^0.3.0: dependencies: read "1" -prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -16719,6 +16985,11 @@ qs@^6.5.1, qs@^6.6.0: resolved "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== +qs@^6.9.4: + version "6.9.4" + resolved "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" + integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ== + qs@~6.5.2: version "6.5.2" resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -16732,6 +17003,11 @@ query-string@^4.1.0: object-assign "^4.1.0" strict-uri-encode "^1.0.0" +querystring-browser@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/querystring-browser/-/querystring-browser-1.0.4.tgz#f2e35881840a819bc7b1bf597faf0979e6622dc6" + integrity sha1-8uNYgYQKgZvHsb9Zf68JeeZiLcY= + querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -16762,7 +17038,7 @@ raf-schd@^4.0.2: resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== -raf@^3.4.1: +raf@^3.1.0, raf@^3.4.1: version "3.4.1" resolved "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -16784,7 +17060,7 @@ ramda@^0.25.0: resolved "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -16884,6 +17160,22 @@ react-clientside-effect@^1.2.2: dependencies: "@babel/runtime" "^7.0.0" +react-copy-to-clipboard@5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz#8eae107bb400be73132ed3b6a7b4fb156090208e" + integrity sha512-ELKq31/E3zjFs5rDWNCfFL4NvNFQvGRoJdAKReD/rUPA+xxiLPQmZBZBvy2vgH7V0GE9isIQpT9WXbwIVErYdA== + dependencies: + copy-to-clipboard "^3" + prop-types "^15.5.8" + +react-debounce-input@^3.2.0: + version "3.2.2" + resolved "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.2.2.tgz#d2cc99c1ce47fae89037965f5699edc1b0317197" + integrity sha512-RIBu68Cq/gImKz/2h1cE042REDqyqj3D+7SJ3lnnIpJX0ht9D9PfH7KAnL+SgDz6hvKa9pZS2CnAxlkrLmnQlg== + dependencies: + lodash.debounce "^4" + prop-types "^15.7.2" + react-dev-utils@^10.2.1: version "10.2.1" resolved "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.1.tgz#f6de325ae25fa4d546d09df4bb1befdc6dd19c19" @@ -17056,6 +17348,27 @@ react-hotkeys@2.0.0: dependencies: prop-types "^15.6.1" +react-immutable-proptypes@2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/react-immutable-proptypes/-/react-immutable-proptypes-2.1.0.tgz#023d6f39bb15c97c071e9e60d00d136eac5fa0b4" + integrity sha1-Aj1vObsVyXwHHp5g0A0TbqxfoLQ= + +react-immutable-pure-component@^1.1.1: + version "1.2.3" + resolved "https://registry.npmjs.org/react-immutable-pure-component/-/react-immutable-pure-component-1.2.3.tgz#fa33638df68cfe9f73ccbee1d5861c17f3053f86" + integrity sha512-kNy2A/fDrSuR8TKwB+4ynmItmp1vgF87tWxxfmadwDYo2J3ANipHqTjDIBvJvJ7libvuh76jIbvmK0krjtKH1g== + optionalDependencies: + "@types/react" "16.4.6" + +react-inspector@^2.3.0: + version "2.3.1" + resolved "https://registry.npmjs.org/react-inspector/-/react-inspector-2.3.1.tgz#f0eb7f520669b545b441af9d38ec6d706e5f649c" + integrity sha512-tUUK7t3KWgZEIUktOYko5Ic/oYwvjEvQUFAGC1UeMeDaQ5za2yZFtItJa2RTwBJB//NxPr000WQK6sEbqC6y0Q== + dependencies: + babel-runtime "^6.26.0" + is-dom "^1.0.9" + prop-types "^15.6.1" + react-inspector@^4.0.0: version "4.0.1" resolved "https://registry.npmjs.org/react-inspector/-/react-inspector-4.0.1.tgz#0f888f78ff7daccbc7be5d452b20c96dc6d5fbb8" @@ -17065,7 +17378,7 @@ react-inspector@^4.0.0: is-dom "^1.0.9" prop-types "^15.6.1" -react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: +react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: version "16.13.1" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -17085,7 +17398,7 @@ react-lazylog@^4.5.2: text-encoding-utf-8 "^1.0.1" whatwg-fetch "^2.0.4" -react-lifecycles-compat@^3.0.4: +react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== @@ -17104,6 +17417,15 @@ react-markdown@^4.3.1: unist-util-visit "^1.3.0" xtend "^4.0.1" +react-motion@^0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316" + integrity sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ== + dependencies: + performance-now "^0.2.0" + prop-types "^15.5.8" + raf "^3.1.0" + react-popper-tooltip@^2.8.3: version "2.10.1" resolved "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-2.10.1.tgz#e10875f31916297c694d64a677d6f8fa0a48b4d1" @@ -17125,6 +17447,19 @@ react-popper@^1.3.6: typed-styles "^0.0.7" warning "^4.0.2" +react-redux@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/react-redux/-/react-redux-5.1.2.tgz#b19cf9e21d694422727bf798e934a916c4080f57" + integrity sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q== + dependencies: + "@babel/runtime" "^7.1.2" + hoist-non-react-statics "^3.3.0" + invariant "^2.2.4" + loose-envify "^1.1.0" + prop-types "^15.6.1" + react-is "^16.6.0" + react-lifecycles-compat "^3.0.0" + react-redux@^7.1.1: version "7.2.0" resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" @@ -17180,6 +17515,17 @@ react-string-replace@^0.4.1: dependencies: lodash "^4.17.4" +react-syntax-highlighter@=12.2.1: + version "12.2.1" + resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-12.2.1.tgz#14d78352da1c1c3f93c6698b70ec7c706b83493e" + integrity sha512-CTsp0ZWijwKRYFg9xhkWD4DSpQqE4vb2NKVMdPAkomnILSmsNBHE0n5GuI5zB+PU3ySVvXvdt9jo+ViD9XibCA== + dependencies: + "@babel/runtime" "^7.3.1" + highlight.js "~9.15.1" + lowlight "1.12.1" + prismjs "^1.8.4" + refractor "^2.4.1" + react-syntax-highlighter@^11.0.2: version "11.0.2" resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-11.0.2.tgz#4e3f376e752b20d2f54e4c55652fd663149e4029" @@ -17235,6 +17581,23 @@ react-universal-interface@^0.6.2: resolved "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== +react-use@^12.2.0: + version "12.13.0" + resolved "https://registry.npmjs.org/react-use/-/react-use-12.13.0.tgz#dfefd8145552841f1c2213c2e79966b505a264ba" + integrity sha512-Kh0m9ezIn9xfRycx4jdAgvsYGstGfjTBO2ecIM3+G0RqrpMxTIL5jjYraHYfUzjGBHf7dUhNYBzm5vw5LItVZA== + dependencies: + "@types/react-wait" "^0.3.0" + copy-to-clipboard "^3.1.0" + nano-css "^5.1.0" + react-fast-compare "^2.0.4" + react-wait "^0.3.0" + resize-observer-polyfill "^1.5.1" + screenfull "^5.0.0" + set-harmonic-interval "^1.0.1" + throttle-debounce "^2.0.1" + ts-easing "^0.2.0" + tslib "^1.10.0" + react-use@^15.3.3: version "15.3.3" resolved "https://registry.npmjs.org/react-use/-/react-use-15.3.3.tgz#f16de7a16286c446388e8bd99680952fc3dc9a95" @@ -17267,6 +17630,11 @@ react-virtualized@^9.21.0: prop-types "^15.6.0" react-lifecycles-compat "^3.0.4" +react-wait@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/react-wait/-/react-wait-0.3.0.tgz#0cdd4d919012451a5bc3ab0a16d00c6fd9a8c10b" + integrity sha512-kB5x/kMKWcn0uVr9gBdNz21/oGbQwEQnF3P9p6E9yLfJ9DRcKS0fagbgYMFI0YFOoyKDj+2q6Rwax0kTYJF37g== + react@^16.0.0, react@^16.12.0, react@^16.13.1, react@^16.8.3: version "16.13.1" resolved "https://registry.npmjs.org/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" @@ -17486,7 +17854,14 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -redux@^4.0.4: +redux-immutable@3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/redux-immutable/-/redux-immutable-3.1.0.tgz#cafbd686e0711261119b9c28960935dc47a49d0a" + integrity sha1-yvvWhuBxEmERm5wolgk13EeknQo= + dependencies: + immutable "^3.8.1" + +redux@^4.0.4, redux@^4.0.5: version "4.0.5" resolved "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== @@ -17627,6 +18002,14 @@ remark-parse@^5.0.0: vfile-location "^2.0.0" xtend "^4.0.1" +remarkable@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/remarkable/-/remarkable-2.0.1.tgz#280ae6627384dfb13d98ee3995627ca550a12f31" + integrity sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA== + dependencies: + argparse "^1.0.10" + autolinker "^3.11.0" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -17648,7 +18031,7 @@ repeat-element@^1.1.2: resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -17743,6 +18126,11 @@ requires-port@^1.0.0: resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + resize-observer-polyfill@^1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" @@ -18225,6 +18613,11 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" + integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= + serialize-javascript@^2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" @@ -18955,6 +19348,13 @@ stream-shift@^1.0.0: resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +stream@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz#7f5363f057f6592c5595f00bc80a27f5cec1f0ef" + integrity sha1-f1Nj8Ff2WSxVlfALyAon9c7B8O8= + dependencies: + emitter-component "^1.1.1" + streamsearch@0.1.2, streamsearch@~0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" @@ -19349,6 +19749,68 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" +swagger-client@=3.10.12: + version "3.10.12" + resolved "https://registry.npmjs.org/swagger-client/-/swagger-client-3.10.12.tgz#f49beb7a6f91b6e5778cfbd3fd4064413be6e791" + integrity sha512-h2o7axvFViMc5sxwTjjza84Rhfz+C52wgMKPOT0P05jODjZhldBK7y9EvGt4zvqgzBJHS+FDQBmOT/dGf9SWdw== + dependencies: + "@babel/runtime-corejs2" "^7.10.4" + btoa "^1.2.1" + buffer "^5.6.0" + cookie "~0.4.1" + cross-fetch "^3.0.5" + deep-extend "~0.6.0" + fast-json-patch "^2.2.1" + isomorphic-form-data "~2.0.0" + js-yaml "^3.14.0" + lodash "^4.17.19" + qs "^6.9.4" + querystring-browser "^1.0.4" + traverse "~0.6.6" + url "~0.11.0" + +swagger-ui-react@^3.31.1: + version "3.31.1" + resolved "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-3.31.1.tgz#1770cfa1dc390f79887d641ea35ee654f4bf7d80" + integrity sha512-bGpNzizMT/7N4LTdw6yx+t3rpsEoalrn0VIfhUzv9zXVrUTl+3AKPLHpLBr0r4NvzvaZLrYuSjkatnLfngJ4vg== + dependencies: + "@babel/runtime-corejs2" "^7.10.4" + "@braintree/sanitize-url" "^4.0.0" + "@kyleshockey/object-assign-deep" "^0.4.2" + "@kyleshockey/xml" "^1.0.2" + base64-js "^1.2.0" + classnames "^2.2.6" + core-js "^2.6.11" + css.escape "1.5.1" + deep-extend "0.6.0" + dompurify "^2.0.7" + ieee754 "^1.1.13" + immutable "^3.x.x" + js-file-download "^0.4.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + memoizee "^0.4.12" + prop-types "^15.7.2" + randombytes "^2.1.0" + react-copy-to-clipboard "5.0.1" + react-debounce-input "^3.2.0" + react-immutable-proptypes "2.1.0" + react-immutable-pure-component "^1.1.1" + react-inspector "^2.3.0" + react-motion "^0.5.2" + react-redux "^5.1.2" + react-syntax-highlighter "=12.2.1" + redux "^4.0.5" + redux-immutable "3.1.0" + remarkable "^2.0.1" + reselect "^4.0.0" + serialize-error "^2.1.0" + sha.js "^2.4.11" + swagger-client "=3.10.12" + url-parse "^1.4.7" + xml-but-prettier "^1.0.1" + zenscroll "^4.0.2" + swr@^0.2.2: version "0.2.3" resolved "https://registry.npmjs.org/swr/-/swr-0.2.3.tgz#e0fb260d27f12fafa2388312083368f45127480d" @@ -19611,6 +20073,11 @@ throat@^5.0.0: resolved "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== +throttle-debounce@^2.0.1: + version "2.2.1" + resolved "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.2.1.tgz#fbd933ae6793448816f7d5b3cae259d464c98137" + integrity sha512-i9hAVld1f+woAiyNGqWelpDD5W1tpMroL3NofTz9xzwq6acWBlO2dC8k5EFSZepU6oOINtV5Q3aSPoRg7o4+fA== + throttle-debounce@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" @@ -19663,6 +20130,14 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +timers-ext@^0.1.5: + version "0.1.7" + resolved "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + timsort@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" @@ -19678,6 +20153,11 @@ tiny-invariant@^1.0.6: resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== +tiny-merge-patch@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/tiny-merge-patch/-/tiny-merge-patch-0.1.2.tgz#2e8ded19c56ea15dbd3ad4ed5db1c8e5ad544c3c" + integrity sha1-Lo3tGcVuoV29OtTtXbHI5a1UTDw= + tiny-warning@^1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" @@ -19817,6 +20297,11 @@ tr46@~0.0.3: resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= +traverse@~0.6.6: + version "0.6.6" + resolved "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= + tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" @@ -20335,7 +20820,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.4.3: +url-parse@^1.4.3, url-parse@^1.4.7: version "1.4.7" resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== @@ -20343,7 +20828,7 @@ url-parse@^1.4.3: querystringify "^2.1.1" requires-port "^1.0.0" -url@0.11.0, url@^0.11.0: +url@0.11.0, url@^0.11.0, url@~0.11.0: version "0.11.0" resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= @@ -21086,6 +21571,13 @@ xdg-basedir@^4.0.0: resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== +xml-but-prettier@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/xml-but-prettier/-/xml-but-prettier-1.0.1.tgz#f5a33267ed42ccd4e355c62557a5e39b01fb40f3" + integrity sha1-9aMyZ+1CzNTjVcYlV6XjmwH7QPM= + dependencies: + repeat-string "^1.5.2" + xml-crypto@^1.4.0: version "1.5.3" resolved "https://registry.npmjs.org/xml-crypto/-/xml-crypto-1.5.3.tgz#a8f500b90f0dfaf0efa3331c345ecb0fff993c34" @@ -21358,6 +21850,11 @@ zen-observable@^0.8.0, zen-observable@^0.8.15: resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== +zenscroll@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/zenscroll/-/zenscroll-4.0.2.tgz#e8d5774d1c0738a47bcfa8729f3712e2deddeb25" + integrity sha1-6NV3TRwHOKR7z6hynzcS4t7d6yU= + zombie@^6.1.4: version "6.1.4" resolved "https://registry.npmjs.org/zombie/-/zombie-6.1.4.tgz#9f0f53f3d9a032beb7f3fe5b382146a3475a4d47" From bf76f07c0673608c3dea98f1c5026158293dd3d3 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Tue, 28 Jul 2020 12:22:11 +0200 Subject: [PATCH 11/26] chore: fix jest rule to be able to the use the asyncapi-react module --- packages/cli/config/jest.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index da9b3ec3e6..77d3a84e82 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -48,8 +48,9 @@ async function getConfig() { // Default behaviour is to not apply transforms for node_modules, but we still want // to apply the esm-transformer to .esm.js files, since that's what we use in backstage packages. + // The @kyma-project/asyncapi-react library needs to be transformed. transformIgnorePatterns: [ - '/node_modules/(?!.*\\.(?:esm\\.js|bmp|gif|jpg|jpeg|png|frag|xml|svg)$)', + '/node_modules/(?!@kyma-project/asyncapi-react/)(?!.*\\.(?:esm\\.js|bmp|gif|jpg|jpeg|png|frag|xml|svg)$)', ], }; From 42f949b465c499fa7c0a9194f4f8a8ceb62916b1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 11 Aug 2020 14:51:36 +0200 Subject: [PATCH 12/26] docs/features/software-templates: add installation docs Co-authored-by: Ben Lambert --- .../software-catalog/descriptor-format.md | 8 +- docs/features/software-templates/index.md | 9 +- .../software-templates/installation.md | 185 ++++++++++++++++++ 3 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 docs/features/software-templates/installation.md diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 68cee2352c..31b5e59fc6 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -316,10 +316,10 @@ group of people in an organizational structure. Describes the following entity kind: -| Field | Value | -| -------------------- | ----------------------- | -| `apiVersion` | `backstage.io/v1alpha1` | -| `Kind: Templatekind` | `Template` | +| Field | Value | +| ---------------- | ----------------------- | +| `apiVersion` | `backstage.io/v1alpha1` | +| `Kind: Template` | `Template` | A Template describes a skeleton for use with the Scaffolder. It is used for describing what templating library is supported, and also for documenting the diff --git a/docs/features/software-templates/index.md b/docs/features/software-templates/index.md index d1631af70c..6b752969ef 100644 --- a/docs/features/software-templates/index.md +++ b/docs/features/software-templates/index.md @@ -11,9 +11,10 @@ like GitHub. ### Getting Started -The Software Templates are available under `/create`, and if you've followed -[Getting Started with Backstage](../../getting-started), you should be able to -reach `http://localhost:3000/create`. +The Software Templates are available under `/create`. If you've followed +[Installing in your Backstage App](./installation.md) in your separate App or +[Getting Started with Backstage](../../getting-started) for this repo, you +should be able to reach `http://localhost:3000/create`. You should get something that looks similar to this: @@ -31,7 +32,7 @@ internally. After filling in these variables, you'll get some more fields to fill out which are required for backstage usage. The owner, which is a `user` in the backstage system, and the `storePath` which right now must be a Github Organisation and a -non-existing github repository name in the format `organistaion/reponame`. +non-existing github repository name in the format `organisation/reponame`. ![Enter backstage vars](./assets/template-picked-2.png) diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md new file mode 100644 index 0000000000..36dc5ebb14 --- /dev/null +++ b/docs/features/software-templates/installation.md @@ -0,0 +1,185 @@ +# Installing in your Backstage App + +The scaffolder plugin comes in two packages, `@backstage/plugin-scaffolder` and +`@backstage/plugin-scaffolder-backend`. Each has their own installation steps, +outlined below. + +The Scaffolder plugin also depends on the Software Catalog. Instructions for how +to set that up can be found [here](./TODO.md). + +## Installing @backstage/plugin-scaffolder + +`The scaffolder frontend plugin should be installed in your`app`package, which is created as a part of`@backstage/create-app`. +To install the package, run: + +```bash +cd packages/app +yarn add @backstage/plugin-scaffolder +``` + +Make sure the version of `@backstage/plugin-scaffolder` matches the version of +other `@backstage` packages. You can update it in `packages/app/package.json` if +it doesn't. + +### Adding the Plugin to your `packages/app` + +Add the following entry to the head of your `packages/app/src/plugins.ts`: + +```ts +export { plugin as ScaffolderPlugin } from '@backstage/plugin-scaffolder'; +``` + +Add the following to your `packages/app/src/apis.ts`: + +```ts +import { scaffolderApiRef, ScaffolderApi } from '@backstage/plugin-scaffolder'; + +// Inside the ApiRegistry builder function ... + +builder.add( + scaffolderApiRef, + new ScaffolderApi({ + apiOrigin: backendUrl, + basePath: '/scaffolder/v1', + }), +); +``` + +Where `backendUrl` is the `backend.baseUrl` from config, i.e. +`const backendUrl = config.getString('backend.baseUrl')`. + +This is all that is needed for the frontend part of the Scaffolder plugin to +work! + +## Installing @backstage/plugin-scaffolder-backend + +The scaffolder backend should be installed in your `backend` package, which is +created as a part of `@backstage/create-app`. To install the package, run: + +```bash +cd packages/backend +yarn add @backstage/plugin-scaffolder-backend +``` + +Make sure the version of `@backstage/plugin-scaffolder-backend` matches the +version of other `@backstage` packages. You can update it in +`packages/backend/package.json` if it doesn't. + +### Adding the Plugin to your `packages/backend` + +You'll need to add the plugin to the `backend`'s router. You can do this by +creating a file called `packages/backend/src/plugins/scaffolder.ts` with the +following contents to get you up and running quickly. + +```ts +import { + CookieCutter, + createRouter, + FilePreparer, + GithubPreparer, + Preparers, + GithubPublisher, + CreateReactAppTemplater, + Templaters, +} from '@backstage/plugin-scaffolder-backend'; +import { Octokit } from '@octokit/rest'; +import type { PluginEnvironment } from '../types'; +import Docker from 'dockerode'; + +export default async function createPlugin({ logger }: PluginEnvironment) { + const cookiecutterTemplater = new CookieCutter(); + const craTemplater = new CreateReactAppTemplater(); + const templaters = new Templaters(); + + // Register default templaters + templaters.register('cookiecutter', cookiecutterTemplater); + templaters.register('cra', craTemplater); + + const filePreparer = new FilePreparer(); + const githubPreparer = new GithubPreparer(); + const preparers = new Preparers(); + + // Register default preparers + preparers.register('file', filePreparer); + preparers.register('github', githubPreparer); + + // Create Github client with your access token from environment variables + const githubClient = new Octokit({ auth: process.env.GITHUB_ACCESS_TOKEN }); + const publisher = new GithubPublisher({ client: githubClient }); + + const dockerClient = new Docker(); + return await createRouter({ + preparers, + templaters, + publisher, + logger, + dockerClient, + }); +} +``` + +Once the `scaffolder.ts` router setup file is in place, add the router to +`packages/backend/src/index.ts`: + +```ts +import scaffolder from './plugins/scaffolder'; + +const scaffolderEnv = useHotMemoize(module, () => createEnv('scaffolder')); + +const service = createServiceBuilder(module) + .loadConfig(configReader) + /** several different routers */ + .addRouter('/scaffolder', await scaffolder(scaffolderEnv)); +``` + +### Adding Templates + +At this point the scaffolder backend is installed in your backend package, but +you will not have any templates available to use. These need to be added to the +software catalog, as they are represented as entities of kind +[Template](/docs/features/software-catalog/descriptor-format.md#kind-template). +You can find out more about adding templates [here](./adding-templates.md). + +To get up and running and try out some templates quickly, you can add some of +our example templates through static configuration. Add the following to the +`catalog.locations` section in your `app-config.yaml`: + +```yaml +catalog: + locations: + # Backstage Example Templates + type: github + target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml + type: github + target: https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml +``` + +### Runtime Dependencies + +For the scaffolder backend plugin to function, it needs a GitHub access token, +and access to a running Docker daemon. You can create a GitHub access token +[here](https://github.com/settings/tokens/new), select `repo` scope only. Full +docs on creating private GitHub access tokens is available +[here](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token). +Note that the need for private GitHub access tokens will be replaced with GitHub +Apps integration further down the line. + +The GitHub access token is passed along using the `GITHUB_ACCESS_TOKEN` +environment variable. + +### Running the Backend + +Finally, make sure you have a local Docker daemon running, and start up the +backend with the new configuration: + +```bash +cd packages/backend +GITHUB_ACCESS_TOKEN= yarn start +``` + +If you've also set up the frontend plugin, so you should be ready to go browse +the templates at [localhost:3000/create](http://localhost:3000/create) now! From 63d1bd80cc3c5095086d2045c7e21ee970432206 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 12 Aug 2020 10:27:25 +0200 Subject: [PATCH 13/26] docs/features/software-templates: review fixes Co-authored-by: Ben Lambert --- docs/features/software-catalog/descriptor-format.md | 8 ++++---- docs/features/software-templates/installation.md | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 31b5e59fc6..0e29453097 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -316,10 +316,10 @@ group of people in an organizational structure. Describes the following entity kind: -| Field | Value | -| ---------------- | ----------------------- | -| `apiVersion` | `backstage.io/v1alpha1` | -| `Kind: Template` | `Template` | +| Field | Value | +| ------------ | ----------------------- | +| `apiVersion` | `backstage.io/v1alpha1` | +| `kind` | `Template` | A Template describes a skeleton for use with the Scaffolder. It is used for describing what templating library is supported, and also for documenting the diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index 36dc5ebb14..ee66fc654c 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -9,6 +9,9 @@ to set that up can be found [here](./TODO.md). ## Installing @backstage/plugin-scaffolder +> **Note that if you used `npx @backstage/create-app`, the plugin may already be +> present** + `The scaffolder frontend plugin should be installed in your`app`package, which is created as a part of`@backstage/create-app`. To install the package, run: @@ -53,6 +56,9 @@ work! ## Installing @backstage/plugin-scaffolder-backend +> **Note that if you used `npx @backstage/create-app`, the plugin may already be +> present** + The scaffolder backend should be installed in your `backend` package, which is created as a part of `@backstage/create-app`. To install the package, run: @@ -168,6 +174,9 @@ docs on creating private GitHub access tokens is available Note that the need for private GitHub access tokens will be replaced with GitHub Apps integration further down the line. +> **Right now it is only possible to scaffold repositories inside GitHub +> organizations, and not under personal accounts.** + The GitHub access token is passed along using the `GITHUB_ACCESS_TOKEN` environment variable. From edf46c80f2bd4311382df54649afc5ae58488545 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 12 Aug 2020 10:54:33 +0200 Subject: [PATCH 14/26] docs/features/software-templates/installation: fix strange inline code blocks --- docs/features/software-templates/installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index ee66fc654c..6ef3f4fa0b 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -12,8 +12,8 @@ to set that up can be found [here](./TODO.md). > **Note that if you used `npx @backstage/create-app`, the plugin may already be > present** -`The scaffolder frontend plugin should be installed in your`app`package, which is created as a part of`@backstage/create-app`. -To install the package, run: +The scaffolder frontend plugin should be installed in your `app` package, which +is created as a part of `@backstage/create-app`. To install the package, run: ```bash cd packages/app From 173a75285571f6c6444d387cd8125e7b9ff790af Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 12 Aug 2020 11:37:56 +0200 Subject: [PATCH 15/26] docs/features/software-catalog: added installation guide Co-authored-by: Ben Lambert --- docs/features/software-catalog/index.md | 7 + .../features/software-catalog/installation.md | 193 ++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 docs/features/software-catalog/installation.md diff --git a/docs/features/software-catalog/index.md b/docs/features/software-catalog/index.md index 06785515f6..8a43a6eca3 100644 --- a/docs/features/software-catalog/index.md +++ b/docs/features/software-catalog/index.md @@ -25,6 +25,13 @@ More specifically, the Service Catalog enables two main use-cases: 2. Makes all the software in your company, and who owns it, discoverable. No more orphan software hiding in the dark corners of your software ecosystem. +## Getting Started + +The Software Catalog is available to browse on the start page at `/`. If you've +followed [Installing in your Backstage App](./installation.md) in your separate +App or [Getting Started with Backstage](../../getting-started) for this repo, +you should be able to browse the catalog at `http://localhost:3000`. + ![](service-catalog-home.png) ## Adding components to the catalog diff --git a/docs/features/software-catalog/installation.md b/docs/features/software-catalog/installation.md new file mode 100644 index 0000000000..974cb5b8f6 --- /dev/null +++ b/docs/features/software-catalog/installation.md @@ -0,0 +1,193 @@ +# Installing in your Backstage App + +The catalog plugin comes in two packages, `@backstage/plugin-catalog` and +`@backstage/plugin-catalog-backend`. Each has their own installation steps, +outlined below. + +## Installing @backstage/plugin-catalog + +> **Note that if you used `npx @backstage/create-app`, the plugin may already be +> present** + +The catalog frontend plugin should be installed in your `app` package, which is +created as a part of `@backstage/create-app`. To install the package, run: + +```bash +cd packages/app +yarn add @backstage/plugin-catalog +``` + +Make sure the version of `@backstage/plugin-catalog` matches the version of +other `@backstage` packages. You can update it in `packages/app/package.json` if +it doesn't. + +### Adding the Plugin to your `packages/app` + +Add the following entry to the head of your `packages/app/src/plugins.ts`: + +```ts +export { plugin as CatalogPlugin } from '@backstage/plugin-catalog'; +``` + +Add the following to your `packages/app/src/apis.ts`: + +```ts +import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog'; + +// Inside the ApiRegistry builder function ... + +builder.add( + catalogApiRef, + new CatalogClient({ + apiOrigin: backendUrl, + basePath: '/catalog', + }), +); +``` + +Where `backendUrl` is the `backend.baseUrl` from config, i.e. +`const backendUrl = config.getString('backend.baseUrl')`. + +The catalog components depend on a number of other +[Utility APIs](/docs/api/utility-apis.md) to function, including at least the +`ErrorApi` and `StorageApi`. You can find an example of how to install these in +your app +[here](https://github.com/spotify/backstage/blob/61c3a7e5b750dc7c059ef16b188594d31b2c04c2/packages/app/src/apis.ts#L80). + +## Gotchas that we will fix + +Since the catalog plugin currently ships with a sentry plugin `InfoCard` +installed by default, you'll need to set `sentry.organization` in your +`app-yaml.yaml`. For example: + +```yaml +sentry: + organization: Acme Corporation +``` + +If you've created an app with an older version of `@backstage/create-app` or +`@backstage/cli create-app`, be sure to remove the Welcome plugin from the app, +as that will conflict with the catalog routes. + +## Installing @backstage/plugin-catalog-backend + +> **Note that if you used `npx @backstage/create-app`, the plugin may already be +> present** + +The catalog backend should be installed in your `backend` package, which is +created as a part of `@backstage/create-app`. To install the package, run: + +```bash +cd packages/backend +yarn add @backstage/plugin-catalog-backend +``` + +Make sure the version of `@backstage/plugin-catalog-backend` matches the version +of other `@backstage` packages. You can update it in +`packages/backend/package.json` if it doesn't. + +### Adding the Plugin to your `packages/backend` + +You'll need to add the plugin to the `backend`'s router. You can do this by +creating a file called `packages/backend/src/plugins/catalog.ts` with the +following contents to get you up and running quickly. + +```ts +import { + createRouter, + DatabaseEntitiesCatalog, + DatabaseLocationsCatalog, + DatabaseManager, + HigherOrderOperations, + LocationReaders, + runPeriodically, +} from '@backstage/plugin-catalog-backend'; +import { PluginEnvironment } from '../types'; +import { useHotCleanup } from '@backstage/backend-common'; + +export default async function createPlugin({ + logger, + database, +}: PluginEnvironment) { + const locationReader = new LocationReaders(logger); + + const db = await DatabaseManager.createDatabase(database, { logger }); + const entitiesCatalog = new DatabaseEntitiesCatalog(db); + const locationsCatalog = new DatabaseLocationsCatalog(db); + const higherOrderOperation = new HigherOrderOperations( + entitiesCatalog, + locationsCatalog, + locationReader, + logger, + ); + + useHotCleanup( + module, + runPeriodically(() => higherOrderOperation.refreshAllLocations(), 10000), + ); + + return await createRouter({ + entitiesCatalog, + locationsCatalog, + higherOrderOperation, + logger, + }); +} +``` + +Once the `catalog.ts` router setup file is in place, add the router to +`packages/backend/src/index.ts`: + +```ts +import catalog from './plugins/catalog'; + +const catalogEnv = useHotMemoize(module, () => createEnv('catalog')); + +const service = createServiceBuilder(module) + .loadConfig(configReader) + /** several different routers */ + .addRouter('/catalog', await catalog(catalogEnv)); +``` + +### Adding Entries to the Catalog + +At this point the catalog backend is installed in your backend package, but you +will not have any entities loaded. + +To get up and running and try out some templates quickly, you can add some of +our example templates through static configuration. Add the following to the +`catalog.locations` section in your `app-config.yaml`: + +```yaml +catalog: + locations: + # Backstage Example Component + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-order-component.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/podcast-api-component.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/queue-proxy-component.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/searcher-component.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-lib-component.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/www-artist-component.yaml + type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/shuffle-api-component.yaml +``` + +### Running the Backend + +Finally, start up the backend with the new configuration: + +```bash +cd packages/backend +yarn start +``` + +If you've also set up the frontend plugin, so you should be ready to go browse +the catalog at [localhost:3000](http://localhost:3000) now! From 1991dfdfcefb118929dc473869a88c61884400ab Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 12 Aug 2020 11:48:15 +0200 Subject: [PATCH 16/26] docs/features/software-templates/installation: update TODO link --- docs/features/software-templates/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index 6ef3f4fa0b..769f375a9d 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -5,7 +5,7 @@ The scaffolder plugin comes in two packages, `@backstage/plugin-scaffolder` and outlined below. The Scaffolder plugin also depends on the Software Catalog. Instructions for how -to set that up can be found [here](./TODO.md). +to set that up can be found [here](../software-catalog/installation.md). ## Installing @backstage/plugin-scaffolder From 94db137153e9f27cc47b10fb37a83cfd8bf27cbe Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 12 Aug 2020 18:41:06 +0200 Subject: [PATCH 17/26] docs/verify-links: avoid absolute links within docs --- docs/verify-links.js | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/docs/verify-links.js b/docs/verify-links.js index 8c865309f9..0a3b08e425 100755 --- a/docs/verify-links.js +++ b/docs/verify-links.js @@ -17,12 +17,21 @@ const { resolve: resolvePath, dirname } = require('path'); const fs = require('fs-extra'); -const fetch = require('node-fetch'); const recursive = require('recursive-readdir'); const projectRoot = resolvePath(__dirname, '..'); async function verifyUrl(basePath, url) { + // Avoid having absolute URL links within docs/, so that links work on the site + if ( + url.match( + /https:\/\/github.com\/spotify\/backstage\/(tree|blob)\/master\/docs\//, + ) && + basePath.match(/^(?:docs|microsite)\//) + ) { + return { url, basePath, problem: 'absolute' }; + } + url = url.replace(/#.*$/, ''); url = url.replace( /https:\/\/github.com\/spotify\/backstage\/(tree|blob)\/master/, @@ -39,7 +48,7 @@ async function verifyUrl(basePath, url) { : resolvePath(dirname(resolvePath(projectRoot, basePath)), url); const exists = await fs.pathExists(path); if (!exists) { - return { url, basePath }; + return { url, basePath, problem: 'missing' }; } } @@ -76,8 +85,14 @@ async function main() { if (badUrls.length) { console.log(`Found ${badUrls.length} bad links within repo`); - for (const { url, basePath } of badUrls) { - console.error(`Unable to reach ${url}, linked from ${basePath}`); + for (const { url, basePath, problem } of badUrls) { + if (problem === 'missing') { + console.error(`Unable to reach ${url}, linked from ${basePath}`); + } else if (problem === 'absolute') { + console.error(`Link to docs/ should be replaced by a relative URL`); + console.error(` From: ${basePath}`); + console.error(` To: ${url}`); + } } process.exit(1); } From 2da62ba5118eaf9266ab934a898175b76ea27885 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 12 Aug 2020 18:45:51 +0200 Subject: [PATCH 18/26] docs: use relative links to docs/ --- docs/overview/what-is-backstage.md | 14 +++++++------- .../2020-04-30-how-to-quickly-set-up-backstage.md | 4 ++-- .../blog/2020-05-22-phase-2-service-catalog.md | 2 +- .../2020-06-22-backstage-service-catalog-alpha.md | 2 +- ...e-authentication-in-backstage-using-passport.md | 2 +- ...8-05-announcing-backstage-software-templates.md | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/overview/what-is-backstage.md b/docs/overview/what-is-backstage.md index 86b5417d5f..c8d659db9a 100644 --- a/docs/overview/what-is-backstage.md +++ b/docs/overview/what-is-backstage.md @@ -14,15 +14,15 @@ to create a streamlined development environment from end to end. Out of the box, Backstage includes: -- [Backstage Service Catalog](https://github.com/spotify/backstage/blob/master/docs/features/software-catalog/index.md) - for managing all your software (microservices, libraries, data pipelines, +- [Backstage Service Catalog](/docs/features/software-catalog/index.md) for + managing all your software (microservices, libraries, data pipelines, websites, ML models, etc.) -- [Backstage Software Templates](https://github.com/spotify/backstage/blob/master/docs/features/software-templates/index.md) - for quickly spinning up new projects and standardizing your tooling with your +- [Backstage Software Templates](/docs/features/software-templates/index.md) for + quickly spinning up new projects and standardizing your tooling with your organization’s best practices -- [Backstage TechDocs](https://github.com/spotify/backstage/tree/master/docs/features/techdocs) - for making it easy to create, maintain, find, and use technical documentation, - using a "docs like code" approach +- [Backstage TechDocs](/docs/features/techdocs) for making it easy to create, + maintain, find, and use technical documentation, using a "docs like code" + approach - Plus, a growing ecosystem of [open source plugins](https://github.com/spotify/backstage/tree/master/plugins) that further expand Backstage’s customizability and functionality diff --git a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md index 7b1fbb2d11..65ee02f6a0 100644 --- a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md +++ b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md @@ -21,7 +21,7 @@ A Backstage app is a modern monorepo web project that is built using Backstage p More specifically, a Backstage app includes the core packages and APIs that provide base functionality to the app. The actual UX is provided by plugins. As an example, when you first load the `/` page of the app, the content is provided by the `welcome` plugin. -Plugins are the essential building blocks of Backstage and extend the platform by providing additional features and functionality. Read more about [Backstage plugins](https://github.com/spotify/backstage/tree/master/docs/getting-started) on GitHub. +Plugins are the essential building blocks of Backstage and extend the platform by providing additional features and functionality. Read more about [Backstage plugins](/docs/getting-started) on GitHub. ## A personalized platform @@ -50,7 +50,7 @@ yarn start And you are good to go! šŸ‘ -Read the full documentation on how to [create an app](https://github.com/spotify/backstage/blob/master/docs/getting-started/create-an-app.md) on GitHub. +Read the full documentation on how to [create an app](/docs/getting-started/create-an-app.md) on GitHub. ## What do I get? (Let's get technical...) diff --git a/microsite/blog/2020-05-22-phase-2-service-catalog.md b/microsite/blog/2020-05-22-phase-2-service-catalog.md index 631931bb82..682965d2dd 100644 --- a/microsite/blog/2020-05-22-phase-2-service-catalog.md +++ b/microsite/blog/2020-05-22-phase-2-service-catalog.md @@ -27,7 +27,7 @@ Quote from [Platform Nuts & Bolts: Extendable Data Models](https://www.kislayver Entities, or what we refer to as ā€œcomponentsā€ in Backstage, represent all software, including services, websites, libraries, data pipelines, and so forth. The focus of Phase 2 will be on adding an entity model in Backstage that makes it easy for engineers to create and manage the software components they own. -With the ability to create a plethora of components in Backstage, how does one keep track of all the software in the ecosystem? Therein lies the highlight feature of Phase 2: the [Service Catalog](https://github.com/spotify/backstage/milestone/4). The service catalog — or software catalog — is a centralized system that keeps track of ownership and metadata about all software in your ecosystem. The catalog is built around the concept of [metadata yaml files](https://github.com/spotify/backstage/blob/master/docs/architecture-decisions/adr002-default-catalog-file-format.md) stored together with the code, which are then harvested and visualized in Backstage. +With the ability to create a plethora of components in Backstage, how does one keep track of all the software in the ecosystem? Therein lies the highlight feature of Phase 2: the [Service Catalog](https://github.com/spotify/backstage/milestone/4). The service catalog — or software catalog — is a centralized system that keeps track of ownership and metadata about all software in your ecosystem. The catalog is built around the concept of [metadata yaml files](/docs/architecture-decisions/adr002-default-catalog-file-format.md) stored together with the code, which are then harvested and visualized in Backstage. ![img](assets/20-05-20/Service_Catalog_MVP.png) diff --git a/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md b/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md index a352faf0cb..0928b8769b 100644 --- a/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md +++ b/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md @@ -24,7 +24,7 @@ With these insights we decided to re-focus our efforts towards the most requeste ## What is the service catalog? -The Backstage Service Catalog — actually, a software catalog, since it includes more than just services — is a centralized system that keeps track of ownership and metadata for all the software in your ecosystem (services, websites, libraries, data pipelines, etc). The catalog is built around the concept of [metadata yaml files](https://github.com/spotify/backstage/blob/master/docs/architecture-decisions/adr002-default-catalog-file-format.md#format) stored together with the code, which are then harvested and visualized in Backstage. +The Backstage Service Catalog — actually, a software catalog, since it includes more than just services — is a centralized system that keeps track of ownership and metadata for all the software in your ecosystem (services, websites, libraries, data pipelines, etc). The catalog is built around the concept of [metadata yaml files](/docs/architecture-decisions/adr002-default-catalog-file-format.md#format) stored together with the code, which are then harvested and visualized in Backstage. This was our pitch for the virtues of a service catalog when we first [announced](https://backstage.io/blog/2020/05/22/phase-2-service-catalog) it as part of Phase 2: diff --git a/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md b/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md index 5111f5c726..ccdd8b34c6 100644 --- a/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md +++ b/microsite/blog/2020-07-01-how-to-enable-authentication-in-backstage-using-passport.md @@ -39,7 +39,7 @@ Getting started is really straightforward, and can be broadly broken down into f 4. Add the provider to the backend. 5. Add a frontend Auth Utility API. -For full details, take a look at our [ā€œAdding authentication providersā€ documentation](https://github.com/spotify/backstage/blob/master/docs/auth/add-auth-provider.md) and at the [excellent documentation](http://www.passportjs.org/docs/) provided by Passport. +For full details, take a look at our [ā€œAdding authentication providersā€ documentation](/docs/auth/add-auth-provider.md) and at the [excellent documentation](http://www.passportjs.org/docs/) provided by Passport. ## Interested in contributing to the next steps for authentication? diff --git a/microsite/blog/2020-08-05-announcing-backstage-software-templates.md b/microsite/blog/2020-08-05-announcing-backstage-software-templates.md index 79b5ec45fd..6143442782 100644 --- a/microsite/blog/2020-08-05-announcing-backstage-software-templates.md +++ b/microsite/blog/2020-08-05-announcing-backstage-software-templates.md @@ -35,11 +35,11 @@ Since the templates can be customized to integrate with your existing infrastruc ### Golden Paths pave the way -You can customize Backstage Software Templates to fit your organization’s standards. Using Go instead of Java? CircleCI instead of Jenkins? Serverless instead of Kubernetes? GCP instead of AWS? [Make your own recipes for any software component](https://github.com/spotify/backstage/blob/master/docs/features/software-templates/adding-templates.md) and your best practices will be baked right in. +You can customize Backstage Software Templates to fit your organization’s standards. Using Go instead of Java? CircleCI instead of Jenkins? Serverless instead of Kubernetes? GCP instead of AWS? [Make your own recipes for any software component](/docs/features/software-templates/adding-templates.md) and your best practices will be baked right in. ## Getting started -The sample Software Templates are available under `/create`. If you're setting up Backstage for the first time, follow [Getting Started with Backstage](https://github.com/spotify/backstage/blob/master/docs/getting-started/index.md) and go to `http://localhost:3000/create`. If you’ve already been running Backstage locally, run the command `yarn lerna run mock-data` to load the new sample templates into the Service Catalog first. +The sample Software Templates are available under `/create`. If you're setting up Backstage for the first time, follow [Getting Started with Backstage](/docs/getting-started/index.md) and go to `http://localhost:3000/create`. If you’ve already been running Backstage locally, run the command `yarn lerna run mock-data` to load the new sample templates into the Service Catalog first. ![available-templates](assets/2020-08-05/templates.png) @@ -69,7 +69,7 @@ New components, of course, get added automatically to the Backstage Service Cata ## Define your standards -Backstage ships with four example templates, but since these are likely not the (only) ones you want to promote inside your company, the next step is to add [your own templates](https://github.com/spotify/backstage/blob/master/docs/features/software-templates/adding-templates.md). Using Backstage’s Software Templates feature, it’s easy to help your engineers get started building software with your organization’s best practices built-in. +Backstage ships with four example templates, but since these are likely not the (only) ones you want to promote inside your company, the next step is to add [your own templates](/docs/features/software-templates/adding-templates.md). Using Backstage’s Software Templates feature, it’s easy to help your engineers get started building software with your organization’s best practices built-in. We have learned that one of the keys to getting these standards adopted is to keep an open process. Templates are code. By making it clear to your engineers that you are open to pull requests, and that teams with different needs can add their own templates, you are on the path of striking a good balance between autonomy and standardization. From 1eceadb94296564444de153153c5bb2dc967b072 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 12 Aug 2020 19:17:27 +0200 Subject: [PATCH 19/26] packages: fix ts-node config in local dev versions of CLIs --- packages/cli/bin/backstage-cli | 1 + packages/create-app/bin/backstage-create-app | 1 + packages/docgen/bin/backstage-docgen | 1 + packages/techdocs-cli/bin/techdocs-cli | 1 + 4 files changed, 4 insertions(+) diff --git a/packages/cli/bin/backstage-cli b/packages/cli/bin/backstage-cli index 2b445ca9af..a065b8ac5a 100755 --- a/packages/cli/bin/backstage-cli +++ b/packages/cli/bin/backstage-cli @@ -25,6 +25,7 @@ if (!isLocal || process.env.BACKSTAGE_E2E_CLI_TEST) { } else { require('ts-node').register({ transpileOnly: true, + project: path.resolve(__dirname, '../../../tsconfig.json'), compilerOptions: { module: 'CommonJS', }, diff --git a/packages/create-app/bin/backstage-create-app b/packages/create-app/bin/backstage-create-app index 2b445ca9af..a065b8ac5a 100755 --- a/packages/create-app/bin/backstage-create-app +++ b/packages/create-app/bin/backstage-create-app @@ -25,6 +25,7 @@ if (!isLocal || process.env.BACKSTAGE_E2E_CLI_TEST) { } else { require('ts-node').register({ transpileOnly: true, + project: path.resolve(__dirname, '../../../tsconfig.json'), compilerOptions: { module: 'CommonJS', }, diff --git a/packages/docgen/bin/backstage-docgen b/packages/docgen/bin/backstage-docgen index 2b445ca9af..a065b8ac5a 100755 --- a/packages/docgen/bin/backstage-docgen +++ b/packages/docgen/bin/backstage-docgen @@ -25,6 +25,7 @@ if (!isLocal || process.env.BACKSTAGE_E2E_CLI_TEST) { } else { require('ts-node').register({ transpileOnly: true, + project: path.resolve(__dirname, '../../../tsconfig.json'), compilerOptions: { module: 'CommonJS', }, diff --git a/packages/techdocs-cli/bin/techdocs-cli b/packages/techdocs-cli/bin/techdocs-cli index 9d77a767ca..d21094a028 100755 --- a/packages/techdocs-cli/bin/techdocs-cli +++ b/packages/techdocs-cli/bin/techdocs-cli @@ -25,6 +25,7 @@ if (!isLocal) { } else { require('ts-node').register({ transpileOnly: true, + project: path.resolve(__dirname, '../../../tsconfig.json'), compilerOptions: { module: 'CommonJS', }, From f809238e6126b49d61b98f1dc029de2bf6c02447 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Thu, 13 Aug 2020 08:30:44 +0200 Subject: [PATCH 20/26] Update @types/swagger-ui-react --- plugins/api-docs/package.json | 2 +- .../OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx | 3 +-- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 3d938a3118..a599e7e322 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -45,7 +45,7 @@ "@testing-library/user-event": "^12.0.7", "@types/jest": "^26.0.7", "@types/node": "^12.0.0", - "@types/swagger-ui-react": "^3.23.2", + "@types/swagger-ui-react": "^3.23.3", "jest-fetch-mock": "^3.0.3" }, "files": [ diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx index c06c90e67f..1cab3d194d 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx @@ -32,10 +32,9 @@ export const OpenApiDefinitionWidget: FC<{ // TODO: This looks fine in the light theme, but wrong in dark mode. We need a custom stylesheet for swagger-ui. // Till then, we add a white background to the swagger-ui to make it usable in dark mode. - // TODO: the typings do not allow a string while the component does (https://github.com/DefinitelyTyped/DefinitelyTyped/pull/46654) return (
- +
); }; diff --git a/yarn.lock b/yarn.lock index 816f65f86c..5987c4dc2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4785,10 +4785,10 @@ dependencies: "@types/superagent" "*" -"@types/swagger-ui-react@^3.23.2": - version "3.23.2" - resolved "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-3.23.2.tgz#153eb466785763b514459a300772a43257a3c16b" - integrity sha512-EMD/EHdGQ6rBjfKE05x2syyw4kMZiA0qRIlv0q9EpQWYWWBhHwffSR0ljSHCy+pbX8zdOct08w8hVA0V0SAo0Q== +"@types/swagger-ui-react@^3.23.3": + version "3.23.3" + resolved "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-3.23.3.tgz#56bcf3872d8655500e6d51d29ba3916397806fa3" + integrity sha512-JKWYWAliabBxMxURagpRR6RHLEZxxp2W2tf1IN7ftqye6dIxC2e4mh4eZzARPG8+2OpzKlodHIOIwueFTYWaag== dependencies: "@types/react" "*" From 8e1020a4540ed6bdaf62795a88de848d75eb7e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 12 Aug 2020 15:19:01 +0200 Subject: [PATCH 21/26] docs(cli): can't create-app with the cli anymore --- packages/cli/README.md | 6 +++--- packages/create-app/package.json | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/cli/README.md b/packages/cli/README.md index 373d0d1073..8868e699c8 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -20,12 +20,12 @@ $ yarn add @backstage/cli For local development the cli can be used directly, even from other packages in this repo. The `bin/backstage-cli` entrypoint contains a switch that will load the implementation from the `src` directory when executed inside this repo. -To run the cli in watch mode, use `yarn start `. For example `yarn start create-app --help`. +To run the cli in watch mode, use `yarn start `. For example `yarn start lint --help`. -To try out the `create-app` command locally, you can execute the following from the parent directory of this repo: +To try out the command locally, you can execute the following from the parent directory of this repo: ```bash -./backstage/packages/cli/bin/backstage-cli create-app +./backstage/packages/cli/bin/backstage-cli --help ``` ## Documentation diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 56bcfc488a..6a1a3b60b5 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -22,7 +22,9 @@ }, "scripts": { "build": "backstage-cli build --outputs cjs", - "lint": "backstage-cli lint" + "lint": "backstage-cli lint", + "clean": "backstage-cli clean", + "start": "nodemon --" }, "dependencies": { "@backstage/cli-common": "^0.1.1-alpha.18", From 6b36a8b94aeab96d5a3a35cb6c3c5725f52f64dc Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2020 09:45:04 +0000 Subject: [PATCH 22/26] chore(deps): bump uuid from 8.1.0 to 8.3.0 Bumps [uuid](https://github.com/uuidjs/uuid) from 8.1.0 to 8.3.0. - [Release notes](https://github.com/uuidjs/uuid/releases) - [Changelog](https://github.com/uuidjs/uuid/blob/master/CHANGELOG.md) - [Commits](https://github.com/uuidjs/uuid/compare/v8.1.0...v8.3.0) Signed-off-by: dependabot-preview[bot] --- yarn.lock | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index f2af00c7fb..7fc1e1c00a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20438,15 +20438,10 @@ uuid@^7.0.3: resolved "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@^8.0.0: - version "8.1.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" - integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg== - -uuid@^8.2.0: - version "8.2.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz#cb10dd6b118e2dada7d0cd9730ba7417c93d920e" - integrity sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q== +uuid@^8.0.0, uuid@^8.2.0: + version "8.3.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" + integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== v8-compile-cache@^2.0.3: version "2.1.0" From 388df8c3bbb33f2d79ece3662a97bf918847ce93 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 13 Aug 2020 13:32:48 +0200 Subject: [PATCH 23/26] docs/features: fix static location entires not being list of objects --- .../features/software-catalog/installation.md | 32 +++++++++---------- .../software-templates/installation.md | 16 +++++----- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/features/software-catalog/installation.md b/docs/features/software-catalog/installation.md index 974cb5b8f6..260972aeac 100644 --- a/docs/features/software-catalog/installation.md +++ b/docs/features/software-catalog/installation.md @@ -162,22 +162,22 @@ our example templates through static configuration. Add the following to the catalog: locations: # Backstage Example Component - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-order-component.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/podcast-api-component.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/queue-proxy-component.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/searcher-component.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-lib-component.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/www-artist-component.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/shuffle-api-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/artist-lookup-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-order-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/podcast-api-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/queue-proxy-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/searcher-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/playback-lib-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/www-artist-component.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/packages/catalog-model/examples/shuffle-api-component.yaml ``` ### Running the Backend diff --git a/docs/features/software-templates/installation.md b/docs/features/software-templates/installation.md index 769f375a9d..925c145259 100644 --- a/docs/features/software-templates/installation.md +++ b/docs/features/software-templates/installation.md @@ -154,14 +154,14 @@ our example templates through static configuration. Add the following to the catalog: locations: # Backstage Example Templates - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml - type: github - target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml - type: github - target: https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/springboot-grpc-template/template.yaml + - type: github + target: https://github.com/spotify/backstage/blob/master/plugins/scaffolder-backend/sample-templates/create-react-app/template.yaml + - type: github + target: https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml ``` ### Runtime Dependencies From 75a316459f413c4efb1a08cf68485e64ce84da4b Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 13 Aug 2020 13:34:22 +0200 Subject: [PATCH 24/26] Fix typo in documentation --- docs/features/software-catalog/system-model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index 9485df20d0..9266ba2030 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -5,7 +5,7 @@ software and resources leads to a better Backstage experience. _This description originates from [this RFC](https://github.com/spotify/backstage/issues/390). Note that some of -the concpets are not yet supported in Backstage._ +the concepts are not yet supported in Backstage._ ## Concepts From 6bb4cf95faf039dd3e88274389479b0fa9c34928 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 13 Aug 2020 13:36:21 +0200 Subject: [PATCH 25/26] Fix button description --- docs/features/software-catalog/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-catalog/index.md b/docs/features/software-catalog/index.md index 06785515f6..ed560f84e1 100644 --- a/docs/features/software-catalog/index.md +++ b/docs/features/software-catalog/index.md @@ -42,7 +42,7 @@ There are 3 ways to add components to the catalog: ### Manually register components Users can register new components by going to `/create` and clicking the -**REGSITER EXISTING COMPONENT** button: +**REGISTER EXISTING COMPONENT** button: ![](bsc-register-1.png) From 61f913f11964c102ddb4ef1cb8329179254c755c Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 13 Aug 2020 13:40:44 +0200 Subject: [PATCH 26/26] Fix heading --- docs/features/software-catalog/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-catalog/index.md b/docs/features/software-catalog/index.md index ed560f84e1..1069ed4ea9 100644 --- a/docs/features/software-catalog/index.md +++ b/docs/features/software-catalog/index.md @@ -78,7 +78,7 @@ them, and do so using their normal Git workflow. Once the change has been merged, Backstage will automatically show the updated metadata in the service catalog after a short while. -## Finding software in the catlog +## Finding software in the catalog By default the service catalog shows components owned by the team of the logged in user. But you can also switch to _All_ to see all the components across your