deleted obsolete code and added save to Documents
This commit is contained in:
parent
51e4bae990
commit
78e3eaaf8f
28
README.md
28
README.md
@ -2,34 +2,6 @@
|
||||
|
||||
A Swift package for merging multiple YAML files from subdirectories into a single combined file.
|
||||
|
||||
## 🏗️ Architecture Overview
|
||||
|
||||
┌─────────────────────-┐ ┌──────────────────┐ ┌─────────────────────┐
|
||||
│ Schema YAML Files │───▶ │ YAMLMerger │───▶ │ Combined OpenAPI │
|
||||
│ (Organized by Type & │ │ (Test Runner) │ │ Specification │
|
||||
│ Function) │ │ │ │ (CombinedSpec.yaml) │
|
||||
└─────────────────────-┘ └──────────────────┘ └─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ Manual Copy Step │
|
||||
│ (Human Action) │
|
||||
└─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐ ┌──────────────────┐ ┌─────────────────────┐
|
||||
│ Generated Swift │◀─── │ Swift OpenAPI │◀─── │ SharedApiModels │
|
||||
│ Client & Server │ │ Generator │ │ openapi.yaml │
|
||||
│ Code │ │ │ │ │
|
||||
└─────────────────────┘ └──────────────────┘ └─────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ ApiClient & │
|
||||
│ ApiServer │
|
||||
│ Packages │
|
||||
└─────────────────────┘
|
||||
|
||||
## How It Works
|
||||
|
||||
YAMLMerger recursively scans subdirectories for YAML files and merges them in a predictable order:
|
||||
|
||||
@ -1,719 +0,0 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
|
||||
|
||||
title: OpenAPI Generation Demo
|
||||
version: 1.0.0
|
||||
description: Demonstration of OpenAPI specification generation using YAMLMerger
|
||||
contact:
|
||||
name: API Support
|
||||
email: support@example.com
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
servers:
|
||||
|
||||
|
||||
- url: https://dummyjson.com
|
||||
description: DummyJSON API Server
|
||||
|
||||
- url: http://localhost:8080
|
||||
description: Local development server
|
||||
|
||||
tags:
|
||||
|
||||
|
||||
- name: auth
|
||||
description: Authentication operations
|
||||
- name: users
|
||||
description: User management operations
|
||||
- name: posts
|
||||
description: Post management operations
|
||||
- name: products
|
||||
description: Product catalog operations
|
||||
- name: carts
|
||||
description: Shopping cart operations
|
||||
- name: todos
|
||||
description: Todo management operations
|
||||
- name: comments
|
||||
description: Comment operations
|
||||
|
||||
paths:
|
||||
|
||||
|
||||
/auth/login:
|
||||
post:
|
||||
operationId: loginUser
|
||||
tags:
|
||||
- auth
|
||||
summary: User login
|
||||
description: Authenticate user and receive access token
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/LoginRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful authentication
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AuthResponse'
|
||||
'400':
|
||||
description: Invalid credentials
|
||||
|
||||
/carts:
|
||||
get:
|
||||
operationId: getAllCarts
|
||||
tags:
|
||||
- carts
|
||||
summary: Get all carts
|
||||
description: Retrieve a list of all shopping carts
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 30
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
carts:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Cart'
|
||||
total:
|
||||
type: integer
|
||||
/carts/{id}:
|
||||
get:
|
||||
operationId: getCartById
|
||||
tags:
|
||||
- carts
|
||||
summary: Get a single cart
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Cart'
|
||||
|
||||
/comments:
|
||||
get:
|
||||
operationId: getAllComments
|
||||
tags:
|
||||
- comments
|
||||
summary: Get all comments
|
||||
description: Retrieve a list of all comments
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 30
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
comments:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Comment'
|
||||
total:
|
||||
type: integer
|
||||
/comments/{id}:
|
||||
get:
|
||||
operationId: getCommentById
|
||||
tags:
|
||||
- comments
|
||||
summary: Get a single comment
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Comment'
|
||||
|
||||
/posts:
|
||||
get:
|
||||
operationId: getAllPosts
|
||||
tags:
|
||||
- posts
|
||||
summary: Get all posts
|
||||
description: Retrieve a list of all posts
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 30
|
||||
- name: skip
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
posts:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Post'
|
||||
total:
|
||||
type: integer
|
||||
post:
|
||||
operationId: createPost
|
||||
tags:
|
||||
- posts
|
||||
summary: Add a new post
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Post'
|
||||
responses:
|
||||
'201':
|
||||
description: Post created successfully
|
||||
/posts/{id}:
|
||||
get:
|
||||
operationId: getPostById
|
||||
tags:
|
||||
- posts
|
||||
summary: Get a single post
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Post'
|
||||
|
||||
/products:
|
||||
get:
|
||||
operationId: getAllProducts
|
||||
tags:
|
||||
- products
|
||||
summary: Get all products
|
||||
description: Retrieve a list of all products
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 30
|
||||
- name: skip
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
products:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Product'
|
||||
total:
|
||||
type: integer
|
||||
post:
|
||||
operationId: createProduct
|
||||
tags:
|
||||
- products
|
||||
summary: Add a new product
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Product'
|
||||
responses:
|
||||
'201':
|
||||
description: Product created successfully
|
||||
/products/{id}:
|
||||
get:
|
||||
operationId: getProductById
|
||||
tags:
|
||||
- products
|
||||
summary: Get a single product
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Product'
|
||||
|
||||
/todos:
|
||||
get:
|
||||
operationId: getAllTodos
|
||||
tags:
|
||||
- todos
|
||||
summary: Get all todos
|
||||
description: Retrieve a list of all todos
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 30
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
todos:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Todo'
|
||||
total:
|
||||
type: integer
|
||||
post:
|
||||
operationId: createTodo
|
||||
tags:
|
||||
- todos
|
||||
summary: Add a new todo
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Todo'
|
||||
responses:
|
||||
'201':
|
||||
description: Todo created successfully
|
||||
/todos/{id}:
|
||||
get:
|
||||
operationId: getTodoById
|
||||
tags:
|
||||
- todos
|
||||
summary: Get a single todo
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Todo'
|
||||
|
||||
/users:
|
||||
get:
|
||||
operationId: getAllUsers
|
||||
tags:
|
||||
- users
|
||||
summary: Get all users
|
||||
description: Retrieve a list of all users
|
||||
parameters:
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 30
|
||||
- name: skip
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 0
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
users:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/User'
|
||||
total:
|
||||
type: integer
|
||||
skip:
|
||||
type: integer
|
||||
limit:
|
||||
type: integer
|
||||
post:
|
||||
operationId: createUser
|
||||
tags:
|
||||
- users
|
||||
summary: Add a new user
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
responses:
|
||||
'201':
|
||||
description: User created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
/users/{id}:
|
||||
get:
|
||||
operationId: getUserById
|
||||
tags:
|
||||
- users
|
||||
summary: Get a single user
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: Successful response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
'404':
|
||||
description: User not found
|
||||
|
||||
webhooks:
|
||||
|
||||
|
||||
newComment:
|
||||
post:
|
||||
summary: New comment notification
|
||||
description: Webhook sent when a new comment is created
|
||||
operationId: onNewComment
|
||||
requestBody:
|
||||
description: Comment data sent to subscriber
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
event:
|
||||
type: string
|
||||
example: comment.created
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
data:
|
||||
$ref: '#/components/schemas/Comment'
|
||||
responses:
|
||||
'200':
|
||||
description: Webhook received successfully
|
||||
'400':
|
||||
description: Bad request
|
||||
|
||||
newPost:
|
||||
post:
|
||||
summary: New post notification
|
||||
description: Webhook sent when a new post is published
|
||||
operationId: onNewPost
|
||||
requestBody:
|
||||
description: Post data sent to subscriber
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
event:
|
||||
type: string
|
||||
example: post.published
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
data:
|
||||
$ref: '#/components/schemas/Post'
|
||||
responses:
|
||||
'200':
|
||||
description: Webhook received successfully
|
||||
'400':
|
||||
description: Bad request
|
||||
components:
|
||||
schemas:
|
||||
|
||||
|
||||
AuthResponse:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
username:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
firstName:
|
||||
type: string
|
||||
lastName:
|
||||
type: string
|
||||
gender:
|
||||
type: string
|
||||
image:
|
||||
type: string
|
||||
format: uri
|
||||
accessToken:
|
||||
type: string
|
||||
refreshToken:
|
||||
type: string
|
||||
|
||||
Cart:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
products:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
price:
|
||||
type: number
|
||||
quantity:
|
||||
type: integer
|
||||
total:
|
||||
type: number
|
||||
discountPercentage:
|
||||
type: number
|
||||
discountedTotal:
|
||||
type: number
|
||||
total:
|
||||
type: number
|
||||
discountedTotal:
|
||||
type: number
|
||||
userId:
|
||||
type: integer
|
||||
totalProducts:
|
||||
type: integer
|
||||
totalQuantity:
|
||||
type: integer
|
||||
|
||||
Comment:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
body:
|
||||
type: string
|
||||
postId:
|
||||
type: integer
|
||||
likes:
|
||||
type: integer
|
||||
user:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
username:
|
||||
type: string
|
||||
fullName:
|
||||
type: string
|
||||
|
||||
LoginRequest:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
example: emilys
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
example: emilyspass
|
||||
expiresInMins:
|
||||
type: integer
|
||||
default: 60
|
||||
|
||||
Post:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
body:
|
||||
type: string
|
||||
tags:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
reactions:
|
||||
type: object
|
||||
properties:
|
||||
likes:
|
||||
type: integer
|
||||
dislikes:
|
||||
type: integer
|
||||
views:
|
||||
type: integer
|
||||
userId:
|
||||
type: integer
|
||||
|
||||
Product:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
category:
|
||||
type: string
|
||||
price:
|
||||
type: number
|
||||
format: float
|
||||
discountPercentage:
|
||||
type: number
|
||||
format: float
|
||||
rating:
|
||||
type: number
|
||||
format: float
|
||||
stock:
|
||||
type: integer
|
||||
brand:
|
||||
type: string
|
||||
thumbnail:
|
||||
type: string
|
||||
format: uri
|
||||
images:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: uri
|
||||
|
||||
Todo:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
todo:
|
||||
type: string
|
||||
completed:
|
||||
type: boolean
|
||||
userId:
|
||||
type: integer
|
||||
|
||||
User:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
firstName:
|
||||
type: string
|
||||
lastName:
|
||||
type: string
|
||||
maidenName:
|
||||
type: string
|
||||
age:
|
||||
type: integer
|
||||
gender:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
phone:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
birthDate:
|
||||
type: string
|
||||
format: date
|
||||
image:
|
||||
type: string
|
||||
format: uri
|
||||
address:
|
||||
type: object
|
||||
properties:
|
||||
address:
|
||||
type: string
|
||||
city:
|
||||
type: string
|
||||
state:
|
||||
type: string
|
||||
postalCode:
|
||||
type: string
|
||||
|
||||
securitySchemes:
|
||||
|
||||
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
description: JWT token obtained from /auth/login endpoint
|
||||
|
||||
externalDocs:
|
||||
|
||||
|
||||
description: DummyJSON Documentation
|
||||
url: https://dummyjson.com/docs
|
||||
@ -3,26 +3,42 @@ import XCTest
|
||||
|
||||
final class YamlMergerTests: XCTestCase {
|
||||
func testMergeSchemaYAML() throws {
|
||||
|
||||
print("📂 CWD:", FileManager.default.currentDirectoryPath)
|
||||
|
||||
// Access the resource from the test bundle
|
||||
|
||||
// 1) INPUT: Schema in the test bundle
|
||||
let bundle = Bundle.module
|
||||
guard let schemaFolder = bundle.url(forResource: "Schema", withExtension: nil) else {
|
||||
XCTFail("Failed to locate Schema folder in resources")
|
||||
return
|
||||
}
|
||||
|
||||
// Merge the files
|
||||
// 2) Merge as before (outputs inside schemaFolder)
|
||||
let merger = YAMLMerger(
|
||||
rootDirectory: schemaFolder,
|
||||
outputFileName: "CombinedSpec.yaml"
|
||||
)
|
||||
merger.merge()
|
||||
|
||||
// Optional: assert output file exists
|
||||
let outputURL = schemaFolder.appendingPathComponent("CombinedSpec.yaml")
|
||||
print("📂 CWD:", outputURL)
|
||||
XCTAssertTrue(FileManager.default.fileExists(atPath: outputURL.path))
|
||||
// 3) Verify source file exists where the merger wrote it
|
||||
let sourceURL = schemaFolder.appendingPathComponent("CombinedSpec.yaml")
|
||||
XCTAssertTrue(FileManager.default.fileExists(atPath: sourceURL.path),
|
||||
"Merged file not found at \(sourceURL.path)")
|
||||
|
||||
// 4) DEST: ~/Documents/CombinedSpec.yaml
|
||||
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
|
||||
let destURL = documentsURL.appendingPathComponent("CombinedSpec.yaml")
|
||||
|
||||
// Ensure Documents exists (it will) and replace if present
|
||||
let fm = FileManager.default
|
||||
if fm.fileExists(atPath: destURL.path) {
|
||||
try fm.removeItem(at: destURL)
|
||||
}
|
||||
|
||||
// 5) Copy (or use moveItem if you want to move instead of copy)
|
||||
try fm.copyItem(at: sourceURL, to: destURL)
|
||||
|
||||
// 6) Assert + log
|
||||
XCTAssertTrue(fm.fileExists(atPath: destURL.path))
|
||||
print("✅ Copied merged spec to:", destURL.path)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user