jaredce / serverless-openapi-documenter Goto Github PK
View Code? Open in Web Editor NEWServerless plugin to export your config as OpenAPI v3 Documentation and Postman Collection V2
License: MIT License
Serverless plugin to export your config as OpenAPI v3 Documentation and Postman Collection V2
License: MIT License
Hi everyone,
I'm having issues generating my [paths] on openapi.json or openapi.yml file.
I defined "documentation" under "custom" in serverless.ts file and I can see my schema correctly in openapi file.
but can't seem to make the functions + paths to show up on openapi definition file.
My functions are well defined and actually work as well.
Does this plugin work with serverless.ts files same as serverless.yml files?
Please let me know if I could provide more information on this.
Describe the bug
After adding a requestHeaders
section, it does not make it in the output file
To Reproduce
serverless.yml (extract)
documentation:
summary: 'Get a QuickSight dasbhoard URL'
description: 'Used to get a QuickSight dashboard URL based on its id'
requestHeaders:
- name: 'env'
description: 'Genesys Cloud environment (e.g. mypurecloud.com)'
schema:
type: 'string'
- name: 'token'
description: 'Genesys Cloud OAuth token'
schema:
type: 'string'
pathParams:
- name: 'id'
description: 'The QuickSight dashboard id'
schema:
type: 'string'
pattern: '^[-a-z0-9_]+$'
methodResponses:
- statusCode: 200
responseBody:
description: 'Success'
responseModels:
application/json: 'SuccessResponse'
Expected behavior
Request headers (here, env
and token
) should be in the openapi.json
file but they are not.
sls openapi generate
does not output any errors.
It has been suggested, that to get up and running real fast with this plugin, that it will autogenerate some default values for the openAPI specification that can be later filled in.
Describe the bug
I get the following error when I try to generate an open API document for an interface that references itself or contains circular dependency with another interface.
Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'properties' -> object with constructor 'Object'
| property 'subRows' -> object with constructor 'Object'
--- property 'items' closes the circle 400
ERROR >>>> TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'properties' -> object with constructor 'Object'
| property 'subRows' -> object with constructor 'Object'
--- property 'items' closes the circle
at JSON.stringify ()
To Reproduce
You can go ahead and reproduce this with the below schema as an example. Pass this schema to deferenceSchema function
and use the dereferenced schema in the convert function. Here default_2 references itself in the subRows. Example provided below:
const schema = { title: 'UserResponse', description: 'Response object for user', type: 'object', properties: { user: { $ref: '#/definitions/default_1', description: 'user details', }, }, definitions: { default_1: { type: 'object', properties: { id: { type: 'number', }, basicInformation: { type: 'object', properties: { firstName: { type: 'string', }, lastName: { type: 'string', }, email: { type: 'string', } }, }, classes: { type: 'array', items: { $ref: '#/definitions/default_2', }, }, }, }, default_2: { type: 'object', properties: { className: { type: 'string', }, details: { type: 'array', items: { $ref: '#/definitions/default_3', }, }, id: { type: 'number', }, parentId: { type: 'number', }, subRows: { type: 'array', items: { $ref: '#/definitions/default_2', }, } }, }, default_3: { type: 'object', properties: { id: { type: 'number', }, detailDesc: { type: 'string', }, detailType: { $ref: '#/definitions/default_4', } }, }, default_4: { type: 'object', properties: { detailTypeName: { type: 'string', }, detailCode: { type: 'string', }, id: { type: 'number', }, }, }, }, $schema: 'http://json-schema.org/draft-07/schema#', };
const deReferencedSchema = await dereferenceSchema(schema);
const convertedSchemas = SchemaFactory.convert(deReferencedSchema, 'UserResponse');
**Expected behavior**
It should generate the document even if the interface is self-referencing or has circular dependencies.
**Desktop (please complete the following information):**
- Serverless version: [e.g. 3.34.0]
- serverless-openapi-documenter version : 0.0.72
Describe the bug
At the moment you can't add externally referenced JSON schema files, all JSON schema files either have to be internally written or available at the time of parsing in the file system.
To Reproduce
Steps to reproduce the behavior:
serverless.yml
service: abc
provider:
name: aws
custom:
documentation:
description: abc
version: 1.0.0
models:
- name: externalFile
- description: An external definition
- contentType: application/json
- schema: https://raw.githubusercontent.com/JaredCE/serverless-openapi-documenter/main/test/models/ErrorResponse.json
Expected behavior
The externally referenced JSON schema should be pulled in to the components object in the right place.
Desktop:
Hi there, not sure if this is an acceptable place to be raising this issue.
I have a project using serverless-aws-documentation
already, so I expect this should mostly work without too much configuration chage.
I have a serverless.yml
file and then I import commonly reused serverless configuration from other files using serverless-import-plugin
(https://www.serverless.com/plugins/serverless-import-config-plugin).
service: '${env:APINAME}-V1'
plugins:
- serverless-import-plugin
- serverless-reqvalidator-plugin
- serverless-aws-documentation
- serverless-openapi-documenter
- serverless-prune-plugin
- serverless-iam-roles-per-function
- serverless-api-gateway-caching
provider:
name: aws
environment: ${file(../../../serverless/environment.yml)}
stage: ${sls:stage, self:custom.default.stage}
region: ${opt:region, self:custom.default.region}
custom:
default:
stage: dev
region: eu-west-1
documentation:
version: "1"
title: "My API"
description: "This is my API"
import:
- another/service/v1
- ../../../common.yml
This works fine for serverless-aws-documentation
however when I go to import my function declarations (in another serverless file) I get the following error:
Generating OpenAPI Description
✖ ERROR: An error was thrown generating the OpenAPI v3 Description
Environment: darwin, node 18.7.0, framework 3.36.0 (local) 3.34.0v (global), plugin 7.1.0, SDK 4.4.0
Docs: docs.serverless.com
Support: forum.serverless.com
Bugs: github.com/serverless/serverless/issues
Error:
ServerlessError: TypeError: Cannot read properties of undefined (reading 'description')
2 deprecations found: run 'serverless doctor' for more details
Error:
Is there any way of working out which line number this could be?
Without the line number, or any indication of where that undefined is, I'm finding it impossible to debug. I suspect this is due to conflicts with serverless-import-plugin
.
If you read the Serverless AWS Documentation or any of its more maintained forks, it mentions that you can reference a model using the following syntax.
custom:
documentation:
models:
-
name: "Address"
description: "This is an address"
contentType: "application/json"
schema:
type: "object"
properties:
street:
type: "string"
-
name: "Customer"
description: "This is a customer"
contentType: "application/json"
schema:
type: "object"
properties:
name:
type: "string"
address:
$ref: "{{model: Address}}" <--------------
I keep getting
-attribute components.schemas.Customer.{{model: Address}} is not of type schema
Is the syntax $ref: "{{model: Address}}"
supported in this plugin?
I notice that the example petstore OAS uses the syntax:
$ref: '#/components/schemas/ProductsProduct'
Should I move my references so they look more like this?
The problem is the models in my custom.documentation
block of my serverless.yml
stack are used for the Serverless AWS Documentation plugin, however if I use this plugin on the same serverless.yml, I keep getting invalid OAS specification (because the models contains these {{ }} type references.
Describe the bug
I get the following output when I try to run the generate operation:
Error ---------------------------------------------------
Error: Cannot find module 'ajv/dist/core'
Require stack: <blah>
So I can't run the plugin at all.
Command: npm run openapi
NPM Script: openapi: "serverless openapi generate --output public/openapi_raw.yaml --format yaml --indent 2 --openApiVersion 3.1.0"
To Reproduce
Steps to reproduce the behavior:
1. run `npm install` running node 14.21.3
2. run `npm run openapi` with the above script configured in your 'scripts' section of your package.json file.
Expected behavior
The plugin to start and at least check my serverless.yml config
Desktop (please complete the following information):
Additional context
Able to get around this by installing the ajv dependency directly with npm install --save-dev ajv
Describe the bug
Somewhere between 0.0.72
and 0.0.90
this plugin began throwing errors when no 4xx response is configured.
Not saying this is wrong, but it DOES throw errors on all of our existing services, none of which have 4xx responses configured, and all of which previously compiled without error.
I would characterize this as a breaking change, deserving of a major version release. As an alternative, I would suggest that this case throw warnings rather than errors.
Here's what we are seeing:
OpenAPI v3 Description Generation
[OPTIONS]
openApiVersion: "3.0.0"
format: "json"
output file: "api/openapi.json"
indentation: "2"
validationWarn: false
postman collection: api/postman.json
Generating OpenAPI Description
Validating generated OpenAPI Description
× ERROR: An error was thrown validating the OpenAPI v3 Description
× [VALIDATION] Validation errors found in OpenAPI Description:
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1doc~1openapi/get/responses
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1doc~1postman/get/responses
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1my~1account/get/responses
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1my~1account/put/responses
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1my~1accounts/get/responses
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1private~1account/get/responses
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1private~1account/put/responses
× Message: Operation must have at least one `4XX` response.
× found at location: #/paths/~1private~1accounts/get/responses
Environment: win32, node 18.12.1, framework 3.32.2 (local), plugin 6.2.3, SDK 4.3.2
Docs: docs.serverless.com
Support: forum.serverless.com
Bugs: github.com/serverless/serverless/issues
Error:
ServerlessError: Error validating OpenAPI Description:
Operation must have at least one `4XX` response.
Operation must have at least one `4XX` response.
Operation must have at least one `4XX` response.
Operation must have at least one `4XX` response.
Operation must have at least one `4XX` response.
Operation must have at least one `4XX` response.
Operation must have at least one `4XX` response.
Operation must have at least one `4XX` response.
To Reproduce
Steps to reproduce the behavior:
Write any endpoint without a 4xx response.
Expected behavior
The plugin should throw warnings instead of errors.
Desktop (please complete the following information):
I'm still fairly new to TypeScript. I might spend my holidays looking at how to implement it properly, but would be great to get some help on making this project TypeScript compatible.
Describe the bug
The following error is generated after upgrading from v0.0.63 to v0.0.64. The error also occurs in v0.0.90.
OpenAPI v3 Document Generation
[OPTIONS]
openApiVersion: "3.0.0"
format: "yaml"
output file: "openapi.yml"
indentation: "2"✖ ERROR: An error was thrown generating the OpenAPI v3 documentation
Environment: linux, node 18.16.0, framework 3.22.0 (local), plugin 6.4.0, SDK 4.4.0
Docs: docs.serverless.com
Support: forum.serverless.com
Bugs: github.com/serverless/serverless/issuesError:
ServerlessError: Error: Expected a file path, URL, or object. Got undefined
To Reproduce
Steps to reproduce the behavior:
npx serverless openapi generate --format yaml --output openapi.yml
Expected behavior
To complete successfully
WSL on Windows 10:
Describe the bug
I don't think we currently support definitions for endpoints which return "No Content".
I get Error: hugoboss-requests-dev-patchStatus is missing a Response Model for statusCode 204
To Reproduce
Steps to reproduce the behavior:
handler: lambda/functions/patchStatus/main.go
timeout: 30
events:
- http:
path: /v1/request/{id}/status/{subId}
method: patch
cors: true
private: true
documentation:
summary: "Patch Status"
description: "updates a status"
pathParams:
- name: "id"
description: "The id of the request to mark as complete"
required: true
schema:
type: "string"
- name: "subId"
description: "The status you want to apply to a request"
required: true
schema:
type: "string"
requestModels:
"application/json": "RequestStatusRequest"
methodResponses:
- statusCode: "204"
responseBody:
description: No content
- statusCode: "404"
responseBody:
description: Not found
responseModels:
"application/json": "RequestServiceError"
- statusCode: "400"
responseBody:
description: Bad request
responseModels:
"application/json": "RequestServiceError"
Expected behavior
I would expect to be able to define a response without a model like the example here.
'204':
description: The resource was deleted successfully.
"Some responses, such as 204 No Content, have no body. To indicate the response body is empty, do not specify a content for the response"
Desktop (please complete the following information):
Additional context
Add any other context about the problem here.
Describe the bug
When I try to use this feature here an error is raised
To Reproduce
Steps to reproduce the behavior:
On serverless.doc.yml
documentation:
version: 1.0.0
description: 'My API description'
servers:
- url: https://my.{env}.url
description: Dev & Staging server
variables:
env:
enum:
- dev
- stage
default: dev
- url: https://my.url
description: Production server
...
Expected behavior
Variables managed on servers
Desktop (please complete the following information):
Additional context
Add any other context about the problem here.
Possible solution
On createServers(servers)
function add
if (server.variables) {
obj.variables = server.variables
}
It is possible to do the same for authorization ?
https://swagger.io/specification/#security-scheme-object
It would be nice if we could define root level security for OpenAPI. One of the most commonly used is the following:
security:
- BearerAuth: []
components:
securitySchemes:
BearerAuth:
bearerFormat: JWT
scheme: bearer
type: http
Describe the bug
In an attempt to maximize the reuse of my JSON schemas, I have opted to utilize the $ref
feature to establish connections and relationships within my payloads. However, I have encountered some challenges when attempting to construct a chain of multiple schemas that reference themselves (like Grandpa
-> Parent
-> Child
).
To Reproduce
Starting with a simple example, if I have the following schemas:
PS: I decided to keep my schemas as simple as possible, for the sake of the example.
src/serverless/schemas/Child.json
{
"title": "Child",
"type": "object",
"properties": {
"child_property": {
"type": "string"
}
}
}
src/serverless/schemas/Parent.json
{
"title": "Parent",
"type": "object",
"properties": {
"parent_property": {
"type": "string"
},
"child_reference": {
"$ref": "src/serverless/schemas/Child.json"
}
}
}
Note: By providing a $ref
that points to the full path of the child schema (src/serverless/schemas/Child.json
), I was able to successfully implement the solution. However, I encountered an issue where, according to the specification, I should be able to utilize a relative path instead, as demonstrated below:
"child_reference": {
"$ref": "Child.json"
}
Reference:
Relative references used in $ref are processed as per JSON Reference, using the URL of the current document as the base URI. See also the Reference Object.
I bring this up because I believe it may be connected to the issues I am about to describe. If we choose to proceed with utilizing full paths, we will likely encounter another problem as we introduce an additional level in the inheritance tree, such as adding the Grandpa schema above the Parent schema:
{
"title": "Grandpa",
"type": "object",
"properties": {
"grandpa_property": {
"type": "string"
},
"parent_reference": {
"$ref": "src/features/songs/serverless/schemas/Parent.json"
}
}
}
I end up with the following error message caused by some bad built-up of the pathname:
Error:
ServerlessError: ResolverError: Error opening file "/home/user/project/src/serverless/schemas/src/serverless/schemas/Child.json"
ENOENT: no such file or directory, open '/home/user/project/src/serverless/schemas/src/serverless/schemas/Child.json'
You can see how it messed up the path by duplicating the src/serverless/schemas/
, the part that I added in the first place because it doesn't resolve properly the relative path. So I believe that I don't construct it the correct way.
And here, you can see some really odd behavior if you start playing with the pathnames:
"parent_reference": {
"$ref": "./Parent.json"
}
ServerlessError: ResolverError: Error opening file "/home/user/project/Parent.json"
ENOENT: no such file or directory, open '/home/user/project/Parent.json'
schemas
to schema
so it points to not valid path) it does resolve it correctly (compare it back to the initial example where we provide the correct path, but it duplicated it for some reason):"parent_reference": {
"$ref": "src/serverless/schema/Parent.json"
}
ServerlessError: ResolverError: Error opening file "/home/user/project/src/serverless/schema/Parent.json"
ENOENT: no such file or directory, open '/home/user/project/src/serverless/schema/Parent.json'
I'm aware of a similar issue that is currently active, but I decided to create a separate issue, so we don't mix up both things:
Expected behavior
My expectations were that I can build up a tree deeper than one level (using references to other schemas).
Desktop (please complete the following information):
I'm new to openapi and this plug-in, so it's nearly certain that is pilot error/lack of understanding on how to implement it
I'm supporting an existing Serverless app that has ~ 12 active endpoints
I have the plug-in in my serverless.yml file located after the serverless-offline as noted in the install section of the README
I'm attempting to get enough boilerplate into the yml file to get the "sls openapi generate ..." cmd to generate a yml file that will be full of dummy data/garbage, and once I get to this point I can start adding in actual documentation key/value pairs for my endpoints 1x1 over time
I'm essentially just copy/paste off of the doc page for the custom: section and the function events: section/s for each of my endpoints
For this effort I don't need anything more that the bare minimums
custom:
documentation:
version: '1'
title: 'My API'
description: 'This is my API'
models: { }
externalDocumentation:
url: https://google.com
description: A link to google
servers:
url: https://example.com
description: The server
tags:
- name: tag1
description: this is a tag
externalDocumentation:
url: https://npmjs.com
description: A link to npm
and in each of the ~12 function/event section, I've added this exact same documentation code snippet under the existing events/http section
events:
- http:
path: path_to_my_existing_function/action/{param1}/{param2}
method: delete
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- X-Auth-Token
documentation:
summary: "Create User"
description: "Creates a user and then sends a generated password email"
requestBody:
description: "A user information object"
requestModels:
application/json: "PutDocumentRequest"
queryParams:
- name: "membershipType"
description: "The user's Membership Type"
schema:
type: "string"
enum:
- "premium"
- "standard"
methodResponses:
- statusCode: 201
responseBody:
description: "A user object along with generated API Keys"
responseModels:
application/json: "PutDocumentResponse"
- statusCode: 500
responseBody:
description: "An error message when creating a new user"
responseModels:
application/json: "ErrorResponse"
The documentation section above is taken off the README page
The error
$: serverless openapi generate -o openapi_test.yml -f yaml -a 3.0.3 --stage mike
Running "serverless" from node_modules
OpenAPI v3 Document Generation
[OPTIONS]
openApiVersion: "3.0.3"
format: "yaml"
output file: "openapi_test.yml"
indentation: "2"
Environment: linux, node 16.16.0, framework 3.30.1 (local) 3.30.1v (global), plugin 6.2.3, SDK 4.3.2
Credentials: Local, "default" profile
Docs: docs.serverless.com
Support: forum.serverless.com
Bugs: github.com/serverless/serverless/issues
Error:
TypeError: this.documentation?.models?.map is not a function
I could use a point in the right direction, TIA
I would like to have specifications like this:
{
"name": "versionId",
"in": "path",
"description": "Id of the version. Uses the latest version by default.",
"required": false, #!
"schema": {
"$ref": "#/components/schemas/versionId"
}
},
But since required: false
is not supported for path parameters it seems impossible.
- name: versionId
description: 'Id of the version. Uses the latest version by default.'
required: false # doesn't work
schema:
type: string
With the config above I have this as an output
{
"name": "versionId",
"in": "path",
"description": "Id of the version. Uses the latest version by default.",
"required": true,
"schema": {
"$ref": "#/components/schemas/versionId"
}
},
Could you tell me please there is any workaround for my case?
I can apply those changes manually but after using the plugin they are disappeared
I need help understanding how HTTP API Authorizers and REST API Authorizers relate to OpenAPI security Schemas. How can I generate a Security Schema for OpenAPI from the authorizer options?
Hi there,
I'm really interested in using this plugin to generate API specs, but I am struggling with having to define my request models twice, as I already use Request Schema Validators.
Is there a good reason why this plugin wants to define its own separate request models, when Request Schema Validators uses the same JSON schema, and also ensures at the API Gateway level that the request will be validated?
Regards,
Doug
Describe the bug
The description property from the serverless.yml
endpoint definition will sometimes "leak" into the OpenAPI paths object.
For example:
{
get: {
summary: "Get OpenAPI docs",
description: "Get JSON-formatted OpenAPI documentation.",
operationId: "publicGetDocOpenapi",
parameters: [ ... ],
tags: [ ... ],
responses: { ... },
},
description: "OpenApi documentation get endpoint handler.", // NOT an endpoint!!
}
We were able to correct for this issue post-generation until your 0.0.80
release, where new function cleanupLinks
fails at this line as the spurious description
property is not an object.
To Reproduce
Steps to reproduce the behavior:
Not entirely sure. We are having the same issue across 15 repos using this plugin, and it has been with us from the beginning. I'd love to know how NOT to reproduce this issue.
Here is the serverless.yml
definition of an endpoint that produces this effect:
public-doc-openapi-get:
description: OpenApi documentation get endpoint handler.
events:
- http:
caching:
enabled: true
cacheKeyParameters:
- name: request.querystring.excludeEndpoints
- name: request.querystring.includeEndpoints
- name: request.querystring.excludeTags
- name: request.querystring.includeTags
cors: true
documentation: ${file(serverless.doc.merged.yml):endpoints.public.doc-openapi-get}
method: get
path: doc/openapi
- http:
method: head
path: doc/openapi
handler: lib/lambda/endpoint/doc/openapi/get/public.handler
name: ${env:STACK_NAME}-public-doc-openapi-get
provisionedConcurrency: 0
And here is the snippet at the documentation link:
endpoints:
public: &EndpointsPublicCommon
doc-openapi-get:
summary: Get OpenAPI docs
description: Get JSON-formatted OpenAPI documentation.
methodResponses:
- statusCode: 200
responseBody:
description: JSON-formatted OpenAPI documentation.
responseModels:
application/json:
schema:
type: object
operationId: publicGetDocOpenapi
queryParams:
- name: excludeEndpoints
description:
"A tilde (~) delimited list of endpoint tags. Endpoints with these tags will be excluded from the result. \
This parameter is mutually exclusive with `includeEndpoints`."
schema:
type: string
- name: excludeTags
description:
"A tilde (~) delimited list of endpoint tags. These tags will be stripped from the result. \
This parameter is mutually exclusive with `includeTags`."
schema:
type: string
- name: includeEndpoints
description:
"A tilde (~) delimited list of endpoint tags. Only endpoints with these tags will be included in the result. \
This parameter is mutually exclusive with `excludeEndpoints`."
schema:
type: string
- name: includeTags
description:
"A tilde (~) delimited list of endpoint tags. All other tags will be stripped from the result. \
This parameter is mutually exclusive with `excludeTags`."
schema:
type: string
tags:
- Public
- Doc
Expected behavior
I expected the spurious description
property (although I don't want it) but I did NOT expect the internal error produced by cleanupLinks
.
Desktop (please complete the following information):
Additional context
A nice outcome of this would be the elimination of that spurious description tag. That thing is a real pain in the butt.
Describe the bug
When event is httpApi Cannot read property 'documentation' of undefined exception is raised
To Reproduce
Create a lambda with httpApi event
functions:
myLambda:
...
events:
- httpApi:
method: GET
path: hello
documentation:
....
...
Expected behavior
No exception raised and open API file generated
Desktop (please complete the following information):
Your Environment Information ---------------------------
Operating System: linux
Node Version: 14.19.1
Framework Version: 2.72.3 (local)
Plugin Version: 5.5.4
SDK Version: 4.3.2
Components Version: 3.18.2
Additional context
A possible solution, on method createPaths
of definitionGenerator.js file there are missing questions mark
const documentation = event.http.documentation || event.httpApi.documentation
should be
const documentation = event.http?.documentation || event.httpApi?.documentation
I saw that this fork is a way ahead of what you guys have been forked from:
https://github.com/motymichaely/serverless-openapi-documentation
There are many bugs that already has been solved.
If you like to move this project, we can support it with PR too.
Hi, I'm generating my model list using a script that creates a modelList.yml
file which contains the list of file where my models are described.
every model is then described inside a file ClassName.json
. I'm using $ref
to reference a model that is contained in a different file.
Example:
serverless.yml:
custom:
modelsList: ${file(resources/models/modelList.yml)}
documentation:
[...]
functions:
AgencyList:
name: bla
handler: bla
events:
- http:
path: api/v1/agencies
method: get
documentation:
summary: "Gets the agency list"
methodResponses:
- statusCode: 200
responseModels:
application/json: "AgencyList"
responseBody:
description: "Test"
file modelList.yml:
---
- name: "Agency"
description: "This is a Agency"
contentType: "application/json"
schema: "${file(resources/models/Agency.json)}"
- name: "AgencyList"
description: "This is a AgencyList"
contentType: "application/json"
schema: "${file(resources/models/AgencyList.json)}"
file AgencyList.json:
{
"type" : "object",
"properties" : {
"agencies" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/Agency"
}
}
}
}
file Agency.json:
{
"type" : "object",
"properties" : {
"id" : {
"type" : "string"
}
}
}
When I run the command to generate the OpenAPI documentation I'm getting this error:
ServerlessError: MissingPointerError: Token "components" does not exist.
like if $ref
could be linked only to other properties of the same file (because as far as I debugged, it is searching components
,schema
,Agency
inside the properties of the same file)
The same configuration was working with the deprecated plugin "serverless-openapi-documentation".
Is there a way to solve this?
thanks a lot
Describe the bug
It may be the case that, in a microservices-based architecture, the Serverless Framework is used to create and maintain different services, each one responsible for a REST resource.
Should these services be deployed on AWS, it is possible that a different mapping is used to forward the requests to different services based on their prefix.
For example, there can be service S1, responsible for resource R1, and service S2, responsible for resource R2.
In this situation, the requests like example.com/R1/* will be forwarded to S1, while requests like example.com/R2 will be forwarded to S2.
In case S1 is implemented via the serverless framework, the HTTP paths of its Lambdas will not contain the prefix R1, nor will the HTTP paths of S2 services contain the prefix R2: in both cases, the prefixes will be added via an API gateway mapping.
However, it would be useful that the documentation generated for S1 and S2 contained prefixes R1, R2, because in this way it would be easier to produce a unified documentation by merging the two openapi.yml | json files.
Expected behavior
The Documenter plugin could contains an option to prepend a prefix to all paths.
custom:
documentation:
version: '1'
title: 'My API'
prefix: R1
description: 'This is my API'
models: {}
externalDocumentation:
url: https://google.com
description: A link to google
servers:
url: https://example.com
description: The server
tags:
- name: tag1
description: this is a tag
externalDocumentation:
url: https://npmjs.com
description: A link to npm
First of all, thank you for this plugin!
I'm currently working on a serverless project that uses another plugin (serverless-apigateway-service-proxy). This plugin allows to define some APIs endpoint outside of the functions section, like this:
custom:
apiGatewayServiceProxies:
- sns:
path: /testEndpoint
method: post
topicName: SNStopic
request:
template:
...
I need to generate documentation also for these endpoints. Is there a way to achieve this?
Thank you
Describe the bug
Can't have Status
field in methodResponse model
To Reproduce
If a Status
field is present in the response model, I get this error:
Error:
AssertionError: Schema object cannot have additionalProperty: Status
SuccessResponse.json
{
"Status": 200,
"EmbedUrl": "url",
"RequestId": "b35fc1ff-578b-4bb4-a975-1abe5574da1b"
}
Here is where it's used in my serverless.yml file:
functions:
getQuickSightDashboardUrl:
handler: handler.getQuickSightDashboardUrl
events:
- http:
path: aws/quicksight/dashboardUrl/{id}
method: get
cors: ${self:custom.cors-config}
documentation:
summary: 'Get a QuickSight dasbhoard URL'
description: 'Used to get a QuickSight dashboard URL based on its id'
tags:
- aws
- quicksights
pathParams:
- name: 'id'
description: 'The QuickSight dashboard id'
schema:
type: 'string'
pattern: '^[-a-z0-9_]+$'
methodResponses:
- statusCode: 200
responseBody:
description: 'Success'
responseModels:
application/json: 'SuccessResponse'
From my point of view, you should not check if a field in the response model contains duplicate fields?
Describe the bug
Given the following valid json schema:
{
"title": "ParsingModel[RequestBody]",
"$ref": "#/definitions/RequestBody",
"definitions": {
"Reason": {
"title": "Reason",
"description": "An enumeration.",
"enum": [
"1",
"2"
],
"type": "string"
},
"RequestBody": {
"title": "RequestBody",
"type": "object",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"reason": {
"default": "1",
"allOf": [
{
"$ref": "#/definitions/Reason"
}
]
}
},
"required": [
"id"
]
}
}
}
The plugin raises the following error:
ServerlessError: AssertionError: expected Object {
default: '1',
allOf: Array [
Object {
title: 'Reason',
description: 'An enumeration.',
enum: Array [ '1', '2' ],
type: 'string'
}
]
} to have property type
If allof
is omitted and the reference is placed in the outer scope like so:
{
"title": "ParsingModel[RequestBody]",
"$ref": "#/definitions/RequestBody",
"definitions": {
"Reason": {
"title": "Reason",
"description": "An enumeration.",
"enum": [
"1",
"2"
],
"type": "string"
},
"RequestBody": {
"title": "RequestBody",
"type": "object",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"reason": {
"default": "1",
"$ref": "#/definitions/Reason"
}
},
"required": [
"id"
]
}
}
}
It will work as expected.
We can't control the schema output as it is automatically generated by pydantic
To Reproduce
Use the given schema in the serverless.yml and run the plugin
Expected behavior
Using allof
should act the same as omitting it as it is a valid schema
Desktop (please complete the following information):
The Serveless AWS Documentation plugin is now deprecated: https://github.com/deliveryhero/serverless-aws-documentation
However, many people want to store the documentation they've generated on AWS API gateway. Now that this plugin is relatively stable, perhaps I should look at stealing parts from the above plugin so that the generated documentation is uploaded to AWS API Gateway.
In OpenAPI the info section can contain a lot more than title, version and description. It would be nice if among other OpenAPI standard attributes which are still missing, in example contact:
"contact": {
"name": "API Support",
"url": "http://www.example.com/support",
"email": "[email protected]"
}
there was the possibility to include custom attributes as well, for instance
x-api-id: e9bc9584aasdsd4380-860a-9asd7495de6f200
x-audience: company-internal
x-logo:
url: 'https://www.google.de/wp-content/logo/logo-black.svg'
altText: company logo
If we want to provide a list of attributes that we want to include in the output file info section we can do something like this:
serverless.docs.yml
documentation:
contact:
name: API Support
url: http://www.example.com/support
email: [email protected]
x-api-id: e9bc9584aasdsd4380-860a-9asd7495de6f200
x-audience: company-internal
x-logo:
url: 'https://www.google.de/wp-content/logo/logo-black.svg'
altText: company logo
additionalInfoAttributes:
- x-api-id
- x-audience
- contact
- x-logo
Update the implementation to something like this:
definitionGenerator.js
createInfo() {
const service = this.serverless.service
const documentation = this.serverless.service.custom.documentation;
const additionalInfoAttributes = documentation?.additionalInfoAttributes || [];
const info = {
title: documentation?.title || service.service,
description: documentation?.description || '',
version: documentation?.version || uuid(),
}
for (const attribute of additionalInfoAttributes){
info[attribute] = documentation[attribute];
}
Object.assign(this.openAPI, {info})
}
BR,
Iwan
Describe the bug
For a same path only one operation can be managed
To Reproduce
functions:
myLambda1:
...
events:
- httpApi:
method: GET
path: /user/{id}
myLambda2:
...
events:
- httpApi:
method: PUT
path: /user/{id}
...
Expected behavior
Expected to have for same path both operations on generated file
Desktop (please complete the following information):
Additional context
Add any other context about the problem here.
A possible solution
if (paths[slashPath]) {
Object.assign(paths[slashPath], path);
} else {
Object.assign(paths, {[slashPath]: path});
}
Is it worth adding the ability to generate async API documentation with this plugin for websockets
or should I create a similar plugin but specifically for AsyncAPI? There's a lot of commonality between the 2 specs.
I have more than one serverless function, but only want to add documentation to a subset of those functions. But when I run
npx serverless openapi generate -f json -o ./docs/api/openapi.json
I get this error:
Configuration error at 'functions.myFunction.events.0.http': must have required property 'documentation'
Describe the bug
When using the plugin within a serverless.yaml
that is a part of a compose project, the plugin cannot resolve the injected variables from compose, causing it to crash - even though variables are entirely irrelevant for the generation of documentation
To Reproduce
Steps to reproduce the behavior:
# main serverless.yml
service: auth
provider:
name: aws
stage: dev
region: sa-east-1
runtime: nodejs18.x
apiGateway:
restApiId: ${param:ApiGW}
restApiRootResourceId: ${param:ApiGWRootResourceId}
websocketApiId: ${param:WebsocketsApi}
environment:
USER_POOL_ID: !Ref UserPool
CLIENT_ID: !Ref UserPoolClient
iam:
role:
statements:
- Effect: Allow
Action:
- cognito-idp:AdminInitiateAuth
- cognito-idp:AdminCreateUser
- cognito-idp:AdminSetUserPassword
- cognito-idp:AdminAddUserToGroup
- cognito-idp:AdminListGroupsForUser
Resource: !GetAtt UserPool.Arn
functions:
signup:
handler: src/signup.handler
events:
- http:
path: auth/signup
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.signup}
requestVerifyEmail:
handler: src/requestVerifyEmail.handler
events:
- http:
path: auth/requestVerifyEmail
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.requestVerifyEmail}
verifyEmail:
handler: src/verifyEmail.handler
events:
- http:
path: auth/verifyEmail
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.verifyEmail}
authorizer:
name: PrivateAuthorizer
type: COGNITO_USER_POOLS
arn: !GetAtt UserPool.Arn
login:
handler: src/login.handler
events:
- http:
path: auth/login
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.login}
refresh:
handler: src/refresh.handler
events:
- http:
path: auth/refresh
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.login}
forgotPassword:
handler: src/forgotPassword.handler
events:
- http:
path: auth/forgotPassword
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.forgotPassword}
resetPassword:
handler: src/resetPassword.handler
events:
- http:
path: auth/resetPassword
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.resetPassword}
changePassword:
handler: src/changePassword.handler
events:
- http:
path: auth/changePassword
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.changePassword}
privateAPI:
handler: src/private.handler
events:
- http:
path: auth/private
method: post
cors: true
documentation: ${file(docs/serverless.doc.yaml):endpoints.privateAPI}
authorizer:
name: PrivateAuthorizer
type: COGNITO_USER_POOLS
arn: !GetAtt UserPool.Arn
idTokenGeneration:
handler: src/idTokenGeneration.handler
events:
- cognitoUserPool:
pool: ${self:service}-pool-${sls:stage}
# pool: !GetAtt UserPool.Name
trigger: PreTokenGeneration
existing: true
resources:
Resources:
UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: ${self:service}-pool-${sls:stage}
Schema:
- Name: email
Required: true
Mutable: true
- Name: admin
DeveloperOnlyAttribute: true
AttributeDataType: String
Mutable: false
Required: false
Policies:
PasswordPolicy:
MinimumLength: 6
EmailConfiguration:
EmailSendingAccount: COGNITO_DEFAULT
VerificationMessageTemplate:
DefaultEmailOption: CONFIRM_WITH_CODE
CognitoUserPoolGroupAdmin:
Type: AWS::Cognito::UserPoolGroup
Properties:
Description: "Admin priviledges"
GroupName: "admin"
UserPoolId: !Ref UserPool
CognitoUserPoolGroupMaintainer:
Type: AWS::Cognito::UserPoolGroup
Properties:
Description: "Access to admin functions only when approved by admins"
GroupName: "maintainer"
UserPoolId: !Ref UserPool
CognitoUserPoolGroupPhysician:
Type: AWS::Cognito::UserPoolGroup
Properties:
Description: "Access to physician functions"
GroupName: "physician"
UserPoolId: !Ref UserPool
CognitoUserPoolGroupPatient:
Type: AWS::Cognito::UserPoolGroup
Properties:
Description: "Regular users"
GroupName: "patient"
UserPoolId: !Ref UserPool
UserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: ${self:service}-pool-client-${sls:stage}
GenerateSecret: false
UserPoolId: !Ref UserPool
AccessTokenValidity: 5
IdTokenValidity: 5
ExplicitAuthFlows:
- ADMIN_NO_SRP_AUTH
# - REFRESH_TOKEN_AUTH
# CognitoUserPoolIdentityProvider:
# Type: AWS::Cognito::UserPoolIdentityProvider
# Properties:
# ProviderName: Google
# AttributeMapping:
# email: emailAddress
# ProviderDetails:
# client_id: ${env:GOOGLE_CLIENT_ID}
# client_secret: ${env:GOOGLE_CLIENT_SECRET}
# authorize_scopes: email name openid
# ProviderType: Google
# UserPoolId: !Ref UserPool
plugins:
- serverless-esbuild
- serverless-openapi-documenter
- serverless-stack-output
package:
individually: true
custom:
documentation: ${file(docs/serverless.doc.yaml):documentation}
output:
file: ../.serverless/stack.json
esbuild:
bundle: true
minify: true
# serverless-compose.yaml
services:
rest:
path: rest
auth:
path: auth
params:
ApiGW: ${rest.ApiGW}
ApiGWRootResourceId: ${rest.ApiGWRootResourceId}
WebsocketsApi: ${rest.WebsocketsApi}
# reat service serverless.yaml
service: rest-api
provider:
name: aws
stage: dev
region: sa-east-1
runtime: nodejs18.x
resources:
Resources:
ApiGW:
Type: AWS::ApiGateway::RestApi
Properties:
Name: ApiGW
WebsocketsApi:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: WebsocketsApi
ProtocolType: WEBSOCKET
RouteSelectionExpression: '$request.body.action'
Outputs:
ApiGW:
Value: !Ref ApiGW
ApiGWRootResourceId:
Value: !GetAtt ApiGW.RootResourceId
WebsocketsApi:
Value: !Ref WebsocketsApi
Expected behavior
The expected behavior is for the serverless openapi generate
to generate the documentation. If I remove the injected variables from serverless-compose
it works just fine. When I run the command with the serverless-compose
setup however, I get the following errors:
# When running from serverless-compose folder
The variable "${rest.ApiGW}" cannot be resolved: the referenced output does not exist.
# When running from auth service folder
Cannot resolve serverless.yaml: Variables resolution errored with:
- Cannot resolve variable at "provider.apiGateway.restApiId": The param "ApiGW" cannot be resolved from CLI options or stage params. If you are using Serverless Framework Compose, make sure to run commands via Compose so that all parameters can be resolved,
- Cannot resolve variable at "provider.apiGateway.restApiRootResourceId": The param "ApiGWRootResourceId" cannot be resolved from CLI options or stage params. If you are using Serverless Framework Compose, make sure to run commands via Compose so that all parameters can be resolved,
- Cannot resolve variable at "provider.apiGateway.websocketApiId": The param "WebsocketsApi" cannot be resolved from CLI options or stage params. If you are using Serverless Framework Compose, make sure to run commands via Compose so that all parameters can be resolved
Desktop (please complete the following information):
Additional context
I am using a pnpm monorepo folder structure where I have a parent microservices
folder, that holds serverless-compose.yaml
and I have one child directory for each individual service, each of them hold their respective serverless.yaml
.
One more question: How do you reference an array of models in a response? I have the following in custom/documentation/models:
- name: DashboardsSuccessResponse
description: Dashboards Success response
content:
application/json:
schema:
type: array
items:
$ref: '#/custom/documentation/models/DashboardItem' <-- This fails
- name: DashboardItem
description: Dashboard item
content:
properties:
Arn:
type: string
DashboardId:
type: string
Name:
type: string
CreatedTime:
type: string
LastUpdatedTime:
type: string
PublishedVersionNumber:
type: number
LastPublishedTime:
type: string
Response is an array of DashboardItem
but I am not sure how to reference it in the DashboardsSuccessResponse
model.
Thanks!
Describe the bug
ServerlessError: Error: There was an error converting the User0000CreateUserRequest schema. Model received looks like:
{ "schema": { "title": "CreateUserRequest", "description": "Request object to create user", "type": "object", "properties": { "field1": { "description": "This is the field 1", "type": "string" }, "category": { "description": "Category", "enum": [ "A", "B" ], "type": "string" }, "field3": { "description": "field 3", "type": "string" }, "amount": { "description": "amount", "type": "number" }, "field4": { "description": "Field 4", "type": "string" }, "field5": { "description": "Field 5", "type": "string" }, "field6": { "type": "string" }, "field7": { "description": "Field 7", "type": "string" }, "field8": { "description": "Field 8", "type": "string" }, "startDate": { "description": "Start Date", "type": "string" }, "endDate": { "description": "End Date", "type": "string" } }, "$schema": "http://json-schema.org/draft-07/schema#" }, "name": "User0000CreateUserRequest", "description": "Request object to create user", "contentType": "application/json" }
To Reproduce
Steps to reproduce the behavior:
Use serverless openapi generate command. The above error is thrown sometimes and the error message appears to be vague and does not specify what has failed and where.
Expected behavior
Document should be generated.
Desktop (please complete the following information):
Describe the bug
I'm trying to get my APIs all documented with custom request / response bodies. Some of my responses are direct ports of AWS specific types. I can run npx ts-json-schema-generator
to generate the correct definitions. Very useful! But the result isnt fully as I expected.
To Reproduce
Add this file as your model
temp.json
{
"$ref": "#/definitions/AWSObject",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AWSObject": {
"additionalProperties": false,
"properties": {
"Name": {
"type": "string"
},
"Status": {
"type": "string"
}
},
"type": "object"
}
}
}
Add the model to custom.documentation.models
in the serverless.ts
(yes I'm using json wrapped in TS)
serverless.ts
...
{
name: 'temp',
contentType: 'application/json',
schema: '${file(temp.json)}',
}
...
Add model to the documentation block of a function
{
statusCode: 201,
responseBody: {
description: 'Temp response',
},
responseModels: {
'application/json': 'temp',
},
},
Run the generate command: serverless openapi generate --output openapi.json --format json
The resulting openapi.json contains this schema:
{
"components": {
"schemas": {
"temp": {
"properties": {
"AWSObject": {
"additionalProperties": false,
"properties": {
"Name": {
"type": "string"
},
"Status": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
}
Expected behavior
I expect the result to be
{
"components": {
"schemas": {
"temp": {
"additionalProperties": false,
"properties": {
"Name": {
"type": "string"
},
"Status": {
"type": "string"
}
},
"type": "object"
}
}
}
}
Desktop (please complete the following information):
Additional context
Yes I know I can just take all the properties from the definition, replace the reference and paste them there. But given that the JSONSchema with a top-level ref only seems to accept the properties of the object, not the name of the object itself, I think there might be a bug.
I get a Cannot convert undefined or null to object
error when running sls openapi generate
This is the first time I am testing this. Great idea btw!!
Steps to reproduce the behavior:
serverless.yml
service: aws
#org: ccportal
app: aws
custom:
documentation:
version: '1'
title: 'My API'
description: 'This is my API'
externalDocumentation:
url: https://google.com
description: A link to google
servers:
url: https://example.com
description: The server
tags:
- name: tag1
description: this is a tag
externalDocumentation:
url: https://npmjs.com
description: A link to npm
models:
- name: 'SuccessResponse'
description: 'Success response'
content:
application/json:
schema: ${file(models/SuccessResponse.json)}
- name: 'ErrorResponse'
description: 'This is an error'
content:
application/json:
schema: ${file(models/ErrorResponse.json)}
- name: 'PutDocumentResponse'
description: 'PUT Document response model (external reference example)'
content:
application/json:
schema: ${file(models/PutDocumentResponse.json)}
- name: 'PutDocumentRequest'
description: 'PUT Document request model (inline example)'
content:
application/json:
schema:
$schema: 'http://json-schema.org/draft-04/schema#'
properties:
SomeObject:
type: 'object'
properties:
SomeAttribute:
type: 'string'
secrets_AWS: ${ssm:/aws/reference/secretsmanager/ccportal/aws}
serverless-offline:
httpPort: 4000
# useChildProcesses: true # Do not use with this API as it has unexpected effects (API won't respond any more)
prune:
automatic: true
number: 1
cors-config:
origins:
- '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- env
- token
allowCredentials: false
provider:
name: aws
runtime: nodejs16.x
memorySize: 8192
profile: ccportal
lambdaHashingVersion: '20201221'
stage: dev
region: eu-central-1
deploymentBucket:
name: my.dev.serverless.deploys
versionFunctions: false
tracing:
lambda: true
logRetentionInDays: 7
timeout: 30 # If using web sockets, you can increase this. It will cause a warning when running 'serverless deploy' but you can ignore it.
environment:
NODE_ENV: ${file(./.env.yml):${opt:stage, self:provider.stage}.NODE_ENV}
AWS_ACCOUNT_ID: ${self:custom.secrets_AWS.ACCOUNT_ID}
AWS_QUICKSIGHT_USER_ARN: ${self:custom.secrets_AWS.quickSight_user_arn}
STAGE: ${opt:stage, self:provider.stage}
iamRoleStatements:
- Effect: Allow
Action:
- lambda:InvokeFunction
- dynamodb:*
- s3:*
- quicksight:GetDashboardEmbedUrl
- quicksight:GetAnonymousUserEmbedUrl
- quicksight:GenerateEmbedUrlForRegisteredUser
- quicksight:ListDashboards
Resource:
- '*'
apiGateway:
restApiId:
'Fn::ImportValue': ${opt:stage, self:provider.stage}-CCPortalGW-restApiId
restApiRootResourceId:
'Fn::ImportValue': ${opt:stage, self:provider.stage}-CCPortalGW-rootResourceId
functions:
getQuickSightDashboardUrl:
handler: handler.getQuickSightDashboardUrl
events:
- http:
path: aws/quicksight/dashboardUrl/{id}
method: get
cors: ${self:custom.cors-config}
documentation:
summary: 'Get a QuickSight dasbhoard URL'
description: 'Used to get a QuickSight dashboard URL based on its id'
tags:
- aws
- quicksights
pathParams:
- name: 'id'
description: 'The QuickSight dashboard id'
schema:
type: 'string'
pattern: '^[-a-z0-9_]+$'
methodResponses:
- statusCode: 200
responseBody:
description: 'Success'
getDashboardList:
handler: handler.listdashboards
events:
- http:
path: aws/quicksight/dashboards
method: get
cors: ${self:custom.cors-config}
documentation:
summary: 'Get a list of QuickSight dasbhoards'
description: 'Gets the list of QuickSights dashboards'
tags:
- aws
- quicksights
methodResponses:
- statusCode: 200
responseBody:
description: 'Success'
getQuickSightSearchBar:
handler: handler.getQuickSightSearchBar
events:
- http:
path: aws/quicksight/searchBarUrl/{id}
method: get
cors: ${self:custom.cors-config}
documentation:
summary: 'Gets a QuickSights search bar URL'
description: 'Used to get a QuickSights search bar URL based on its id'
tags:
- aws
- quicksights
pathParams:
- name: 'id'
description: 'The QuickSight search bar id'
schema:
type: 'string'
pattern: '^[-a-z0-9_]+$'
methodResponses:
- statusCode: 200
responseBody:
description: 'Success'
responseModels:
application/json: 'SuccessResponse'
package:
exclude:
- .dynamodb/**
- .nyc_output/**
- coverage/**
- test/**
- .git/**
- serverless.yml
- .serverless/**
- requests.http
- snowflake.log
- node_modules/puppeteer/.local-chromium/**
plugins:
- serverless-offline
- serverless-prune-plugin
- serverless-plugin-common-excludes
- serverless-openapi-documenter
Expected behavior
Generate an OpenAPI file and a Postman collection file
Output from running sls openapi generate
$sls openapi generate
Running "serverless" from node_modules
OpenAPI v3 Document Generation
[OPTIONS]
openApiVersion: "3.0.0"
format: "json"
output file: "openapi.json"
indentation: "2"
✖ ERROR: An error was thrown generating the OpenAPI v3 documentation
Environment: linux, node 16.13.1, framework 3.18.2 (local) 3.22.0v (global), plugin 6.2.2, SDK 4.3.2
Credentials: Local, "ccportal" profile
Docs: docs.serverless.com
Support: forum.serverless.com
Bugs: github.com/serverless/serverless/issues
Error:
TypeError: Cannot convert undefined or null to object
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.