1.0.19 • Published 3 years ago

mares-swagger-spec-maker v1.0.19

Weekly downloads
-
License
ISC
Repository
-
Last release
3 years ago

mares-swagger-spec-maker

mares framework 구조에 맞춰서openapi spec을 combine 해주는 모듈입니다.

Installation

npm install --save mares-swagger-spec-maker

Example

const specMaker = require('mares-swagger-spec-maker')()

// setting project root spec,
let rootSpec = require('./.root-api-spec.js')

// 각 서비스의 폴더를 추가해준다. 배열로 추가가 가능하다. 서비스별 폴더 구조는 아래에서 다시 설명한다.
rootSpec = specMaker.merge(rootSpec, [require('./service-name')])

// api prefix가 있다면 추가해준다.
rootSpec.paths = specMaker.addPrefix(rootSpec.paths, this._prefix) //optional

root spec의 경우 .root-api-spec.js 라고 이름지어 줘야 하며, 형태는 다음과 같다. version, servers, info, components 정의가 가능하다.

module.exports = {
    openapi: "3.0.0",
    servers: [{
        url: env === 'development' ? 'http://localhost:8080' : 'https://aaaaa.com'
    }],
    info: {
        description: packageJson.description,
        version: packageJson.version,
        title: packageJson.name,
        termsOfService: 'http://swagger.io/terms/',
        contact: {
            email: 'aaa@aaaa.com'
        },
        license: {
            name: 'Private',
            url: 'http://aaaa.com'
        }
    },
    components: {
        schemas: {
            Error: {
                type: 'object',
                required: ['rows', 'count'],
                properties: {
                    rows: {
                        type: 'string',
                    },
                    count: {
                        type: 'integer',
                        description: '전체 에러의 수',
                        example: 1,
                        nullable: false
                    }
                }
            }
        }
    }
}

컨텍스트별 스펙의 경우 .context-api-spec.js 과 같이 파일명을 지어야 하며 형태는 아래와 같다. root components를 overriding 하고, tag를 지정하는데 사용된다.

const meta = GET_META('infra-message');
const spec = {
    tags: [{
        name: 'message',
        description: '문자 발송, 발송된 문자 조회 등의 기능을 담은 API.'
    }],
    components: {
        securitySchemes: {
            ApiKeyAuth: {
                type: 'apiKey',
                in: 'header',
                name: 'X-API-TOKEN'
            }
        },
        schemas: {
            PhoneNum: {
                type: 'string',
                pattern: /(^\+[0-9]{2}|^\+[0-9]{2}\(0\)|^\(\+[0-9]{2}\)\(0\)|^00[0-9]{2}|^0)([0-9]{9}$|[0-9\-\s]{10}$)/,
                minLength: meta.std.message.minPhoneNumLength,
                maxLength: meta.std.message.maxPhoneNumLength,
                description: '문자를 받을 수 있는 전화번호, +국가코드 형태가 되어야 한다.',
                example: '+821011112222',
                nullable: false
            }
        },
        parameters: {
            messageContextLimitParam: {
                in: 'query',
                name: 'limit',
                description: '최대 불러올 데이터 row 수',
                required: false,
                schema: {
                    type: 'integer'
                },
                example: meta.std.default.defaultContentsLength
            }
        }
    }
}
module.exports = spec

다음으로 버전에 대한 스펙이 있다. .version-api-spec.js 라고 이름 지어줘야 한다.

module.exports = {
    in: 'path',
    name: 'version',
    description: '버전 값',
    required: false,
    schema: {
        type: 'string',
        enum: ['v1'],
        default: 'v1',
        example: 'v1'
    }
}

마지막으로 실제 router spec을 정의해야한다. .spec.js 로 정의한다. 전체 스펙에서 url 부분부터 정의를 해주면 된다.

const meta = GET_META('message-context');

const spec = {
    '/{version}/messages': {
        get: {
            tags: ['message'],
            summary: '문자 내역 확인',
            operationId: 'findMessages',
            description: '해당 스펙에서 message 라는 의미는 발송된 문자를 의미한다. 해당 API는 발송했던 문자 내역을 불러온다.',
            parameters: [{
                $ref: '#/components/parameters/messageContextOffsetParam'
            }, {
                $ref: '#/components/parameters/messageContextLimitParam'
            }, {
                in: 'query',
                name: 'templateKey',
                description: '문자 발송시 이용된 템플릿의 키 겁색 (prefix 검색 가능)',
                required: false,
                schema: {
                    type: 'string',
                    example: 'templateKey123',
                    nullable: false
                }
            }],
            responses: {
                '200': {
                    description: '불러오기 성공',
                    content: {
                        'application/json': {
                            schema: {
                                type: 'object',
                                properties: {
                                    rows: {
                                        type: 'array',
                                        items: {
                                            $ref: '#/components/schemas/MessageDomain'
                                        },
                                        description: '문자 도메인 배열'
                                    },
                                    count: {
                                        type: 'integer',
                                        description: '해당 조건에 해당하는 전체 문자 도메인 카운트'
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
module.exports = spec

최종적으로는 아래와 같이 사용이 가능하다.

const getSpec = () => {
    // 최상단 루트 스펙을 가져온다.
    let rootSpec = require(path.resolve(rootPath, '.root-api-spec.js'))
    
    // 루프를 돌면서 마레스 모듈을 읽어와서 루트스펙에 머지한다,.
    for (let i = 0; i < contexts.length; ++i) {
        let moduleName = path.basename(contexts[i])
        rootSpec = specMaker.merge(rootSpec, path.resolve(rootPath, moduleName))
    }
    
    // 모든 url에 prefix를 붙여준다. 예를들면 account/users 라는 리소스가 있다면 prefix/account/users라고 변경이 된다.
    rootSpec.paths = specMaker.addPrefix(rootSpec.paths, prefix)
    
    // 모든 루트스펙에 선언된 컴포넌트 ($ref) 를 실제 객체로 바꿔준다. (이유는 실제 객체를 통해 router에서 parameter, requestBody 등을 validation하기 위함이다.)
    rootSpec = specMaker.replaceAllComponents(rootSpec)
    
    // 필요한 곳에 리턴한다.
    return rootSpec	
} 

Structure

폴더 및 파일 구조는 다음과 같다. 1. 루트 프로젝트: .root-api-spec.js가 위치한다. 2. service 폴더: 서비스폴더 루트에 .context-api-spec.js 가 존재한다. 1. presentation: 프레젠테이션 레이어 1. v1: api 버전폴더: 해당폴더 안에 version-api-spec.js가 존재한다. 1. resourceName: 해당폴더 안에 .spec.js가 존재한다. 2. application: 어플리케이션 레이어 3. domain: 도메인 레이어 4. infra: 인프라스트럭쳐 레이어 5. test: test 코드

1.0.19

3 years ago

1.0.18

3 years ago

1.0.17

5 years ago

1.0.16

5 years ago

1.0.15

5 years ago

1.0.14

5 years ago

1.0.13

5 years ago

1.0.12

5 years ago

1.0.11

5 years ago

1.0.10

5 years ago

1.0.9

5 years ago

1.0.8

5 years ago

1.0.7

5 years ago

1.0.6

5 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago