@mhmdalimansour/mock-mock 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +5 -0
- package/README.md +196 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +84 -0
- package/dist/cli.js.map +1 -0
- package/dist/fetcher/confluence.d.ts +7 -0
- package/dist/fetcher/confluence.d.ts.map +1 -0
- package/dist/fetcher/confluence.js +150 -0
- package/dist/fetcher/confluence.js.map +1 -0
- package/dist/parser/erd-parser.d.ts +11 -0
- package/dist/parser/erd-parser.d.ts.map +1 -0
- package/dist/parser/erd-parser.js +346 -0
- package/dist/parser/erd-parser.js.map +1 -0
- package/dist/parser/schema-types.d.ts +13 -0
- package/dist/parser/schema-types.d.ts.map +1 -0
- package/dist/parser/schema-types.js +7 -0
- package/dist/parser/schema-types.js.map +1 -0
- package/dist/server/data-generator.d.ts +6 -0
- package/dist/server/data-generator.d.ts.map +1 -0
- package/dist/server/data-generator.js +127 -0
- package/dist/server/data-generator.js.map +1 -0
- package/dist/server/mock-server.d.ts +3 -0
- package/dist/server/mock-server.d.ts.map +1 -0
- package/dist/server/mock-server.js +186 -0
- package/dist/server/mock-server.js.map +1 -0
- package/package.json +47 -0
package/.env.example
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# MockMock
|
|
2
|
+
|
|
3
|
+
> Production-grade CLI tool to generate mock API servers from Confluence documentation
|
|
4
|
+
|
|
5
|
+
MockMock fetches API endpoint definitions from Confluence pages, parses them into a structured schema, and spins up an Express mock server with those endpoints.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- š **Fast Setup**: Generate a mock server in seconds
|
|
10
|
+
- š **Confluence Integration**: Fetches API definitions directly from Confluence pages
|
|
11
|
+
- š **Auth Support**: Optional Basic Auth for private Confluence pages
|
|
12
|
+
- šÆ **Type-Safe**: Built with TypeScript for reliability
|
|
13
|
+
- š§© **Modular Architecture**: Clean separation of concerns
|
|
14
|
+
- š **Express-Powered**: Reliable and extensible mock server
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install
|
|
20
|
+
npm run build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Basic Usage
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm run dev -- --url https://your-confluence.com/pages/123456 --port 4000
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or using the built CLI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
mockgen --url <confluence-url> --port 4000
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Options
|
|
38
|
+
|
|
39
|
+
- `--url, -u` **(required)**: Confluence page URL containing API definitions
|
|
40
|
+
- `--port, -p` (optional): Port for the mock server (default: 4000)
|
|
41
|
+
|
|
42
|
+
### Authentication
|
|
43
|
+
|
|
44
|
+
For private Confluence pages, set these environment variables:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
export CONFLUENCE_EMAIL=your-email@example.com
|
|
48
|
+
export CONFLUENCE_API_TOKEN=your-api-token
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Then run the CLI as normal.
|
|
52
|
+
|
|
53
|
+
## API Definition Format
|
|
54
|
+
|
|
55
|
+
MockMock expects code blocks in your Confluence page with this format:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
POST /api/categories
|
|
59
|
+
|
|
60
|
+
Request:
|
|
61
|
+
{
|
|
62
|
+
"name": "string"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Response:
|
|
66
|
+
{
|
|
67
|
+
"id": 1,
|
|
68
|
+
"name": "string"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Supported Fields
|
|
73
|
+
|
|
74
|
+
- **HTTP Method**: GET, POST, PUT, DELETE
|
|
75
|
+
- **Path**: The endpoint path (e.g., `/api/users`)
|
|
76
|
+
- **Request** (optional): JSON body schema
|
|
77
|
+
- **Response** (required): JSON response body
|
|
78
|
+
- **Status** (optional): HTTP status code (default: 200)
|
|
79
|
+
|
|
80
|
+
### Example
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
GET /api/users
|
|
84
|
+
|
|
85
|
+
Response:
|
|
86
|
+
{
|
|
87
|
+
"users": [
|
|
88
|
+
{
|
|
89
|
+
"id": 1,
|
|
90
|
+
"name": "John Doe"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
POST /api/users
|
|
98
|
+
|
|
99
|
+
Request:
|
|
100
|
+
{
|
|
101
|
+
"name": "string",
|
|
102
|
+
"email": "string"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
Response:
|
|
106
|
+
{
|
|
107
|
+
"id": 1,
|
|
108
|
+
"name": "string",
|
|
109
|
+
"email": "string"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
Status: 201
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Architecture
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
mock-mock/
|
|
119
|
+
src/
|
|
120
|
+
cli.ts # CLI entry point
|
|
121
|
+
fetcher/
|
|
122
|
+
confluence.ts # Confluence page fetcher
|
|
123
|
+
parser/
|
|
124
|
+
erd-parser.ts # Endpoint parser
|
|
125
|
+
schema-types.ts # Schema definitions
|
|
126
|
+
server/
|
|
127
|
+
mock-server.ts # Express mock server
|
|
128
|
+
package.json
|
|
129
|
+
tsconfig.json
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Layer Independence
|
|
133
|
+
|
|
134
|
+
Each layer is independent and communicates through the `MockSchema` interface:
|
|
135
|
+
|
|
136
|
+
1. **Fetcher**: Retrieves raw HTML from Confluence
|
|
137
|
+
2. **Parser**: Extracts and normalizes endpoints into `MockSchema`
|
|
138
|
+
3. **Server**: Consumes `MockSchema` and creates Express routes
|
|
139
|
+
|
|
140
|
+
## Development
|
|
141
|
+
|
|
142
|
+
### Run in Development Mode
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npm run dev -- --url <confluence-url>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Build
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm run build
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Run Built Version
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm start -- --url <confluence-url>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Error Handling
|
|
161
|
+
|
|
162
|
+
MockMock gracefully handles:
|
|
163
|
+
|
|
164
|
+
- ā Invalid Confluence URLs
|
|
165
|
+
- ā Network errors
|
|
166
|
+
- ā Malformed JSON in code blocks
|
|
167
|
+
- ā Missing endpoints
|
|
168
|
+
- ā Invalid port numbers
|
|
169
|
+
|
|
170
|
+
## Example Output
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
š MockMock CLI
|
|
174
|
+
|
|
175
|
+
š Fetching Confluence page: https://confluence.example.com/123456
|
|
176
|
+
ā
Page fetched successfully
|
|
177
|
+
|
|
178
|
+
š Parsing API endpoints...
|
|
179
|
+
ā
Found 3 endpoint(s)
|
|
180
|
+
|
|
181
|
+
š” Registering endpoints:
|
|
182
|
+
|
|
183
|
+
GET /api/users
|
|
184
|
+
POST /api/users
|
|
185
|
+
DELETE /api/users/1
|
|
186
|
+
|
|
187
|
+
ā
Mock server started successfully!
|
|
188
|
+
|
|
189
|
+
š Base URL: http://localhost:4000
|
|
190
|
+
š Total endpoints: 3
|
|
191
|
+
š Health check: http://localhost:4000/health
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
// Load environment variables from .env file
|
|
8
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
9
|
+
dotenv_1.default.config();
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
const confluence_1 = require("./fetcher/confluence");
|
|
13
|
+
const erd_parser_1 = require("./parser/erd-parser");
|
|
14
|
+
const mock_server_1 = require("./server/mock-server");
|
|
15
|
+
const package_json_1 = __importDefault(require("../package.json"));
|
|
16
|
+
const program = new commander_1.Command();
|
|
17
|
+
program
|
|
18
|
+
.name("mock-mock")
|
|
19
|
+
.description("Generate mock API server from Confluence API documentation")
|
|
20
|
+
.version(package_json_1.default.version)
|
|
21
|
+
.requiredOption("-u, --url <url>", "Confluence page URL containing API definitions")
|
|
22
|
+
.option("-p, --port <port>", "Port for mock server", "4000")
|
|
23
|
+
.option("-f, --fallback <url>", "Fallback base URL to proxy requests not found in the ERD")
|
|
24
|
+
.option("--delay <ms>", "Response delay in milliseconds to simulate real API latency", "0")
|
|
25
|
+
.option("-e, --email <email>", "Confluence email (overrides CONFLUENCE_EMAIL env var)")
|
|
26
|
+
.option("-t, --token <token>", "Confluence API token (overrides CONFLUENCE_API_TOKEN env var)")
|
|
27
|
+
.option("-d, --debug", "Enable debug mode (saves HTML to debug.html)")
|
|
28
|
+
.action(async (options) => {
|
|
29
|
+
try {
|
|
30
|
+
if (options.email)
|
|
31
|
+
process.env.CONFLUENCE_EMAIL = options.email;
|
|
32
|
+
if (options.token)
|
|
33
|
+
process.env.CONFLUENCE_API_TOKEN = options.token;
|
|
34
|
+
const url = options.url;
|
|
35
|
+
const port = parseInt(options.port, 10);
|
|
36
|
+
const delay = parseInt(options.delay, 10);
|
|
37
|
+
const fallbackUrl = options.fallback;
|
|
38
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
39
|
+
console.error("ā Invalid port number. Must be between 1 and 65535.");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
if (isNaN(delay) || delay < 0) {
|
|
43
|
+
console.error("ā Invalid delay. Must be a non-negative number in milliseconds.");
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
console.log("š MockMock CLI\n");
|
|
47
|
+
console.log(`š Fetching Confluence page: ${url}`);
|
|
48
|
+
// Step 1: Fetch HTML from Confluence
|
|
49
|
+
const html = await (0, confluence_1.fetchConfluencePage)(url);
|
|
50
|
+
console.log("ā
Page fetched successfully\n");
|
|
51
|
+
// Debug mode: save HTML to file
|
|
52
|
+
if (options.debug) {
|
|
53
|
+
(0, fs_1.writeFileSync)("debug.html", html);
|
|
54
|
+
console.log("š Debug: HTML saved to debug.html\n");
|
|
55
|
+
}
|
|
56
|
+
// Step 2: Parse endpoints
|
|
57
|
+
console.log("š Parsing API endpoints...");
|
|
58
|
+
const schema = (0, erd_parser_1.parseERDFromHTML)(html);
|
|
59
|
+
if (options.debug && schema.length > 0) {
|
|
60
|
+
console.log("š Debug: Parsed endpoints:");
|
|
61
|
+
console.log(JSON.stringify(schema, null, 2));
|
|
62
|
+
console.log();
|
|
63
|
+
}
|
|
64
|
+
(0, erd_parser_1.validateSchema)(schema);
|
|
65
|
+
console.log(`ā
Found ${schema.length} endpoint(s)\n`);
|
|
66
|
+
// Step 3: Start mock server
|
|
67
|
+
if (fallbackUrl) {
|
|
68
|
+
console.log(`š Fallback URL: ${fallbackUrl}`);
|
|
69
|
+
console.log(" Unmatched requests will be proxied to this URL\n");
|
|
70
|
+
}
|
|
71
|
+
(0, mock_server_1.startMockServer)(schema, port, fallbackUrl, delay);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (error instanceof Error) {
|
|
75
|
+
console.error(`\nā Error: ${error.message}\n`);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
console.error("\nā An unexpected error occurred\n");
|
|
79
|
+
}
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
program.parse();
|
|
84
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches HTML content from a Confluence page
|
|
3
|
+
* Supports optional Basic Auth via environment variables
|
|
4
|
+
* Automatically uses Confluence REST API for Atlassian Cloud URLs
|
|
5
|
+
*/
|
|
6
|
+
export declare function fetchConfluencePage(url: string): Promise<string>;
|
|
7
|
+
//# sourceMappingURL=confluence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confluence.d.ts","sourceRoot":"","sources":["../../src/fetcher/confluence.ts"],"names":[],"mappings":"AAyBA;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwFtE"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fetchConfluencePage = fetchConfluencePage;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
/**
|
|
10
|
+
* Extracts page ID from Confluence URL
|
|
11
|
+
*/
|
|
12
|
+
function extractPageId(url) {
|
|
13
|
+
// Match patterns like /pages/655949830/ or /pages/655949830/Page+Title
|
|
14
|
+
const match = url.match(/\/pages\/(\d+)/);
|
|
15
|
+
return match ? match[1] : null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Extracts Confluence base URL
|
|
19
|
+
*/
|
|
20
|
+
function extractBaseUrl(url) {
|
|
21
|
+
try {
|
|
22
|
+
const urlObj = new URL(url);
|
|
23
|
+
return `${urlObj.protocol}//${urlObj.hostname}`;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetches HTML content from a Confluence page
|
|
31
|
+
* Supports optional Basic Auth via environment variables
|
|
32
|
+
* Automatically uses Confluence REST API for Atlassian Cloud URLs
|
|
33
|
+
*/
|
|
34
|
+
async function fetchConfluencePage(url) {
|
|
35
|
+
try {
|
|
36
|
+
// Handle local file URLs
|
|
37
|
+
if (url.startsWith('file://')) {
|
|
38
|
+
console.log('š Reading local file\n');
|
|
39
|
+
try {
|
|
40
|
+
let filePath = url.replace('file://', '');
|
|
41
|
+
// Handle Windows paths: file:///c:/path or file:///c|/path
|
|
42
|
+
if (filePath.startsWith('/') && filePath.match(/^\/[a-zA-Z][:|\|]/)) {
|
|
43
|
+
filePath = filePath.substring(1).replace('|', ':');
|
|
44
|
+
}
|
|
45
|
+
return (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw new Error(`Failed to read local file: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const email = process.env.CONFLUENCE_EMAIL;
|
|
52
|
+
const token = process.env.CONFLUENCE_API_TOKEN;
|
|
53
|
+
// Check if this is an Atlassian Cloud URL
|
|
54
|
+
const isAtlassianCloud = url.includes('.atlassian.net');
|
|
55
|
+
const pageId = extractPageId(url);
|
|
56
|
+
const baseUrl = extractBaseUrl(url);
|
|
57
|
+
// For Atlassian Cloud with credentials, use the REST API
|
|
58
|
+
if (isAtlassianCloud && email && token && pageId && baseUrl) {
|
|
59
|
+
console.log('š Using Confluence REST API with authentication\n');
|
|
60
|
+
return await fetchViaRestApi(baseUrl, pageId, email, token);
|
|
61
|
+
}
|
|
62
|
+
// Fallback: Try direct fetch (for local files or public pages)
|
|
63
|
+
const config = {
|
|
64
|
+
headers: {
|
|
65
|
+
'Accept': 'text/html',
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
if (email && token) {
|
|
69
|
+
config.auth = {
|
|
70
|
+
username: email,
|
|
71
|
+
password: token,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
else if (isAtlassianCloud) {
|
|
75
|
+
console.log('ā ļø No authentication credentials found');
|
|
76
|
+
console.log(' Set CONFLUENCE_EMAIL and CONFLUENCE_API_TOKEN for private pages\n');
|
|
77
|
+
}
|
|
78
|
+
const response = await axios_1.default.get(url, config);
|
|
79
|
+
const html = response.data;
|
|
80
|
+
// Check if we got a login page instead of content
|
|
81
|
+
if (html.includes('Log in with Atlassian account') ||
|
|
82
|
+
html.includes('id-frontend.prod') ||
|
|
83
|
+
html.includes('JavaScript is disabled')) {
|
|
84
|
+
throw new Error('Received login page instead of content. Please provide authentication credentials.\n' +
|
|
85
|
+
' Set CONFLUENCE_EMAIL and CONFLUENCE_API_TOKEN environment variables.\n' +
|
|
86
|
+
' See AUTH_SETUP.md for detailed instructions.');
|
|
87
|
+
}
|
|
88
|
+
return html;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
92
|
+
if (error.response?.status === 401) {
|
|
93
|
+
throw new Error('Authentication failed (401 Unauthorized).\n' +
|
|
94
|
+
' Check your CONFLUENCE_EMAIL and CONFLUENCE_API_TOKEN credentials.\n' +
|
|
95
|
+
' See AUTH_SETUP.md for setup instructions.');
|
|
96
|
+
}
|
|
97
|
+
if (error.response?.status === 403) {
|
|
98
|
+
throw new Error('Access forbidden (403). You don\'t have permission to view this page.\n' +
|
|
99
|
+
' Ask your Confluence admin for access.');
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`Failed to fetch Confluence page: ${error.message}${error.response?.status ? ` (Status: ${error.response.status})` : ''}`);
|
|
102
|
+
}
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Fetches page content via Confluence REST API
|
|
108
|
+
*/
|
|
109
|
+
async function fetchViaRestApi(baseUrl, pageId, email, token) {
|
|
110
|
+
try {
|
|
111
|
+
// Try v1 API first (more commonly used)
|
|
112
|
+
const apiUrl = `${baseUrl}/wiki/rest/api/content/${pageId}?expand=body.storage`;
|
|
113
|
+
const config = {
|
|
114
|
+
headers: {
|
|
115
|
+
'Accept': 'application/json',
|
|
116
|
+
},
|
|
117
|
+
auth: {
|
|
118
|
+
username: email,
|
|
119
|
+
password: token,
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
const response = await axios_1.default.get(apiUrl, config);
|
|
123
|
+
// The API returns JSON with the page body in storage format (HTML)
|
|
124
|
+
const pageData = response.data;
|
|
125
|
+
if (pageData.body && pageData.body.storage && pageData.body.storage.value) {
|
|
126
|
+
return pageData.body.storage.value;
|
|
127
|
+
}
|
|
128
|
+
throw new Error('Page body not found in API response');
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
132
|
+
if (error.response?.status === 401) {
|
|
133
|
+
throw new Error('Authentication failed (401 Unauthorized).\n' +
|
|
134
|
+
' Check your CONFLUENCE_EMAIL and CONFLUENCE_API_TOKEN credentials.\n' +
|
|
135
|
+
' Make sure the API token is valid and not expired.');
|
|
136
|
+
}
|
|
137
|
+
if (error.response?.status === 403) {
|
|
138
|
+
throw new Error('Access forbidden (403). You don\'t have permission to view this page.\n' +
|
|
139
|
+
' Ask your Confluence admin for access.');
|
|
140
|
+
}
|
|
141
|
+
if (error.response?.status === 404) {
|
|
142
|
+
throw new Error('Page not found (404). Check that the page ID is correct.\n' +
|
|
143
|
+
' URL should contain /pages/[PAGE_ID]/');
|
|
144
|
+
}
|
|
145
|
+
throw new Error(`Confluence API error: ${error.message}${error.response?.status ? ` (Status: ${error.response.status})` : ''}`);
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=confluence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confluence.js","sourceRoot":"","sources":["../../src/fetcher/confluence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MockSchema } from './schema-types';
|
|
2
|
+
/**
|
|
3
|
+
* Parses API endpoint definitions from Confluence HTML
|
|
4
|
+
* Supports both code blocks and table-based formats
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseERDFromHTML(html: string): MockSchema;
|
|
7
|
+
/**
|
|
8
|
+
* Validates that the parsed schema contains at least one endpoint
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateSchema(schema: MockSchema): void;
|
|
11
|
+
//# sourceMappingURL=erd-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"erd-parser.d.ts","sourceRoot":"","sources":["../../src/parser/erd-parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CA6BzD;AAsTD;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAIvD"}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseERDFromHTML = parseERDFromHTML;
|
|
37
|
+
exports.validateSchema = validateSchema;
|
|
38
|
+
const cheerio = __importStar(require("cheerio"));
|
|
39
|
+
/**
|
|
40
|
+
* Parses API endpoint definitions from Confluence HTML
|
|
41
|
+
* Supports both code blocks and table-based formats
|
|
42
|
+
*/
|
|
43
|
+
function parseERDFromHTML(html) {
|
|
44
|
+
const $ = cheerio.load(html);
|
|
45
|
+
let endpoints = [];
|
|
46
|
+
// Strategy 1: Try parsing tables (common in Confluence ERD pages)
|
|
47
|
+
const tableEndpoints = parseTableBasedEndpoints($, html);
|
|
48
|
+
if (tableEndpoints.length > 0) {
|
|
49
|
+
endpoints.push(...tableEndpoints);
|
|
50
|
+
}
|
|
51
|
+
// Strategy 2: Try parsing code blocks (original format)
|
|
52
|
+
const codeBlocks = $('pre, code, div.code, div.codeContent').toArray();
|
|
53
|
+
for (const block of codeBlocks) {
|
|
54
|
+
const text = $(block).text().trim();
|
|
55
|
+
if (!text)
|
|
56
|
+
continue;
|
|
57
|
+
try {
|
|
58
|
+
const endpoint = parseEndpointFromText(text);
|
|
59
|
+
if (endpoint) {
|
|
60
|
+
endpoints.push(endpoint);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
// Gracefully skip invalid blocks
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return endpoints;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Parses a single endpoint definition from text
|
|
72
|
+
*/
|
|
73
|
+
function parseEndpointFromText(text) {
|
|
74
|
+
// Match HTTP method and path (e.g., "POST /api/categories")
|
|
75
|
+
const methodPathRegex = /^(GET|POST|PUT|DELETE)\s+(\/[^\s\n]*)/im;
|
|
76
|
+
const methodPathMatch = text.match(methodPathRegex);
|
|
77
|
+
if (!methodPathMatch) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const method = methodPathMatch[1].toUpperCase();
|
|
81
|
+
const path = methodPathMatch[2];
|
|
82
|
+
// Extract Request JSON
|
|
83
|
+
let request = undefined;
|
|
84
|
+
const requestMatch = text.match(/Request:\s*\n\s*(\{[\s\S]*?\})/i);
|
|
85
|
+
if (requestMatch) {
|
|
86
|
+
try {
|
|
87
|
+
request = JSON.parse(requestMatch[1]);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Invalid JSON, skip request
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Extract Response JSON
|
|
94
|
+
let response = {};
|
|
95
|
+
const responseMatch = text.match(/Response:\s*\n\s*(\{[\s\S]*?\})/i);
|
|
96
|
+
if (responseMatch) {
|
|
97
|
+
try {
|
|
98
|
+
response = JSON.parse(responseMatch[1]);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Invalid JSON, use empty object
|
|
102
|
+
response = {};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Extract status code if specified
|
|
106
|
+
let status = undefined;
|
|
107
|
+
const statusMatch = text.match(/Status:\s*(\d{3})/i);
|
|
108
|
+
if (statusMatch) {
|
|
109
|
+
status = parseInt(statusMatch[1], 10);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
method,
|
|
113
|
+
path,
|
|
114
|
+
request,
|
|
115
|
+
response,
|
|
116
|
+
status,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Extracts all code snippets from CDATA blocks in raw HTML
|
|
121
|
+
*/
|
|
122
|
+
function extractCDATASnippets(html) {
|
|
123
|
+
const snippets = [];
|
|
124
|
+
// Find all CDATA blocks
|
|
125
|
+
const cdataRegex = /<!\[CDATA\[([\s\S]*?)\]\]>/g;
|
|
126
|
+
let match;
|
|
127
|
+
while ((match = cdataRegex.exec(html)) !== null) {
|
|
128
|
+
const cdataContent = match[1];
|
|
129
|
+
const snippet = {};
|
|
130
|
+
// Extract Response Structure
|
|
131
|
+
if (cdataContent.includes('Response Structure:')) {
|
|
132
|
+
const responseJSON = extractCompleteJSON(cdataContent, 'Response Structure:');
|
|
133
|
+
if (responseJSON) {
|
|
134
|
+
snippet.response = responseJSON;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Extract Request Structure or Body
|
|
138
|
+
if (cdataContent.includes('Request Structure:') || cdataContent.includes('Body:')) {
|
|
139
|
+
const keyword = cdataContent.includes('Request Structure:') ? 'Request Structure:' : 'Body:';
|
|
140
|
+
const requestJSON = extractCompleteJSON(cdataContent, keyword);
|
|
141
|
+
if (requestJSON) {
|
|
142
|
+
snippet.request = requestJSON;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (snippet.response || snippet.request) {
|
|
146
|
+
snippets.push(snippet);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return snippets;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Parses endpoints from Confluence table format
|
|
153
|
+
* Handles Confluence storage format (XML-like structure)
|
|
154
|
+
*/
|
|
155
|
+
function parseTableBasedEndpoints($, html) {
|
|
156
|
+
const endpoints = [];
|
|
157
|
+
// Extract all code snippets from CDATA blocks first
|
|
158
|
+
const allSnippets = extractCDATASnippets(html);
|
|
159
|
+
let snippetIndex = 0;
|
|
160
|
+
// Find all tables
|
|
161
|
+
const tables = $('table').toArray();
|
|
162
|
+
console.log(`[DEBUG] Found ${tables.length} tables in HTML`);
|
|
163
|
+
for (let i = 0; i < tables.length; i++) {
|
|
164
|
+
const table = tables[i];
|
|
165
|
+
const endpoint = parseEndpointFromTable($, table);
|
|
166
|
+
console.log(`[DEBUG] Table ${i + 1}: ${endpoint ? `${endpoint.method} ${endpoint.path}` : 'No endpoint found'}`);
|
|
167
|
+
if (endpoint) {
|
|
168
|
+
// Use the next available code snippet from CDATA
|
|
169
|
+
const codeSnippet = allSnippets[snippetIndex] || {};
|
|
170
|
+
endpoint.response = codeSnippet.response || { message: 'Success', data: {} };
|
|
171
|
+
endpoint.request = codeSnippet.request;
|
|
172
|
+
// Determine status based on method
|
|
173
|
+
if (!endpoint.status) {
|
|
174
|
+
endpoint.status = endpoint.method === 'POST' ? 201 : 200;
|
|
175
|
+
}
|
|
176
|
+
endpoints.push(endpoint);
|
|
177
|
+
snippetIndex++;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
console.log(`[DEBUG] Total endpoints parsed: ${endpoints.length}`);
|
|
181
|
+
return endpoints;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Parses a single endpoint from a table
|
|
185
|
+
*/
|
|
186
|
+
function parseEndpointFromTable($, table) {
|
|
187
|
+
const rows = $(table).find('tr').toArray();
|
|
188
|
+
const endpoint = {};
|
|
189
|
+
let hasMethodRow = false;
|
|
190
|
+
let hasUrlRow = false;
|
|
191
|
+
for (const row of rows) {
|
|
192
|
+
try {
|
|
193
|
+
const th = $(row).find('th').first();
|
|
194
|
+
const td = $(row).find('td').first();
|
|
195
|
+
if (th.length === 0 || td.length === 0)
|
|
196
|
+
continue;
|
|
197
|
+
const label = th.text().trim().toLowerCase();
|
|
198
|
+
const valueElem = td;
|
|
199
|
+
// Extract value - handle both text and code elements
|
|
200
|
+
let value = valueElem.find('code').text().trim() || valueElem.text().trim();
|
|
201
|
+
// Parse URL field
|
|
202
|
+
if (label.includes('url') || label.includes('endpoint')) {
|
|
203
|
+
hasUrlRow = true;
|
|
204
|
+
let url = value.split('?')[0]; // Remove query params
|
|
205
|
+
// Handle paths like "api/inventory/..." or "/api/inventory/..."
|
|
206
|
+
if (url.startsWith('api/')) {
|
|
207
|
+
url = '/' + url;
|
|
208
|
+
}
|
|
209
|
+
else if (!url.startsWith('/') && url.includes('api/')) {
|
|
210
|
+
url = '/' + url;
|
|
211
|
+
}
|
|
212
|
+
endpoint.path = url;
|
|
213
|
+
}
|
|
214
|
+
// Parse Method field
|
|
215
|
+
if (label.includes('method')) {
|
|
216
|
+
hasMethodRow = true;
|
|
217
|
+
// Extract method from status macro or plain text (no word boundaries needed - handles "POSTPurple", etc.)
|
|
218
|
+
const methodMatch = value.match(/(GET|POST|PUT|DELETE|PATCH)/i);
|
|
219
|
+
if (methodMatch) {
|
|
220
|
+
endpoint.method = methodMatch[1].toUpperCase();
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
// Debug: couldn't find method in value
|
|
224
|
+
console.log(`[DEBUG] Method field found but no HTTP method in value: "${value}"`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Debug logging
|
|
233
|
+
if (hasMethodRow || hasUrlRow) {
|
|
234
|
+
console.log(`[DEBUG] Table scan: URL=${hasUrlRow}(${endpoint.path || 'none'}), Method=${hasMethodRow}(${endpoint.method || 'none'})`);
|
|
235
|
+
}
|
|
236
|
+
// Only return if we have both method and path
|
|
237
|
+
if (endpoint.method && endpoint.path) {
|
|
238
|
+
return endpoint;
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Extracts a complete JSON object from text, handling nested structures
|
|
244
|
+
*/
|
|
245
|
+
function extractCompleteJSON(text, startKeyword) {
|
|
246
|
+
const startIndex = text.indexOf(startKeyword);
|
|
247
|
+
if (startIndex === -1)
|
|
248
|
+
return null;
|
|
249
|
+
// Find the first opening brace after the keyword
|
|
250
|
+
const jsonStart = text.indexOf('{', startIndex);
|
|
251
|
+
if (jsonStart === -1)
|
|
252
|
+
return null;
|
|
253
|
+
// Count braces to find the matching closing brace
|
|
254
|
+
let braceCount = 0;
|
|
255
|
+
let inString = false;
|
|
256
|
+
let escapeNext = false;
|
|
257
|
+
let jsonEnd = -1;
|
|
258
|
+
for (let i = jsonStart; i < text.length; i++) {
|
|
259
|
+
const char = text[i];
|
|
260
|
+
if (escapeNext) {
|
|
261
|
+
escapeNext = false;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (char === '\\') {
|
|
265
|
+
escapeNext = true;
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (char === '"') {
|
|
269
|
+
inString = !inString;
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (inString)
|
|
273
|
+
continue;
|
|
274
|
+
if (char === '{') {
|
|
275
|
+
braceCount++;
|
|
276
|
+
}
|
|
277
|
+
else if (char === '}') {
|
|
278
|
+
braceCount--;
|
|
279
|
+
if (braceCount === 0) {
|
|
280
|
+
jsonEnd = i + 1;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (jsonEnd === -1)
|
|
286
|
+
return null;
|
|
287
|
+
const jsonStr = text.substring(jsonStart, jsonEnd);
|
|
288
|
+
try {
|
|
289
|
+
return JSON.parse(jsonStr);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Extracts request/response JSON from Confluence expand/code macros
|
|
297
|
+
*/
|
|
298
|
+
function extractCodeSnippetsFromExpand($, elements) {
|
|
299
|
+
const result = {};
|
|
300
|
+
// Look for Confluence expand macros or code blocks
|
|
301
|
+
elements.each((_idx, elem) => {
|
|
302
|
+
const text = $(elem).text();
|
|
303
|
+
// Look for "Response Structure:" or "Response:"
|
|
304
|
+
if (text.includes('Response Structure:')) {
|
|
305
|
+
const json = extractCompleteJSON(text, 'Response Structure:');
|
|
306
|
+
if (json) {
|
|
307
|
+
result.response = json;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
else if (text.includes('Response:') && !text.includes('Response Structure:')) {
|
|
311
|
+
const json = extractCompleteJSON(text, 'Response:');
|
|
312
|
+
if (json) {
|
|
313
|
+
result.response = json;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Look for "Request Structure:" or "Request Body:"
|
|
317
|
+
if (text.includes('Request Structure:')) {
|
|
318
|
+
const json = extractCompleteJSON(text, 'Request Structure:');
|
|
319
|
+
if (json) {
|
|
320
|
+
result.request = json;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
else if (text.includes('Request Body:')) {
|
|
324
|
+
const json = extractCompleteJSON(text, 'Request Body:');
|
|
325
|
+
if (json) {
|
|
326
|
+
result.request = json;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
else if (text.includes('Request:') && !text.includes('Response')) {
|
|
330
|
+
const json = extractCompleteJSON(text, 'Request:');
|
|
331
|
+
if (json) {
|
|
332
|
+
result.request = json;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Validates that the parsed schema contains at least one endpoint
|
|
340
|
+
*/
|
|
341
|
+
function validateSchema(schema) {
|
|
342
|
+
if (schema.length === 0) {
|
|
343
|
+
throw new Error('No valid endpoints found in the Confluence page');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=erd-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"erd-parser.js","sourceRoot":"","sources":["../../src/parser/erd-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core schema types for MockMock
|
|
3
|
+
* This is the normalized contract between parser and server
|
|
4
|
+
*/
|
|
5
|
+
export interface MockEndpoint {
|
|
6
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
|
7
|
+
path: string;
|
|
8
|
+
request?: unknown;
|
|
9
|
+
response: unknown;
|
|
10
|
+
status?: number;
|
|
11
|
+
}
|
|
12
|
+
export type MockSchema = MockEndpoint[];
|
|
13
|
+
//# sourceMappingURL=schema-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-types.d.ts","sourceRoot":"","sources":["../../src/parser/schema-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-types.js","sourceRoot":"","sources":["../../src/parser/schema-types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-generator.d.ts","sourceRoot":"","sources":["../../src/server/data-generator.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CA6B3D"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateFakeData = generateFakeData;
|
|
4
|
+
const faker_1 = require("@faker-js/faker");
|
|
5
|
+
/**
|
|
6
|
+
* Generates fake data based on a template object
|
|
7
|
+
* Replaces string/number/boolean values with realistic fake data
|
|
8
|
+
*/
|
|
9
|
+
function generateFakeData(template) {
|
|
10
|
+
if (template === null || template === undefined) {
|
|
11
|
+
return template;
|
|
12
|
+
}
|
|
13
|
+
// Handle arrays
|
|
14
|
+
if (Array.isArray(template)) {
|
|
15
|
+
if (template.length === 0) {
|
|
16
|
+
// Return empty array
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
// Generate 2-3 items based on the first template item
|
|
20
|
+
const itemCount = faker_1.faker.number.int({ min: 2, max: 3 });
|
|
21
|
+
return Array.from({ length: itemCount }, () => generateFakeData(template[0]));
|
|
22
|
+
}
|
|
23
|
+
// Handle objects
|
|
24
|
+
if (typeof template === 'object') {
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const [key, value] of Object.entries(template)) {
|
|
27
|
+
result[key] = generateFakeDataForField(key, value);
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
// Primitive values
|
|
32
|
+
return generatePrimitiveValue(template);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generates fake data for a specific field based on key name and value type
|
|
36
|
+
*/
|
|
37
|
+
function generateFakeDataForField(key, value) {
|
|
38
|
+
const lowerKey = key.toLowerCase();
|
|
39
|
+
// Handle nested objects
|
|
40
|
+
if (value !== null && typeof value === 'object') {
|
|
41
|
+
return generateFakeData(value);
|
|
42
|
+
}
|
|
43
|
+
// String field inference
|
|
44
|
+
if (typeof value === 'string') {
|
|
45
|
+
// IDs
|
|
46
|
+
if (lowerKey.includes('id') && !lowerKey.includes('title')) {
|
|
47
|
+
return faker_1.faker.number.int({ min: 1, max: 1000 });
|
|
48
|
+
}
|
|
49
|
+
// Names and titles
|
|
50
|
+
if (lowerKey.includes('name') || lowerKey.includes('title')) {
|
|
51
|
+
if (lowerKey.includes('company') || lowerKey.includes('store')) {
|
|
52
|
+
return faker_1.faker.company.name();
|
|
53
|
+
}
|
|
54
|
+
if (lowerKey.includes('category')) {
|
|
55
|
+
return faker_1.faker.commerce.department();
|
|
56
|
+
}
|
|
57
|
+
if (lowerKey.includes('product')) {
|
|
58
|
+
return faker_1.faker.commerce.productName();
|
|
59
|
+
}
|
|
60
|
+
return faker_1.faker.lorem.words(2);
|
|
61
|
+
}
|
|
62
|
+
// Email
|
|
63
|
+
if (lowerKey.includes('email')) {
|
|
64
|
+
return faker_1.faker.internet.email();
|
|
65
|
+
}
|
|
66
|
+
// URLs and images
|
|
67
|
+
if (lowerKey.includes('url') || lowerKey.includes('link')) {
|
|
68
|
+
return faker_1.faker.internet.url();
|
|
69
|
+
}
|
|
70
|
+
if (lowerKey.includes('image') || lowerKey.includes('img') || lowerKey.includes('avatar')) {
|
|
71
|
+
return faker_1.faker.image.url();
|
|
72
|
+
}
|
|
73
|
+
// Descriptions
|
|
74
|
+
if (lowerKey.includes('description') || lowerKey.includes('desc')) {
|
|
75
|
+
return faker_1.faker.lorem.sentence();
|
|
76
|
+
}
|
|
77
|
+
// Language codes
|
|
78
|
+
if (lowerKey === 'en' || lowerKey === 'english') {
|
|
79
|
+
return faker_1.faker.lorem.words(2);
|
|
80
|
+
}
|
|
81
|
+
if (lowerKey === 'ar' || lowerKey === 'arabic') {
|
|
82
|
+
return 'Ų¹Ų±ŲØŁ'; // Generic Arabic text
|
|
83
|
+
}
|
|
84
|
+
// Default string
|
|
85
|
+
return faker_1.faker.lorem.word();
|
|
86
|
+
}
|
|
87
|
+
// Number field inference
|
|
88
|
+
if (typeof value === 'number') {
|
|
89
|
+
if (lowerKey.includes('count') || lowerKey.includes('total') || lowerKey.includes('quantity')) {
|
|
90
|
+
return faker_1.faker.number.int({ min: 0, max: 100 });
|
|
91
|
+
}
|
|
92
|
+
if (lowerKey.includes('price') || lowerKey.includes('cost') || lowerKey.includes('amount')) {
|
|
93
|
+
return faker_1.faker.number.float({ min: 0, max: 1000, fractionDigits: 2 });
|
|
94
|
+
}
|
|
95
|
+
if (lowerKey.includes('priority') || lowerKey.includes('order')) {
|
|
96
|
+
return faker_1.faker.number.int({ min: 1, max: 10 });
|
|
97
|
+
}
|
|
98
|
+
if (lowerKey.includes('id')) {
|
|
99
|
+
return faker_1.faker.number.int({ min: 1, max: 1000 });
|
|
100
|
+
}
|
|
101
|
+
return faker_1.faker.number.int({ min: 1, max: 100 });
|
|
102
|
+
}
|
|
103
|
+
// Boolean field inference
|
|
104
|
+
if (typeof value === 'boolean') {
|
|
105
|
+
if (lowerKey.includes('error') || lowerKey.includes('failed')) {
|
|
106
|
+
return false; // Default to success
|
|
107
|
+
}
|
|
108
|
+
return faker_1.faker.datatype.boolean();
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Generates a primitive fake value based on type
|
|
114
|
+
*/
|
|
115
|
+
function generatePrimitiveValue(value) {
|
|
116
|
+
if (typeof value === 'string') {
|
|
117
|
+
return faker_1.faker.lorem.word();
|
|
118
|
+
}
|
|
119
|
+
if (typeof value === 'number') {
|
|
120
|
+
return faker_1.faker.number.int({ min: 1, max: 100 });
|
|
121
|
+
}
|
|
122
|
+
if (typeof value === 'boolean') {
|
|
123
|
+
return faker_1.faker.datatype.boolean();
|
|
124
|
+
}
|
|
125
|
+
return value;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=data-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-generator.js","sourceRoot":"","sources":["../../src/server/data-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-server.d.ts","sourceRoot":"","sources":["../../src/server/mock-server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAgB,MAAM,wBAAwB,CAAC;AAalE,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,IAAI,CAsI/G"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.startMockServer = startMockServer;
|
|
7
|
+
const express_1 = __importDefault(require("express"));
|
|
8
|
+
const cors_1 = __importDefault(require("cors"));
|
|
9
|
+
const axios_1 = __importDefault(require("axios"));
|
|
10
|
+
const readline_1 = __importDefault(require("readline"));
|
|
11
|
+
const data_generator_1 = require("./data-generator");
|
|
12
|
+
let responseDelay = 0;
|
|
13
|
+
function convertPathParams(path) {
|
|
14
|
+
return path.replace(/\{([^}]+)\}/g, ':$1');
|
|
15
|
+
}
|
|
16
|
+
function sleep(ms) {
|
|
17
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
18
|
+
}
|
|
19
|
+
function startMockServer(schema, port, fallbackUrl, delay = 0) {
|
|
20
|
+
responseDelay = delay;
|
|
21
|
+
const app = (0, express_1.default)();
|
|
22
|
+
app.use((0, cors_1.default)());
|
|
23
|
+
app.use(express_1.default.json());
|
|
24
|
+
app.use(express_1.default.urlencoded({ extended: true }));
|
|
25
|
+
console.log('\nš” Registering endpoints:\n');
|
|
26
|
+
for (const endpoint of schema) {
|
|
27
|
+
registerEndpoint(app, endpoint);
|
|
28
|
+
const expressPath = convertPathParams(endpoint.path);
|
|
29
|
+
console.log(` ${endpoint.method.padEnd(6)} ${expressPath}`);
|
|
30
|
+
}
|
|
31
|
+
app.get('/health', (_req, res) => {
|
|
32
|
+
const endpointList = schema.map(ep => {
|
|
33
|
+
const expressPath = convertPathParams(ep.path);
|
|
34
|
+
const examplePath = expressPath.replace(/:([^/]+)/g, (_, param) => `{${param}}`);
|
|
35
|
+
return {
|
|
36
|
+
method: ep.method,
|
|
37
|
+
path: expressPath,
|
|
38
|
+
example: `http://localhost:${port}${examplePath}`,
|
|
39
|
+
description: `Replace {paramName} with actual values`
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
res.json({
|
|
43
|
+
status: 'ok',
|
|
44
|
+
server: 'MockMock',
|
|
45
|
+
totalEndpoints: schema.length,
|
|
46
|
+
baseUrl: `http://localhost:${port}`,
|
|
47
|
+
fallbackUrl: fallbackUrl || null,
|
|
48
|
+
delay: `${responseDelay}ms`,
|
|
49
|
+
endpoints: endpointList
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
app.get('/_config/delay', (_req, res) => {
|
|
53
|
+
res.json({ delay: responseDelay });
|
|
54
|
+
});
|
|
55
|
+
app.put('/_config/delay', (req, res) => {
|
|
56
|
+
const { delay: newDelay } = req.body;
|
|
57
|
+
if (typeof newDelay !== 'number' || newDelay < 0) {
|
|
58
|
+
res.status(400).json({ error: 'delay must be a non-negative number (ms)' });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
responseDelay = newDelay;
|
|
62
|
+
console.log(`ā±ļø Response delay updated to ${responseDelay}ms`);
|
|
63
|
+
res.json({ delay: responseDelay });
|
|
64
|
+
});
|
|
65
|
+
// Fallback proxy / 404 handler
|
|
66
|
+
app.use(async (req, res) => {
|
|
67
|
+
if (fallbackUrl) {
|
|
68
|
+
const baseUrl = fallbackUrl.replace(/\/+$/, '');
|
|
69
|
+
const targetUrl = `${baseUrl}${req.originalUrl}`;
|
|
70
|
+
try {
|
|
71
|
+
console.log(`ā¤µļø Proxying to fallback: ${req.method} ${targetUrl}`);
|
|
72
|
+
const proxyResponse = await (0, axios_1.default)({
|
|
73
|
+
method: req.method,
|
|
74
|
+
url: targetUrl,
|
|
75
|
+
headers: {
|
|
76
|
+
...req.headers,
|
|
77
|
+
host: new URL(baseUrl).host,
|
|
78
|
+
},
|
|
79
|
+
data: ['GET', 'HEAD'].includes(req.method.toUpperCase()) ? undefined : req.body,
|
|
80
|
+
params: req.query,
|
|
81
|
+
validateStatus: () => true,
|
|
82
|
+
responseType: 'arraybuffer',
|
|
83
|
+
});
|
|
84
|
+
res.status(proxyResponse.status);
|
|
85
|
+
const skipHeaders = new Set(['transfer-encoding', 'connection', 'keep-alive']);
|
|
86
|
+
for (const [key, value] of Object.entries(proxyResponse.headers)) {
|
|
87
|
+
if (value && !skipHeaders.has(key.toLowerCase())) {
|
|
88
|
+
res.setHeader(key, value);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
res.send(Buffer.from(proxyResponse.data));
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
95
|
+
console.error(`ā Fallback proxy error: ${message}`);
|
|
96
|
+
res.status(502).json({
|
|
97
|
+
error: 'Fallback server unavailable',
|
|
98
|
+
target: targetUrl,
|
|
99
|
+
details: message,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
res.status(404).json({ error: 'Endpoint not found' });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const server = app.listen(port, () => {
|
|
108
|
+
console.log('\nā
Mock server started successfully!\n');
|
|
109
|
+
console.log(`š Base URL: http://localhost:${port}`);
|
|
110
|
+
console.log(`š Total endpoints: ${schema.length}`);
|
|
111
|
+
console.log(`ā±ļø Response delay: ${responseDelay}ms`);
|
|
112
|
+
if (fallbackUrl) {
|
|
113
|
+
console.log(`š Fallback: ${fallbackUrl}`);
|
|
114
|
+
}
|
|
115
|
+
console.log(`š Health check: http://localhost:${port}/health\n`);
|
|
116
|
+
console.log('Type "delay <ms>" to change response delay (e.g. "delay 500")');
|
|
117
|
+
console.log('Press Ctrl+C to stop the server\n');
|
|
118
|
+
setupStdinDelayControl();
|
|
119
|
+
});
|
|
120
|
+
// Graceful shutdown on Ctrl+C (SIGINT) or SIGTERM
|
|
121
|
+
const shutdown = () => {
|
|
122
|
+
console.log('\n\nš Shutting down mock server...');
|
|
123
|
+
server.close(() => {
|
|
124
|
+
console.log('ā
Server stopped gracefully\n');
|
|
125
|
+
process.exit(0);
|
|
126
|
+
});
|
|
127
|
+
// Force close after 5 seconds if graceful shutdown fails
|
|
128
|
+
setTimeout(() => {
|
|
129
|
+
console.error('ā ļø Forced shutdown after timeout');
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}, 5000);
|
|
132
|
+
};
|
|
133
|
+
process.on('SIGINT', shutdown);
|
|
134
|
+
process.on('SIGTERM', shutdown);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Registers a single endpoint with Express
|
|
138
|
+
*/
|
|
139
|
+
function registerEndpoint(app, endpoint) {
|
|
140
|
+
const { method, path, response, status = 200 } = endpoint;
|
|
141
|
+
const expressPath = convertPathParams(path);
|
|
142
|
+
const handler = async (_req, res) => {
|
|
143
|
+
if (responseDelay > 0) {
|
|
144
|
+
await sleep(responseDelay);
|
|
145
|
+
}
|
|
146
|
+
const fakeData = (0, data_generator_1.generateFakeData)(response);
|
|
147
|
+
res.status(status).json(fakeData);
|
|
148
|
+
};
|
|
149
|
+
switch (method) {
|
|
150
|
+
case 'GET':
|
|
151
|
+
app.get(expressPath, handler);
|
|
152
|
+
break;
|
|
153
|
+
case 'POST':
|
|
154
|
+
app.post(expressPath, handler);
|
|
155
|
+
break;
|
|
156
|
+
case 'PUT':
|
|
157
|
+
app.put(expressPath, handler);
|
|
158
|
+
break;
|
|
159
|
+
case 'PATCH':
|
|
160
|
+
app.patch(expressPath, handler);
|
|
161
|
+
break;
|
|
162
|
+
case 'DELETE':
|
|
163
|
+
app.delete(expressPath, handler);
|
|
164
|
+
break;
|
|
165
|
+
default:
|
|
166
|
+
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function setupStdinDelayControl() {
|
|
170
|
+
const rl = readline_1.default.createInterface({ input: process.stdin });
|
|
171
|
+
rl.on('line', (line) => {
|
|
172
|
+
const trimmed = line.trim().toLowerCase();
|
|
173
|
+
const match = trimmed.match(/^delay\s+(\d+)$/);
|
|
174
|
+
if (match) {
|
|
175
|
+
responseDelay = parseInt(match[1], 10);
|
|
176
|
+
console.log(`ā±ļø Response delay updated to ${responseDelay}ms`);
|
|
177
|
+
}
|
|
178
|
+
else if (trimmed === 'delay') {
|
|
179
|
+
console.log(`ā±ļø Current response delay: ${responseDelay}ms`);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
console.log('Unknown command. Use "delay <ms>" to set delay or "delay" to check current value.');
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=mock-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-server.js","sourceRoot":"","sources":["../../src/server/mock-server.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mhmdalimansour/mock-mock",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Production-grade CLI tool to generate mock servers from Confluence API documentation",
|
|
5
|
+
"main": "dist/cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mock-mock": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
".env.example"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "ts-node src/cli.ts",
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"start": "node dist/cli.js",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=16"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mock",
|
|
25
|
+
"api",
|
|
26
|
+
"confluence",
|
|
27
|
+
"cli"
|
|
28
|
+
],
|
|
29
|
+
"author": "",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@faker-js/faker": "^8.4.1",
|
|
33
|
+
"axios": "^1.6.7",
|
|
34
|
+
"cheerio": "^1.0.0-rc.12",
|
|
35
|
+
"commander": "^12.0.0",
|
|
36
|
+
"cors": "^2.8.6",
|
|
37
|
+
"dotenv": "^17.2.4",
|
|
38
|
+
"express": "^4.18.2"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/cors": "^2.8.19",
|
|
42
|
+
"@types/express": "^4.17.21",
|
|
43
|
+
"@types/node": "^20.11.19",
|
|
44
|
+
"ts-node": "^10.9.2",
|
|
45
|
+
"typescript": "^5.3.3"
|
|
46
|
+
}
|
|
47
|
+
}
|