deleted obsolete code and added save to Documents

This commit is contained in:
Mihaela Mihaljevic 2025-10-25 23:50:04 +02:00
parent 51e4bae990
commit 78e3eaaf8f
3 changed files with 24 additions and 755 deletions

View File

@ -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:

View File

@ -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

View File

@ -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)
}
}