Initial project setup: Add contracts, API definitions, tests, and documentation
- Add Foundry project configuration (foundry.toml, foundry.lock) - Add Solidity contracts (TokenFactory138, BridgeVault138, ComplianceRegistry, etc.) - Add API definitions (OpenAPI, GraphQL, gRPC, AsyncAPI) - Add comprehensive test suite (unit, integration, fuzz, invariants) - Add API services (REST, GraphQL, orchestrator, packet service) - Add documentation (ISO20022 mapping, runbooks, adapter guides) - Add development tools (RBC tool, Swagger UI, mock server) - Update OpenZeppelin submodules to v5.0.0
This commit is contained in:
7
api/tools/swagger-ui/.dockerignore
Normal file
7
api/tools/swagger-ui/.dockerignore
Normal file
@@ -0,0 +1,7 @@
|
||||
node_modules
|
||||
dist
|
||||
*.log
|
||||
.env
|
||||
.git
|
||||
.DS_Store
|
||||
|
||||
28
api/tools/swagger-ui/Dockerfile
Normal file
28
api/tools/swagger-ui/Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
COPY tsconfig.json ./
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Install dependencies
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source files
|
||||
COPY src/ ./src/
|
||||
COPY ../../packages/openapi/v1/openapi.yaml ./packages/openapi/v1/openapi.yaml
|
||||
COPY static/ ./static/
|
||||
|
||||
# Build
|
||||
RUN pnpm run build
|
||||
|
||||
# Expose port
|
||||
EXPOSE 8080
|
||||
|
||||
# Start server
|
||||
CMD ["pnpm", "start"]
|
||||
|
||||
33
api/tools/swagger-ui/Makefile
Normal file
33
api/tools/swagger-ui/Makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
.PHONY: install build start dev generate-standalone docker-build docker-run help
|
||||
|
||||
help:
|
||||
@echo "Swagger UI Server - Available commands:"
|
||||
@echo " make install - Install dependencies"
|
||||
@echo " make build - Build TypeScript"
|
||||
@echo " make start - Start server"
|
||||
@echo " make dev - Start in development mode"
|
||||
@echo " make generate-standalone - Generate standalone HTML"
|
||||
@echo " make docker-build - Build Docker image"
|
||||
@echo " make docker-run - Run Docker container"
|
||||
|
||||
install:
|
||||
pnpm install
|
||||
|
||||
build:
|
||||
pnpm run build
|
||||
|
||||
start: build
|
||||
pnpm start
|
||||
|
||||
dev:
|
||||
pnpm run dev
|
||||
|
||||
generate-standalone:
|
||||
pnpm run generate:standalone
|
||||
|
||||
docker-build:
|
||||
docker build -t emoney-swagger-ui .
|
||||
|
||||
docker-run:
|
||||
docker run -p 8080:8080 emoney-swagger-ui
|
||||
|
||||
126
api/tools/swagger-ui/QUICKSTART.md
Normal file
126
api/tools/swagger-ui/QUICKSTART.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Swagger UI Quick Start Guide
|
||||
|
||||
## Local Development
|
||||
|
||||
### Option 1: Node.js (Recommended)
|
||||
|
||||
```bash
|
||||
cd api/tools/swagger-ui
|
||||
pnpm install
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
Visit: http://localhost:8080/api-docs
|
||||
|
||||
### Option 2: Docker
|
||||
|
||||
```bash
|
||||
cd api/tools/swagger-ui
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
Visit: http://localhost:8080/api-docs
|
||||
|
||||
## Features
|
||||
|
||||
### Interactive Documentation
|
||||
- Browse all API endpoints
|
||||
- View request/response schemas
|
||||
- See example payloads
|
||||
- Explore data models
|
||||
|
||||
### Try It Out
|
||||
- Test API calls directly from the browser
|
||||
- Set authentication tokens
|
||||
- View real responses
|
||||
- Debug API interactions
|
||||
|
||||
### Authentication Testing
|
||||
- OAuth2 client credentials flow
|
||||
- mTLS configuration
|
||||
- API key testing
|
||||
- Token persistence
|
||||
|
||||
### Export Options
|
||||
- Download OpenAPI spec as JSON
|
||||
- Download OpenAPI spec as YAML
|
||||
- Share documentation links
|
||||
|
||||
## API Endpoints
|
||||
|
||||
The Swagger UI server provides:
|
||||
|
||||
- `GET /api-docs` - Interactive documentation
|
||||
- `GET /openapi.json` - OpenAPI spec (JSON)
|
||||
- `GET /openapi.yaml` - OpenAPI spec (YAML)
|
||||
- `GET /health` - Health check
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
SWAGGER_PORT=8080 # Server port (default: 8080)
|
||||
```
|
||||
|
||||
### Customization
|
||||
|
||||
Edit `src/index.ts` to customize:
|
||||
- Swagger UI theme
|
||||
- Default expansion level
|
||||
- Supported HTTP methods
|
||||
- OAuth2 redirect URL
|
||||
|
||||
## Integration with Main API
|
||||
|
||||
To integrate Swagger UI into the main REST API server:
|
||||
|
||||
```typescript
|
||||
// In api/services/rest-api/src/index.ts
|
||||
import swaggerUi from 'swagger-ui-express';
|
||||
import YAML from 'yamljs';
|
||||
import { join } from 'path';
|
||||
|
||||
const openapiSpec = YAML.load(join(__dirname, '../../packages/openapi/v1/openapi.yaml'));
|
||||
|
||||
app.use('/docs', swaggerUi.serve, swaggerUi.setup(openapiSpec));
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Standalone Server
|
||||
|
||||
Deploy as separate service:
|
||||
- Lightweight Express server
|
||||
- Serves only documentation
|
||||
- Can be behind CDN
|
||||
- No API dependencies
|
||||
|
||||
### Embedded in API
|
||||
|
||||
Include in main API server:
|
||||
- Single deployment
|
||||
- Shared authentication
|
||||
- Live spec updates
|
||||
- Integrated experience
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### OpenAPI Spec Not Loading
|
||||
|
||||
1. Check file path: `../../packages/openapi/v1/openapi.yaml`
|
||||
2. Verify YAML syntax is valid
|
||||
3. Check file permissions
|
||||
|
||||
### OAuth2 Not Working
|
||||
|
||||
1. Verify redirect URL matches configuration
|
||||
2. Check CORS settings
|
||||
3. Ensure OAuth2 server is accessible
|
||||
|
||||
### Styles Not Loading
|
||||
|
||||
1. Check network tab for 404s
|
||||
2. Verify CDN is accessible
|
||||
3. Check custom CSS syntax
|
||||
|
||||
55
api/tools/swagger-ui/README.md
Normal file
55
api/tools/swagger-ui/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Swagger UI Server
|
||||
|
||||
Interactive API documentation server for the eMoney Token Factory API.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Start server
|
||||
pnpm start
|
||||
|
||||
# Or in development mode
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
The Swagger UI will be available at:
|
||||
- **Documentation**: http://localhost:8080/api-docs
|
||||
- **OpenAPI JSON**: http://localhost:8080/openapi.json
|
||||
- **OpenAPI YAML**: http://localhost:8080/openapi.yaml
|
||||
|
||||
## Features
|
||||
|
||||
- ✅ Interactive API documentation
|
||||
- ✅ Try-it-out functionality
|
||||
- ✅ Request/response examples
|
||||
- ✅ Authentication testing (OAuth2, mTLS, API Key)
|
||||
- ✅ Schema exploration
|
||||
- ✅ Export OpenAPI spec (JSON/YAML)
|
||||
|
||||
## Configuration
|
||||
|
||||
Set environment variables:
|
||||
|
||||
```bash
|
||||
export SWAGGER_PORT=8080 # Default: 8080
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. Navigate to http://localhost:8080/api-docs
|
||||
2. Click "Authorize" to set up authentication
|
||||
3. Explore endpoints by expanding sections
|
||||
4. Use "Try it out" to test API calls
|
||||
5. View request/response schemas
|
||||
|
||||
## Integration
|
||||
|
||||
This server can be:
|
||||
- Deployed standalone for documentation
|
||||
- Integrated into main API server
|
||||
- Used in CI/CD for API validation
|
||||
- Embedded in developer portals
|
||||
|
||||
278
api/tools/swagger-ui/SWAGGER_DOCS.md
Normal file
278
api/tools/swagger-ui/SWAGGER_DOCS.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# Swagger Documentation - Complete Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Full Swagger/OpenAPI documentation for the eMoney Token Factory API is available through an interactive Swagger UI server.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Option 1: Node.js Server (Recommended)
|
||||
|
||||
```bash
|
||||
cd api/tools/swagger-ui
|
||||
pnpm install
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
**Access**: http://localhost:8080/api-docs
|
||||
|
||||
### Option 2: Docker
|
||||
|
||||
```bash
|
||||
cd api/tools/swagger-ui
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
**Access**: http://localhost:8080/api-docs
|
||||
|
||||
### Option 3: Standalone HTML
|
||||
|
||||
```bash
|
||||
cd api/tools/swagger-ui
|
||||
pnpm install
|
||||
pnpm run build
|
||||
pnpm run generate:standalone
|
||||
```
|
||||
|
||||
**Output**: `static/standalone.html` (open directly in browser)
|
||||
|
||||
## Documentation Endpoints
|
||||
|
||||
When the server is running:
|
||||
|
||||
- **Interactive Docs**: http://localhost:8080/api-docs
|
||||
- **OpenAPI JSON**: http://localhost:8080/openapi.json
|
||||
- **OpenAPI YAML**: http://localhost:8080/openapi.yaml
|
||||
- **Standalone HTML**: http://localhost:8080/standalone
|
||||
- **Health Check**: http://localhost:8080/health
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Complete API Coverage
|
||||
|
||||
All API endpoints documented:
|
||||
- ✅ Token operations (deploy, mint, burn, clawback, force-transfer)
|
||||
- ✅ Lien management (place, reduce, release, query)
|
||||
- ✅ Compliance operations (set, freeze, query)
|
||||
- ✅ Account-Wallet mappings
|
||||
- ✅ Trigger management (ISO-20022 processing)
|
||||
- ✅ Packet operations (generate, dispatch, acknowledge)
|
||||
- ✅ Bridge operations (lock, unlock)
|
||||
|
||||
### 2. Interactive Testing
|
||||
|
||||
- **Try It Out**: Test any endpoint directly from the browser
|
||||
- **Request Builder**: Fill in parameters and see request format
|
||||
- **Response Viewer**: See actual API responses
|
||||
- **Error Handling**: View error responses with reason codes
|
||||
|
||||
### 3. Authentication Support
|
||||
|
||||
- **OAuth2**: Test client credentials flow
|
||||
- **mTLS**: Configure mutual TLS for adapters
|
||||
- **API Key**: Set API keys for internal services
|
||||
- **Token Persistence**: Tokens saved across page reloads
|
||||
|
||||
### 4. Schema Documentation
|
||||
|
||||
- **Data Models**: All request/response schemas
|
||||
- **Enums**: All enum values (ReasonCodes, TriggerStates, Rails, etc.)
|
||||
- **Examples**: Example payloads for each endpoint
|
||||
- **Validation Rules**: Field requirements and constraints
|
||||
|
||||
### 5. Export Options
|
||||
|
||||
- **Download JSON**: Get OpenAPI spec as JSON
|
||||
- **Download YAML**: Get OpenAPI spec as YAML
|
||||
- **Share Links**: Share specific endpoint documentation
|
||||
- **Embed**: Embed Swagger UI in other applications
|
||||
|
||||
## API Modules Documented
|
||||
|
||||
### Tokens Module
|
||||
- Deploy new eMoney tokens
|
||||
- Configure token policies
|
||||
- Mint and burn operations
|
||||
- Clawback and force transfer
|
||||
- Query token metadata
|
||||
|
||||
### Liens Module
|
||||
- Place liens on accounts
|
||||
- Reduce lien amounts
|
||||
- Release liens
|
||||
- Query lien information
|
||||
- Check encumbrance summaries
|
||||
|
||||
### Compliance Module
|
||||
- Set compliance profiles
|
||||
- Freeze/unfreeze accounts
|
||||
- Manage risk tiers
|
||||
- Set jurisdiction information
|
||||
- Query compliance status
|
||||
|
||||
### Mappings Module
|
||||
- Link accounts to wallets
|
||||
- Unlink mappings
|
||||
- Query account wallets
|
||||
- Query wallet accounts
|
||||
|
||||
### Triggers Module
|
||||
- Submit ISO-20022 messages
|
||||
- Query trigger status
|
||||
- Manage trigger lifecycle
|
||||
- View trigger history
|
||||
|
||||
### ISO-20022 Module
|
||||
- Submit inbound messages (from rails)
|
||||
- Submit outbound messages (to rails)
|
||||
- Message normalization
|
||||
- Instruction ID tracking
|
||||
|
||||
### Packets Module
|
||||
- Generate packets (PDF/AS4/Email)
|
||||
- Dispatch packets
|
||||
- Track acknowledgements
|
||||
- Download packet files
|
||||
|
||||
### Bridge Module
|
||||
- Lock tokens for cross-chain
|
||||
- Unlock tokens with proofs
|
||||
- Query lock status
|
||||
- View supported corridors
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Testing Token Deployment
|
||||
|
||||
1. Navigate to `/tokens` endpoint
|
||||
2. Click "Try it out"
|
||||
3. Fill in token configuration:
|
||||
```json
|
||||
{
|
||||
"name": "USD Wrapped",
|
||||
"symbol": "USDW",
|
||||
"decimals": 18,
|
||||
"issuer": "0x1234...",
|
||||
"defaultLienMode": "ENCUMBERED"
|
||||
}
|
||||
```
|
||||
4. Click "Execute"
|
||||
5. View response with token address
|
||||
|
||||
### Testing Lien Placement
|
||||
|
||||
1. Navigate to `/liens` endpoint
|
||||
2. Click "Try it out"
|
||||
3. Fill in lien details:
|
||||
```json
|
||||
{
|
||||
"debtor": "0xabcd...",
|
||||
"amount": "1000000000000000000",
|
||||
"priority": 1,
|
||||
"reasonCode": "DEBT_ENFORCEMENT"
|
||||
}
|
||||
```
|
||||
4. Click "Execute"
|
||||
5. View response with lien ID
|
||||
|
||||
### Setting Authentication
|
||||
|
||||
1. Click "Authorize" button at top
|
||||
2. Enter OAuth2 token in "Value" field
|
||||
3. Click "Authorize"
|
||||
4. Token will be used for all requests
|
||||
5. Click "Logout" to clear
|
||||
|
||||
## Integration
|
||||
|
||||
### Embed in Main API Server
|
||||
|
||||
Add to `api/services/rest-api/src/index.ts`:
|
||||
|
||||
```typescript
|
||||
import swaggerUi from 'swagger-ui-express';
|
||||
import YAML from 'yamljs';
|
||||
import { join } from 'path';
|
||||
|
||||
const openapiSpec = YAML.load(join(__dirname, '../../packages/openapi/v1/openapi.yaml'));
|
||||
|
||||
app.use('/docs', swaggerUi.serve, swaggerUi.setup(openapiSpec));
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
|
||||
1. **Standalone Service**: Deploy as separate service
|
||||
2. **CDN Distribution**: Serve via CDN for performance
|
||||
3. **Embedded**: Include in main API server
|
||||
4. **Static HTML**: Generate and serve static file
|
||||
|
||||
## Customization
|
||||
|
||||
### Change Port
|
||||
|
||||
```bash
|
||||
export SWAGGER_PORT=9000
|
||||
pnpm start
|
||||
```
|
||||
|
||||
### Custom Theme
|
||||
|
||||
Edit `src/index.ts`:
|
||||
|
||||
```typescript
|
||||
const swaggerOptions = {
|
||||
customCss: `
|
||||
.swagger-ui .info .title {
|
||||
color: #your-brand-color;
|
||||
font-family: 'Your Font';
|
||||
}
|
||||
`,
|
||||
};
|
||||
```
|
||||
|
||||
### Default Server
|
||||
|
||||
Set default API server:
|
||||
|
||||
```typescript
|
||||
swaggerOptions: {
|
||||
url: 'https://api.emoney.example.com/v1',
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Server Won't Start
|
||||
|
||||
- Check if port 8080 is available
|
||||
- Verify OpenAPI spec path is correct
|
||||
- Check YAML syntax is valid
|
||||
|
||||
### Spec Not Loading
|
||||
|
||||
- Verify `openapi.yaml` exists
|
||||
- Check file permissions
|
||||
- Validate YAML syntax
|
||||
|
||||
### Try It Out Fails
|
||||
|
||||
- Check CORS settings on API server
|
||||
- Verify authentication is set
|
||||
- Check network tab for errors
|
||||
- Ensure API server is running
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Keep Spec Updated**: Update OpenAPI spec as API changes
|
||||
2. **Use Examples**: Provide realistic examples in spec
|
||||
3. **Document Errors**: Include error response examples
|
||||
4. **Test Regularly**: Use Try It Out to validate endpoints
|
||||
5. **Share Links**: Share specific endpoint URLs with team
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [OpenAPI Specification](https://swagger.io/specification/)
|
||||
- [Swagger UI Documentation](https://swagger.io/tools/swagger-ui/)
|
||||
- [API Integration Cookbook](../docs/api/integration-cookbook.md)
|
||||
- [Error Catalog](../docs/api/error-catalog.md)
|
||||
|
||||
13
api/tools/swagger-ui/docker-compose.yml
Normal file
13
api/tools/swagger-ui/docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
swagger-ui:
|
||||
build: .
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- SWAGGER_PORT=8080
|
||||
volumes:
|
||||
- ../packages/openapi/v1/openapi.yaml:/app/packages/openapi/v1/openapi.yaml:ro
|
||||
restart: unless-stopped
|
||||
|
||||
28
api/tools/swagger-ui/package.json
Normal file
28
api/tools/swagger-ui/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "@emoney/swagger-ui",
|
||||
"version": "1.0.0",
|
||||
"description": "Swagger UI server for eMoney API documentation",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js",
|
||||
"dev": "ts-node-dev --respawn --transpile-only src/index.ts",
|
||||
"generate:standalone": "ts-node src/generate-standalone.ts",
|
||||
"docker:build": "docker build -t emoney-swagger-ui .",
|
||||
"docker:run": "docker run -p 8080:8080 emoney-swagger-ui"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"swagger-ui-express": "^5.0.0",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
"yamljs": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/swagger-ui-express": "^4.1.4",
|
||||
"@types/node": "^20.10.0",
|
||||
"typescript": "^5.3.0",
|
||||
"ts-node-dev": "^2.0.0",
|
||||
"ts-node": "^10.9.2"
|
||||
}
|
||||
}
|
||||
87
api/tools/swagger-ui/src/generate-standalone.ts
Normal file
87
api/tools/swagger-ui/src/generate-standalone.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Generate standalone HTML documentation
|
||||
* Creates a self-contained HTML file with embedded OpenAPI spec
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import YAML from 'yamljs';
|
||||
|
||||
const openapiPath = join(__dirname, '../../packages/openapi/v1/openapi.yaml');
|
||||
const openapiSpec = YAML.load(openapiPath);
|
||||
const outputPath = join(__dirname, '../swagger-ui/static/standalone.html');
|
||||
|
||||
const htmlTemplate = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>eMoney Token Factory API Documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5.10.3/swagger-ui.css" />
|
||||
<style>
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
.swagger-ui .topbar {
|
||||
display: none;
|
||||
}
|
||||
.swagger-ui .info {
|
||||
margin: 50px 0;
|
||||
}
|
||||
.swagger-ui .info .title {
|
||||
font-size: 36px;
|
||||
color: #3b4151;
|
||||
}
|
||||
.swagger-ui .info .description {
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
<script src="https://unpkg.com/swagger-ui-dist@5.10.3/swagger-ui-bundle.js"></script>
|
||||
<script src="https://unpkg.com/swagger-ui-dist@5.10.3/swagger-ui-standalone-preset.js"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
const spec = ${JSON.stringify(openapiSpec, null, 2)};
|
||||
|
||||
const ui = SwaggerUIBundle({
|
||||
spec: spec,
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout",
|
||||
persistAuthorization: true,
|
||||
displayRequestDuration: true,
|
||||
filter: true,
|
||||
tryItOutEnabled: true,
|
||||
supportedSubmitMethods: ['get', 'post', 'put', 'patch', 'delete'],
|
||||
docExpansion: 'list',
|
||||
defaultModelsExpandDepth: 2,
|
||||
defaultModelExpandDepth: 2,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
writeFileSync(outputPath, htmlTemplate);
|
||||
console.log(`Standalone HTML documentation generated: ${outputPath}`);
|
||||
|
||||
85
api/tools/swagger-ui/src/index.ts
Normal file
85
api/tools/swagger-ui/src/index.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Swagger UI Server
|
||||
* Serves interactive API documentation from OpenAPI specification
|
||||
*/
|
||||
|
||||
import express from 'express';
|
||||
import swaggerUi from 'swagger-ui-express';
|
||||
import YAML from 'yamljs';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import path from 'path';
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.SWAGGER_PORT || 8080;
|
||||
|
||||
// Load OpenAPI specification
|
||||
const openapiPath = join(__dirname, '../../packages/openapi/v1/openapi.yaml');
|
||||
const openapiSpec = YAML.load(openapiPath);
|
||||
|
||||
// Serve static files (OAuth2 redirect, standalone HTML)
|
||||
app.use('/static', express.static(join(__dirname, '../../swagger-ui/static')));
|
||||
|
||||
// Swagger UI options
|
||||
const swaggerOptions = {
|
||||
customCss: `
|
||||
.swagger-ui .topbar { display: none; }
|
||||
.swagger-ui .info { margin: 50px 0; }
|
||||
.swagger-ui .info .title { font-size: 36px; }
|
||||
.swagger-ui .info .description { font-size: 16px; line-height: 1.6; }
|
||||
.swagger-ui .scheme-container { margin: 20px 0; }
|
||||
`,
|
||||
customSiteTitle: 'eMoney Token Factory API Documentation',
|
||||
customfavIcon: '/favicon.ico',
|
||||
swaggerOptions: {
|
||||
persistAuthorization: true,
|
||||
displayRequestDuration: true,
|
||||
filter: true,
|
||||
tryItOutEnabled: true,
|
||||
supportedSubmitMethods: ['get', 'post', 'put', 'patch', 'delete'],
|
||||
docExpansion: 'list',
|
||||
defaultModelsExpandDepth: 2,
|
||||
defaultModelExpandDepth: 2,
|
||||
oauth2RedirectUrl: '/static/oauth2-redirect.html',
|
||||
},
|
||||
};
|
||||
|
||||
// Serve Swagger UI
|
||||
app.use('/api-docs', swaggerUi.serve);
|
||||
app.get('/api-docs', swaggerUi.setup(openapiSpec, swaggerOptions));
|
||||
|
||||
// Serve OpenAPI spec as JSON
|
||||
app.get('/openapi.json', (req, res) => {
|
||||
res.json(openapiSpec);
|
||||
});
|
||||
|
||||
// Serve OpenAPI spec as YAML
|
||||
app.get('/openapi.yaml', (req, res) => {
|
||||
res.setHeader('Content-Type', 'text/yaml');
|
||||
res.send(readFileSync(openapiPath, 'utf-8'));
|
||||
});
|
||||
|
||||
// Serve standalone HTML
|
||||
app.get('/standalone', (req, res) => {
|
||||
res.sendFile(join(__dirname, '../../swagger-ui/static/standalone.html'));
|
||||
});
|
||||
|
||||
// Redirect root to docs
|
||||
app.get('/', (req, res) => {
|
||||
res.redirect('/api-docs');
|
||||
});
|
||||
|
||||
// Health check
|
||||
app.get('/health', (req, res) => {
|
||||
res.json({ status: 'ok', service: 'swagger-ui' });
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Swagger UI server running on http://localhost:${PORT}`);
|
||||
console.log(`API Documentation: http://localhost:${PORT}/api-docs`);
|
||||
console.log(`OpenAPI JSON: http://localhost:${PORT}/openapi.json`);
|
||||
console.log(`OpenAPI YAML: http://localhost:${PORT}/openapi.yaml`);
|
||||
});
|
||||
|
||||
export default app;
|
||||
|
||||
66
api/tools/swagger-ui/static/index.html
Normal file
66
api/tools/swagger-ui/static/index.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>eMoney Token Factory API Documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5.10.3/swagger-ui.css" />
|
||||
<style>
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #fafafa;
|
||||
}
|
||||
.swagger-ui .topbar {
|
||||
display: none;
|
||||
}
|
||||
.swagger-ui .info {
|
||||
margin: 50px 0;
|
||||
}
|
||||
.swagger-ui .info .title {
|
||||
font-size: 36px;
|
||||
color: #3b4151;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
<script src="https://unpkg.com/swagger-ui-dist@5.10.3/swagger-ui-bundle.js"></script>
|
||||
<script src="https://unpkg.com/swagger-ui-dist@5.10.3/swagger-ui-standalone-preset.js"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "/openapi.yaml",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: "StandaloneLayout",
|
||||
persistAuthorization: true,
|
||||
displayRequestDuration: true,
|
||||
filter: true,
|
||||
tryItOutEnabled: true,
|
||||
supportedSubmitMethods: ['get', 'post', 'put', 'patch', 'delete'],
|
||||
docExpansion: 'list',
|
||||
defaultModelsExpandDepth: 2,
|
||||
defaultModelExpandDepth: 2,
|
||||
oauth2RedirectUrl: window.location.origin + '/oauth2-redirect.html'
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
76
api/tools/swagger-ui/static/oauth2-redirect.html
Normal file
76
api/tools/swagger-ui/static/oauth2-redirect.html
Normal file
@@ -0,0 +1,76 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1);
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&");
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
||||
qp = qp ? JSON.parse('{' + arr.join() +'}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value);
|
||||
}
|
||||
) : {};
|
||||
|
||||
isValid = qp.state === sentState;
|
||||
|
||||
if ((
|
||||
oauth2.auth.schema.get("flow") === "accessCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
||||
oauth2.auth.schema.get("flow") === "authorization_code"
|
||||
) && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
err: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||
} else {
|
||||
let oauthErrorMsg;
|
||||
if (qp.error) {
|
||||
oauthErrorMsg = "["+qp.error+"]: " +
|
||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
err: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
run();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', run);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
18
api/tools/swagger-ui/tsconfig.json
Normal file
18
api/tools/swagger-ui/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"lib": ["ES2020"],
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user