-
Notifications
You must be signed in to change notification settings - Fork 0
Inspector client, server 초기 설정 및 배포 파이프라인 추가 #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
toothlessdev
wants to merge
5
commits into
develop
Choose a base branch
from
27-setup-inspector-client-server-package
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
1d915d1
chore: inspector client, server 초기설정
toothlessdev 12bb712
chore: nestjs decorator 를 위해 inspector/server 패키지 eslint 비활성화
toothlessdev d4d401c
chore: inspector client, server 초기설정
toothlessdev c2ce62d
docs: 패키지별 claude code rule 추가
toothlessdev 9d19f53
feat: ci/cd 파이프라인에 inspector 배포 job 추가
toothlessdev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| --- | ||
| paths: | ||
| - "packages/patchlogr-core/**" | ||
| --- | ||
|
|
||
| # @patchlogr/core | ||
|
|
||
| API 스펙 파티셔닝, 변경 감지, 버전 범프 계산 등 핵심 비즈니스 로직 패키지. | ||
|
|
||
| ## Exported Functions | ||
|
|
||
| ### Partition (해시 기반 트리 생성) | ||
|
|
||
| ```typescript | ||
| // 태그별로 operation 그룹화 | ||
| function partitionByTag(spec: CanonicalSpec): PartitionedSpec<string>; | ||
|
|
||
| // HTTP 메서드별로 그룹화 | ||
| function partitionByMethod(spec: CanonicalSpec): PartitionedSpec<string>; | ||
|
|
||
| // 노드 생성 유틸리티 | ||
| function createNode<K, V>(key: K, hash: string, children: HashNode<K, V>[]): HashNode<K, V>; | ||
| function createLeafNode<K, V>(key: K, hash: string, value: V): HashNode<K, V>; | ||
| function createHashedLeaf<K, V>(key: K, value: V): HashNode<K, V>; // 자동 해시 생성 | ||
| function createHashedNode<K, V>(key: K, children: HashNode<K, V>[]): HashNode<K, V>; // 자동 해시 생성 | ||
| ``` | ||
|
|
||
| ### Diff (변경 감지) - 현재 내부 모듈, 향후 export 예정 | ||
|
|
||
| ```typescript | ||
| // 두 PartitionedSpec 비교 | ||
| function diffSpec<K>(base: PartitionedSpec<K>, head: PartitionedSpec<K>): SpecChangeSet<K>; | ||
|
|
||
| // 버전 범프 권장 | ||
| function detectVersionBump<K>(changeSet: SpecChangeSet<K>): VersionBumpResult; | ||
| ``` | ||
|
|
||
| ## Exported Types | ||
|
|
||
| ### Partition Types | ||
|
|
||
| ```typescript | ||
| type Hash = string; | ||
|
|
||
| type HashNode<K = string, V = unknown> = { | ||
| type: "node" | "leaf"; | ||
| key: K; | ||
| hash: Hash; | ||
| children?: HashNode<K, V>[]; // type: "node"일 때 | ||
| value?: V; // type: "leaf"일 때 | ||
| }; | ||
|
|
||
| type PartitionedSpec<K = string, V = unknown> = { | ||
| root: HashNode<K, V>; | ||
| metadata: Record<string, unknown>; | ||
| hashObjects: HashObject<V>[]; | ||
| }; | ||
| ``` | ||
|
|
||
| ### Diff Types (내부 모듈) | ||
|
|
||
| ```typescript | ||
| type ChangeType = "added" | "removed" | "modified" | "type_changed"; | ||
|
|
||
| type SpecChange<K = string> = { | ||
| type: ChangeType; | ||
| path: K[]; | ||
| key: K; | ||
| baseHash?: string; | ||
| headHash?: string; | ||
| baseNodeType?: "node" | "leaf"; | ||
| headNodeType?: "node" | "leaf"; | ||
| }; | ||
|
|
||
| type SpecChangeSet<K = string> = { | ||
| baseHash: string; | ||
| headHash: string; | ||
| changes: SpecChange<K>[]; | ||
| }; | ||
|
|
||
| type VersionBump = "major" | "minor" | "patch" | "none"; | ||
|
|
||
| type VersionBumpResult = { | ||
| recommendedBump: VersionBump; | ||
| isBreaking: boolean; | ||
| reasons: string[]; | ||
| }; | ||
| ``` | ||
|
|
||
| ## 버전 범프 분류 기준 | ||
|
|
||
| - **major** (Breaking): `removed`, `type_changed` | ||
| - **minor** (New feature): `added` | ||
| - **patch** (Bug fix): `modified` (현재는 minor로 처리) | ||
|
|
||
| ## 의존성 | ||
|
|
||
| - `@patchlogr/types`: CanonicalSpec 등 타입 | ||
| - `@patchlogr/oas`: 전처리된 스펙 사용 | ||
| - `fast-json-stable-stringify`: 결정적 해시 생성 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| --- | ||
| paths: | ||
| - "packages/patchlogr-inspector/**" | ||
| --- | ||
|
|
||
| # @patchlogr/inspector | ||
|
|
||
| ## Overview | ||
|
|
||
| API 변경사항을 시각적으로 리뷰할 수 있는 웹 UI 도구. Storybook처럼 로컬에서 띄워서 사용. | ||
|
|
||
| ## 핵심 기능 | ||
|
|
||
| - **Diff 시각화**: `@patchlogr/core`의 diff 결과를 side-by-side 뷰로 표시 | ||
| - **Breaking Change 강조**: Breaking change를 명확하게 표시 | ||
| - **Operation별 상세 뷰**: Parameters, Request Body, Responses 탭으로 구분 | ||
| - **변경 타입 표시**: Added (초록), Removed (빨강), Modified (파랑) 구분 | ||
|
|
||
| ## 패키지 구조 | ||
|
|
||
| ``` | ||
| packages/patchlogr-inspector/ | ||
| client/ # React 기반 웹 UI | ||
| server/ # diff 결과를 서빙하는 dev server | ||
| ``` | ||
|
|
||
| ## 의존성 | ||
|
|
||
| - `@patchlogr/core`: `SpecChangeSet`, `VersionBumpResult` 타입 소비 | ||
| - `@patchlogr/types`: `CanonicalSpec`, `CanonicalOperation` 등 타입 참조 | ||
|
|
||
| ## 아키텍처 결정 | ||
|
|
||
| ### 모노레포 유지 (별도 레포 분리 X) | ||
|
|
||
| **이유**: | ||
| 1. **타이트한 타입 의존성**: core의 diff 결과 타입에 직접 의존 | ||
| 2. **버전 동기화 필요**: core 변경 시 inspector도 함께 수정 필요 | ||
| 3. **개발 편의성**: core 수정 후 바로 inspector에서 확인 가능 | ||
| 4. **Storybook 패턴**: 메인 프로젝트와 같은 레포에서 관리하는 것이 일반적 | ||
|
|
||
| ## 개발 가이드 | ||
|
|
||
| - client는 React + Vite 사용 예정 | ||
| - server는 Express 또는 Fastify 기반 dev server | ||
| - TypeScript strict mode 유지 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| --- | ||
| paths: | ||
| - "packages/patchlogr-oas/**" | ||
| --- | ||
|
|
||
| # @patchlogr/oas | ||
|
|
||
| OpenAPI 문서를 표준화된 `CanonicalSpec` 형태로 변환하는 파이프라인 패키지. | ||
|
|
||
| ## 핵심 역할 | ||
|
|
||
| - OpenAPI v2/v3 문서를 입력받아 `@patchlogr/types`에 정의된 표준화된 형태로 변환 | ||
| - `allOf`, `anyOf`, `oneOf` 같은 composition을 펼쳐서 flat한 구조로 만듦 | ||
| - `$ref` 참조를 모두 역참조(dereference)하여 self-contained 문서 생성 | ||
| - v2/v3 차이를 추상화하여 일관된 데이터 구조 제공 | ||
|
|
||
| ## Exported Functions | ||
|
|
||
| ### preprocessOASDocument | ||
|
|
||
| ```typescript | ||
| function preprocessOASDocument( | ||
| doc: OpenAPI.Document, | ||
| options?: OASStageOptions, | ||
| ): Promise<OASStageContext>; | ||
| ``` | ||
|
|
||
| **파이프라인 단계**: | ||
|
|
||
| 1. `OASBundleStage` - 외부 참조($ref) 번들링 | ||
| 2. `OASValidationStage` - OpenAPI 스펙 유효성 검증 | ||
| 3. `OASDereferenceStage` - $ref 참조를 실제 객체로 역참조 | ||
| 4. `OASCanonicalizeStage` - allOf/anyOf/oneOf 펼치고 `CanonicalSpec`으로 변환 | ||
|
|
||
| **사용 예시**: | ||
|
|
||
| ```typescript | ||
| import { preprocessOASDocument } from "@patchlogr/oas"; | ||
|
|
||
| const result = await preprocessOASDocument(oasDoc, { skipValidation: false }); | ||
| const canonicalSpec = result.canonicalSpec; | ||
| ``` | ||
|
|
||
| ## Exported Types | ||
|
|
||
| ```typescript | ||
| type OASStageOptions = { | ||
| skipValidation?: boolean; | ||
| }; | ||
| ``` | ||
|
|
||
| ## 내부 구조 | ||
|
|
||
| ``` | ||
| src/ | ||
| pipeline/ # 파이프라인 인프라 | ||
| canonicalize/ | ||
| v2/ # OpenAPI v2 → CanonicalSpec 변환 | ||
| v3/ # OpenAPI v3 → CanonicalSpec 변환 | ||
| ``` | ||
|
|
||
| ## 의존성 | ||
|
|
||
| - `@patchlogr/types`: CanonicalSpec 등 타입 | ||
| - `@apidevtools/swagger-parser`: OAS 파싱/검증/역참조 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| --- | ||
| paths: | ||
| - "packages/patchlogr-types/**" | ||
| --- | ||
|
|
||
| # @patchlogr/types | ||
|
|
||
| OpenAPI 스펙을 표준화(Canonicalization)한 타입 정의 패키지. | ||
|
|
||
| ## 설계 목적 | ||
|
|
||
| OpenAPI v2/v3의 `allOf`, `anyOf`, `oneOf` 같은 composition을 모두 펼쳐서(flatten) diff 비교가 용이한 flat한 구조로 정의. 실제 변환은 `@patchlogr/oas`에서 수행. | ||
|
|
||
| ## Exported Types | ||
|
|
||
| ### Utility Types | ||
|
|
||
| ```typescript | ||
| type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD" | "TRACE"; | ||
| type OperationKey = `${HTTPMethod} ${string}`; // e.g. "GET /users/{id}" | ||
| ``` | ||
|
|
||
| ### Schema Types (allOf/anyOf/oneOf 펼친 형태) | ||
|
|
||
| ```typescript | ||
| type CanonicalSchema = { | ||
| type?: string | string[]; | ||
| format?: string; | ||
| properties?: Record<string, CanonicalSchemaProperty>; | ||
| items?: CanonicalSchema | CanonicalSchema[]; | ||
| enum?: unknown[]; | ||
| default?: unknown; | ||
| description?: string; | ||
| [key: string]: unknown; // minimum, maximum, pattern 등 | ||
| }; | ||
|
|
||
| type CanonicalSchemaProperty = CanonicalSchema & { | ||
| required?: boolean; // required 배열에서 추출하여 필드에 직접 표시 | ||
| }; | ||
| ``` | ||
|
|
||
| ### Request/Response Types | ||
|
|
||
| ```typescript | ||
| type CanonicalParam = { | ||
| name: string; | ||
| in: "path" | "query" | "header" | "cookie"; | ||
| required: boolean; | ||
| schema?: CanonicalSchema; | ||
| deprecated?: boolean; | ||
| description?: string; | ||
| }; | ||
|
|
||
| type CanonicalBody = { | ||
| required: boolean; | ||
| content: Record<string, { schema?: CanonicalSchema }>; | ||
| }; | ||
|
|
||
| type CanonicalMessage = { | ||
| params: CanonicalParam[]; | ||
| body?: CanonicalBody; | ||
| }; | ||
|
|
||
| type CanonicalHeader = { | ||
| required?: boolean; | ||
| schema?: CanonicalSchema; | ||
| deprecated?: boolean; | ||
| description?: string; | ||
| }; | ||
|
|
||
| type CanonicalResponse = { | ||
| description?: string; | ||
| headers?: Record<string, CanonicalHeader>; | ||
| content?: CanonicalBody["content"]; | ||
| }; | ||
| ``` | ||
|
|
||
| ### Operation Types | ||
|
|
||
| ```typescript | ||
| type CanonicalSecurityRequirement = Record<string, string[]>; | ||
|
|
||
| type CanonicalOperationContract = { | ||
| key: OperationKey; | ||
| method: HTTPMethod; | ||
| path: string; | ||
| deprecated?: boolean; | ||
| security?: CanonicalSecurityRequirement[]; | ||
| request: CanonicalMessage; | ||
| responses: Record<string, CanonicalResponse>; | ||
| }; | ||
|
|
||
| type CanonicalOperationDoc = { | ||
| operationId?: string; | ||
| tags?: string[]; | ||
| summary?: string; | ||
| description?: string; | ||
| }; | ||
|
|
||
| type CanonicalOperation = CanonicalOperationContract & { | ||
| doc?: CanonicalOperationDoc; | ||
| }; | ||
| ``` | ||
|
|
||
| ### Spec Type | ||
|
|
||
| ```typescript | ||
| type CanonicalSpec = { | ||
| info?: { title?: string; version?: string; description?: string }; | ||
| security?: CanonicalSecurityRequirement[]; | ||
| operations: Record<OperationKey, CanonicalOperation>; | ||
| }; | ||
| ``` | ||
|
|
||
| ## 의존성 | ||
|
|
||
| - 없음 (기반 타입 레이어) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,20 @@ | ||
| { | ||
| "hooks": { | ||
| "pre-commit": "yarn lint && yarn typecheck && yarn test" | ||
| }, | ||
| "permissions": { | ||
| "allowedCommands": [ | ||
| "yarn build", | ||
| "yarn test", | ||
| "yarn test:coverage", | ||
| "yarn lint", | ||
| "yarn lint:fix", | ||
| "yarn typecheck", | ||
| "yarn clean", | ||
| "git status", | ||
| "git diff", | ||
| "git log", | ||
| "git branch", | ||
| "ls", | ||
| "cat", | ||
| "pwd" | ||
| ] | ||
| } | ||
| "permissions": { | ||
| "allowedCommands": [ | ||
| "yarn build", | ||
toothlessdev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "yarn test", | ||
| "yarn test:coverage", | ||
| "yarn lint", | ||
| "yarn lint:fix", | ||
| "yarn typecheck", | ||
| "yarn clean", | ||
| "git status", | ||
| "git diff", | ||
| "git log", | ||
| "git branch", | ||
| "ls", | ||
| "cat", | ||
| "pwd" | ||
| ] | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.