npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mares-swagger-spec-maker

v1.0.19

Published

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

Downloads

9

Readme

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: '[email protected]'
        },
        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 코드