swagger-to-playwright-api-clients 1.0.4

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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +190 -0
  3. package/dist/api.d.ts +27 -0
  4. package/dist/api.d.ts.map +1 -0
  5. package/dist/api.js +127 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.d.ts +6 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +255 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/clients/BaseAPIClient.d.ts +88 -0
  12. package/dist/clients/BaseAPIClient.d.ts.map +1 -0
  13. package/dist/clients/BaseAPIClient.js +199 -0
  14. package/dist/clients/BaseAPIClient.js.map +1 -0
  15. package/dist/config/types.d.ts +72 -0
  16. package/dist/config/types.d.ts.map +1 -0
  17. package/dist/config/types.js +19 -0
  18. package/dist/config/types.js.map +1 -0
  19. package/dist/index.d.ts +17 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +55 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/utils/copyBaseClient.d.ts +8 -0
  24. package/dist/utils/copyBaseClient.d.ts.map +1 -0
  25. package/dist/utils/copyBaseClient.js +354 -0
  26. package/dist/utils/copyBaseClient.js.map +1 -0
  27. package/dist/utils/logger.d.ts +6 -0
  28. package/dist/utils/logger.d.ts.map +1 -0
  29. package/dist/utils/logger.js +57 -0
  30. package/dist/utils/logger.js.map +1 -0
  31. package/dist/utils/swagger/ClientGenerator.d.ts +49 -0
  32. package/dist/utils/swagger/ClientGenerator.d.ts.map +1 -0
  33. package/dist/utils/swagger/ClientGenerator.js +192 -0
  34. package/dist/utils/swagger/ClientGenerator.js.map +1 -0
  35. package/dist/utils/swagger/FileWriter.d.ts +66 -0
  36. package/dist/utils/swagger/FileWriter.d.ts.map +1 -0
  37. package/dist/utils/swagger/FileWriter.js +185 -0
  38. package/dist/utils/swagger/FileWriter.js.map +1 -0
  39. package/dist/utils/swagger/SwaggerGenerator.d.ts +42 -0
  40. package/dist/utils/swagger/SwaggerGenerator.d.ts.map +1 -0
  41. package/dist/utils/swagger/SwaggerGenerator.js +211 -0
  42. package/dist/utils/swagger/SwaggerGenerator.js.map +1 -0
  43. package/dist/utils/swagger/SwaggerParser.d.ts +69 -0
  44. package/dist/utils/swagger/SwaggerParser.d.ts.map +1 -0
  45. package/dist/utils/swagger/SwaggerParser.js +358 -0
  46. package/dist/utils/swagger/SwaggerParser.js.map +1 -0
  47. package/dist/utils/swagger/TypeGenerator.d.ts +49 -0
  48. package/dist/utils/swagger/TypeGenerator.d.ts.map +1 -0
  49. package/dist/utils/swagger/TypeGenerator.js +166 -0
  50. package/dist/utils/swagger/TypeGenerator.js.map +1 -0
  51. package/dist/utils/swagger/index.d.ts +12 -0
  52. package/dist/utils/swagger/index.d.ts.map +1 -0
  53. package/dist/utils/swagger/index.js +38 -0
  54. package/dist/utils/swagger/index.js.map +1 -0
  55. package/dist/utils/swagger/run-generator.d.ts +23 -0
  56. package/dist/utils/swagger/run-generator.d.ts.map +1 -0
  57. package/dist/utils/swagger/run-generator.js +195 -0
  58. package/dist/utils/swagger/run-generator.js.map +1 -0
  59. package/dist/utils/swagger/types.d.ts +142 -0
  60. package/dist/utils/swagger/types.d.ts.map +1 -0
  61. package/dist/utils/swagger/types.js +7 -0
  62. package/dist/utils/swagger/types.js.map +1 -0
  63. package/dist/utils/swagger/utils/naming.d.ts +48 -0
  64. package/dist/utils/swagger/utils/naming.d.ts.map +1 -0
  65. package/dist/utils/swagger/utils/naming.js +109 -0
  66. package/dist/utils/swagger/utils/naming.js.map +1 -0
  67. package/dist/utils/swagger/utils/pathUtils.d.ts +40 -0
  68. package/dist/utils/swagger/utils/pathUtils.d.ts.map +1 -0
  69. package/dist/utils/swagger/utils/pathUtils.js +118 -0
  70. package/dist/utils/swagger/utils/pathUtils.js.map +1 -0
  71. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amar Tanwar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # swagger-to-playwright-api-clients
2
+
3
+ Generate TypeScript API clients from Swagger/OpenAPI specifications for Playwright testing.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install swagger-to-playwright-api-clients
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### 1. Initialize Configuration
14
+
15
+ ```bash
16
+ npx swagger-to-playwright init
17
+ ```
18
+
19
+ This creates a `generator-config.ts` file in your project root.
20
+
21
+ ### 2. Configure Your Sources
22
+
23
+ Edit `generator-config.ts`:
24
+
25
+ ```typescript
26
+ import type { AutomationConfig } from 'swagger-to-playwright-api-clients';
27
+ import * as path from 'path';
28
+
29
+ const config: AutomationConfig = {
30
+ // Output directory for generated clients
31
+ outputDir: path.join(__dirname, 'src/clients'),
32
+
33
+ // Clean output before generation
34
+ cleanOutput: true,
35
+
36
+ // Process sources in parallel
37
+ parallel: false,
38
+
39
+ // BaseAPIClient import path (optional - defaults to '../../../BaseAPIClient')
40
+ // Generated clients are at: outputDir/generatedClients/ServiceName/FolderName/
41
+ // The library will auto-copy BaseAPIClient.ts to your outputDir
42
+ // baseClientPath: '../../../BaseAPIClient',
43
+
44
+ // Swagger/OpenAPI sources
45
+ sources: [
46
+ {
47
+ type: 'file',
48
+ source: './swagger/api.json',
49
+ serviceName: 'MyService',
50
+ },
51
+ {
52
+ type: 'url',
53
+ source: 'https://api.example.com/swagger.json',
54
+ serviceName: 'ExampleService',
55
+ },
56
+ ],
57
+ };
58
+
59
+ export default config;
60
+ ```
61
+
62
+ ### 3. Generate Clients
63
+
64
+ ```bash
65
+ npx swagger-to-playwright
66
+ ```
67
+
68
+ Or using npm script:
69
+
70
+ ```bash
71
+ npm run generate
72
+ ```
73
+
74
+ ## CLI Usage
75
+
76
+ ```bash
77
+ # Generate from config file
78
+ npx swagger-to-playwright
79
+
80
+ # Generate from specific config
81
+ npx swagger-to-playwright --config ./my-config.ts
82
+
83
+ # Generate from single file
84
+ npx swagger-to-playwright --file ./swagger.json --output ./src/clients
85
+
86
+ # Generate from URL
87
+ npx swagger-to-playwright --url https://api.example.com/swagger.json --output ./src/clients
88
+
89
+ # Show help
90
+ npx swagger-to-playwright --help
91
+
92
+ # Initialize a new config file
93
+ npx swagger-to-playwright init
94
+ ```
95
+
96
+ ## Programmatic Usage
97
+
98
+ ```typescript
99
+ import { generate, generateFromConfig } from 'swagger-to-playwright-api-clients';
100
+
101
+ // Generate from a single source
102
+ const result = await generate({
103
+ source: './swagger.json',
104
+ type: 'file',
105
+ outputDir: './src/clients',
106
+ serviceName: 'MyService',
107
+ });
108
+
109
+ // Generate from config object
110
+ const results = await generateFromConfig({
111
+ outputDir: './src/clients',
112
+ sources: [{ type: 'file', source: './swagger.json', serviceName: 'MyService' }],
113
+ });
114
+ ```
115
+
116
+ ## Using Generated Clients
117
+
118
+ ```typescript
119
+ import { test, expect } from '@playwright/test';
120
+ import { BaseAPIClient } from './clients/BaseAPIClient';
121
+ import { MyServiceActivityClient } from './clients/generatedClients/MyService/Activity/MyServiceActivityClient';
122
+
123
+ test('API test example', async () => {
124
+ const baseClient = new BaseAPIClient('https://api.example.com', {
125
+ 'Content-Type': 'application/json',
126
+ Authorization: 'Bearer your-token',
127
+ });
128
+ await baseClient.init();
129
+
130
+ const activityClient = new MyServiceActivityClient(baseClient);
131
+
132
+ const { body, status } = await activityClient.getActivities();
133
+
134
+ expect(status).toBe(200);
135
+ expect(body.activities).toBeDefined();
136
+
137
+ await baseClient.dispose();
138
+ });
139
+ ```
140
+
141
+ ## Configuration Options
142
+
143
+ | Option | Type | Default | Description |
144
+ | ---------------- | --------------------- | -------------------------- | ------------------------------------ |
145
+ | `outputDir` | string | required | Output directory for generated files |
146
+ | `sources` | SwaggerSourceConfig[] | required | Array of swagger sources |
147
+ | `baseClientPath` | string | `'../../../BaseAPIClient'` | Custom path to BaseAPIClient |
148
+ | `copyBaseClient` | boolean | `true` | Copy BaseAPIClient to output |
149
+ | `cleanOutput` | boolean | `true` | Clean output before generation |
150
+ | `parallel` | boolean | `false` | Process sources in parallel |
151
+
152
+ ### Source Configuration
153
+
154
+ | Option | Type | Description |
155
+ | ------------- | ------------------- | ----------------------------- |
156
+ | `type` | `'file'` \| `'url'` | Source type |
157
+ | `source` | string | Path or URL to swagger JSON |
158
+ | `serviceName` | string | Override service name |
159
+ | `outputDir` | string | Custom output for this source |
160
+ | `skip` | boolean | Skip this source |
161
+
162
+ ## Generated Structure
163
+
164
+ ```
165
+ src/clients/
166
+ ├── BaseAPIClient.ts # Base client (auto-copied)
167
+ └── generatedClients/
168
+ └── MyService/
169
+ ├── Activity/
170
+ │ ├── types.ts
171
+ │ └── MyServiceActivityClient.ts
172
+ ├── Users/
173
+ │ ├── types.ts
174
+ │ └── MyServiceUsersClient.ts
175
+ └── Root/
176
+ ├── types.ts
177
+ └── MyServiceRootClient.ts
178
+ ```
179
+
180
+ ## Peer Dependencies
181
+
182
+ This library requires Playwright to be installed in your project:
183
+
184
+ ```bash
185
+ npm install @playwright/test playwright
186
+ ```
187
+
188
+ ## License
189
+
190
+ MIT
package/dist/api.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Programmatic API for the generator
3
+ * Allows users to use the generator as a library
4
+ */
5
+ import { AutomationConfig } from './config/types';
6
+ import { RunResults } from './utils/swagger/run-generator';
7
+ import { GeneratorResult } from './utils/swagger/SwaggerGenerator';
8
+ /**
9
+ * Generate API clients from a single swagger source
10
+ */
11
+ export declare function generate(options: {
12
+ source: string;
13
+ type: 'file' | 'url';
14
+ outputDir: string;
15
+ serviceName?: string;
16
+ baseClientPath?: string;
17
+ copyBaseClient?: boolean;
18
+ }): Promise<GeneratorResult>;
19
+ /**
20
+ * Generate API clients from a configuration object
21
+ */
22
+ export declare function generateFromConfig(config: AutomationConfig): Promise<RunResults>;
23
+ /**
24
+ * Load configuration from a file path
25
+ */
26
+ export declare function loadConfig(configPath: string): Promise<AutomationConfig>;
27
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAA2C,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAgB,UAAU,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAoB,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAIrF;;GAEG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,eAAe,CAAC,CA8B3B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CActF;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuC9E"}
package/dist/api.js ADDED
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ /**
3
+ * Programmatic API for the generator
4
+ * Allows users to use the generator as a library
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.generate = generate;
41
+ exports.generateFromConfig = generateFromConfig;
42
+ exports.loadConfig = loadConfig;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const types_1 = require("./config/types");
46
+ const run_generator_1 = require("./utils/swagger/run-generator");
47
+ const SwaggerGenerator_1 = require("./utils/swagger/SwaggerGenerator");
48
+ const copyBaseClient_1 = require("./utils/copyBaseClient");
49
+ /**
50
+ * Generate API clients from a single swagger source
51
+ */
52
+ async function generate(options) {
53
+ const { source, type, outputDir, serviceName, baseClientPath, copyBaseClient: shouldCopyBaseClient = true, } = options;
54
+ // Copy BaseAPIClient if needed
55
+ if (shouldCopyBaseClient && !baseClientPath) {
56
+ await (0, copyBaseClient_1.copyBaseClient)(outputDir);
57
+ }
58
+ const generatedClientsDir = path.join(outputDir, 'generatedClients');
59
+ await fs.promises.mkdir(generatedClientsDir, { recursive: true });
60
+ const generator = new SwaggerGenerator_1.SwaggerGenerator({
61
+ outputDir: generatedClientsDir,
62
+ serviceName,
63
+ baseClientPath: baseClientPath || types_1.DEFAULT_BASE_CLIENT_PATH,
64
+ });
65
+ if (type === 'file') {
66
+ const filePath = path.isAbsolute(source) ? source : path.join(process.cwd(), source);
67
+ return generator.generateFromFile(filePath);
68
+ }
69
+ else {
70
+ return generator.generateFromUrl(source);
71
+ }
72
+ }
73
+ /**
74
+ * Generate API clients from a configuration object
75
+ */
76
+ async function generateFromConfig(config) {
77
+ const mergedConfig = {
78
+ ...types_1.defaultConfig,
79
+ ...config,
80
+ };
81
+ // Copy BaseAPIClient if needed (when no custom baseClientPath is provided)
82
+ if (mergedConfig.copyBaseClient !== false && !config.baseClientPath) {
83
+ await (0, copyBaseClient_1.copyBaseClient)(mergedConfig.outputDir);
84
+ // Use the default base client path relative to generated clients
85
+ mergedConfig.baseClientPath = types_1.DEFAULT_BASE_CLIENT_PATH;
86
+ }
87
+ return (0, run_generator_1.runGenerator)(mergedConfig);
88
+ }
89
+ /**
90
+ * Load configuration from a file path
91
+ */
92
+ async function loadConfig(configPath) {
93
+ const absolutePath = path.isAbsolute(configPath)
94
+ ? configPath
95
+ : path.join(process.cwd(), configPath);
96
+ if (!fs.existsSync(absolutePath)) {
97
+ throw new Error(`Configuration file not found: ${absolutePath}`);
98
+ }
99
+ // For TypeScript files, we need to use dynamic import or require with ts-node
100
+ const ext = path.extname(absolutePath);
101
+ if (ext === '.ts') {
102
+ // Try to load TypeScript config
103
+ try {
104
+ // Check if ts-node is available
105
+ require.resolve('ts-node');
106
+ require('ts-node').register({
107
+ transpileOnly: true,
108
+ compilerOptions: {
109
+ module: 'commonjs',
110
+ },
111
+ });
112
+ }
113
+ catch {
114
+ // ts-node not available, try to load compiled JS version
115
+ const jsPath = absolutePath.replace(/\.ts$/, '.js');
116
+ if (fs.existsSync(jsPath)) {
117
+ const config = require(jsPath);
118
+ return config.default || config;
119
+ }
120
+ throw new Error('ts-node is not installed. Install it with: npm install -D ts-node\n' +
121
+ 'Or compile your config to JavaScript first.');
122
+ }
123
+ }
124
+ const config = require(absolutePath);
125
+ return config.default || config;
126
+ }
127
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entry point for swagger-to-playwright-api-clients
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG"}
package/dist/cli.js ADDED
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * CLI entry point for swagger-to-playwright-api-clients
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const api_1 = require("./api");
43
+ const DEFAULT_CONFIG_NAMES = [
44
+ 'generator-config.ts',
45
+ 'generator-config.js',
46
+ 'swagger-generator.config.ts',
47
+ 'swagger-generator.config.js',
48
+ ];
49
+ async function findConfigFile() {
50
+ const cwd = process.cwd();
51
+ for (const name of DEFAULT_CONFIG_NAMES) {
52
+ const configPath = path.join(cwd, name);
53
+ if (fs.existsSync(configPath)) {
54
+ return configPath;
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+ function printHelp() {
60
+ console.log(`
61
+ swagger-to-playwright-api-clients - Generate TypeScript API clients from Swagger/OpenAPI
62
+
63
+ Usage:
64
+ swagger-to-playwright [command] [options]
65
+
66
+ Commands:
67
+ generate Generate API clients from config file (default)
68
+ init Create a sample configuration file
69
+
70
+ Options:
71
+ --config <path> Path to config file (default: generator-config.ts)
72
+ --file <path> Generate from a single swagger file
73
+ --url <url> Generate from a single swagger URL
74
+ --output <dir> Output directory (default: ./src/clients)
75
+ --name <name> Service name override
76
+ --help, -h Show this help message
77
+ --version, -v Show version
78
+
79
+ Examples:
80
+ # Generate from config file in project root
81
+ swagger-to-playwright
82
+
83
+ # Generate from specific config file
84
+ swagger-to-playwright --config ./my-config.ts
85
+
86
+ # Generate from a single file
87
+ swagger-to-playwright --file ./swagger.json --output ./src/clients
88
+
89
+ # Generate from URL
90
+ swagger-to-playwright --url https://api.example.com/swagger.json --output ./src/clients
91
+
92
+ # Initialize a new config file
93
+ swagger-to-playwright init
94
+ `);
95
+ }
96
+ function printVersion() {
97
+ try {
98
+ const packageJsonPath = path.join(__dirname, '..', 'package.json');
99
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
100
+ console.log(`swagger-to-playwright-api-clients v${packageJson.version}`);
101
+ }
102
+ catch {
103
+ console.log('swagger-to-playwright-api-clients v1.0.0');
104
+ }
105
+ }
106
+ async function initConfig() {
107
+ const configPath = path.join(process.cwd(), 'generator-config.ts');
108
+ if (fs.existsSync(configPath)) {
109
+ console.error('Error: generator-config.ts already exists');
110
+ process.exit(1);
111
+ }
112
+ const configContent = `/**
113
+ * Swagger to Playwright API Client Generator Configuration
114
+ *
115
+ * Customize this file to specify your Swagger/OpenAPI sources.
116
+ * Run with: npx swagger-to-playwright
117
+ */
118
+
119
+ import type { AutomationConfig } from 'swagger-to-playwright-api-clients';
120
+ import * as path from 'path';
121
+
122
+ const config: AutomationConfig = {
123
+ // Output directory for generated clients
124
+ outputDir: path.join(__dirname, 'src/clients'),
125
+
126
+ // Clean output before generation
127
+ cleanOutput: true,
128
+
129
+ // Process sources in parallel
130
+ parallel: false,
131
+
132
+ // BaseAPIClient import path (relative to generated client files)
133
+ // Generated clients are at: outputDir/generatedClients/ServiceName/FolderName/
134
+ // Default: '../../../BaseAPIClient' - library will copy BaseAPIClient.ts to outputDir
135
+ // baseClientPath: '../../../BaseAPIClient',
136
+
137
+ // Swagger/OpenAPI sources
138
+ sources: [
139
+ // Example: Local file
140
+ // {
141
+ // type: 'file',
142
+ // source: './swagger/api.json',
143
+ // serviceName: 'MyService',
144
+ // },
145
+
146
+ // Example: Remote URL
147
+ // {
148
+ // type: 'url',
149
+ // source: 'https://api.example.com/swagger.json',
150
+ // serviceName: 'ExampleService',
151
+ // },
152
+ ],
153
+ };
154
+
155
+ export default config;
156
+ `;
157
+ await fs.promises.writeFile(configPath, configContent, 'utf-8');
158
+ console.log('Created generator-config.ts');
159
+ console.log('\nNext steps:');
160
+ console.log('1. Edit generator-config.ts to add your Swagger sources');
161
+ console.log('2. Run: npx swagger-to-playwright');
162
+ }
163
+ async function main() {
164
+ const args = process.argv.slice(2);
165
+ // Handle help
166
+ if (args.includes('--help') || args.includes('-h')) {
167
+ printHelp();
168
+ return;
169
+ }
170
+ // Handle version
171
+ if (args.includes('--version') || args.includes('-v')) {
172
+ printVersion();
173
+ return;
174
+ }
175
+ // Handle init command
176
+ if (args[0] === 'init') {
177
+ await initConfig();
178
+ return;
179
+ }
180
+ // Handle single file/url mode
181
+ const fileIndex = args.indexOf('--file');
182
+ const urlIndex = args.indexOf('--url');
183
+ const outputIndex = args.indexOf('--output');
184
+ const nameIndex = args.indexOf('--name');
185
+ if (fileIndex !== -1 || urlIndex !== -1) {
186
+ const outputDir = outputIndex !== -1 ? args[outputIndex + 1] : './src/clients';
187
+ const serviceName = nameIndex !== -1 ? args[nameIndex + 1] : undefined;
188
+ const type = fileIndex !== -1 ? 'file' : 'url';
189
+ const source = fileIndex !== -1 ? args[fileIndex + 1] : args[urlIndex + 1];
190
+ if (!source) {
191
+ console.error(`Error: Missing ${type} path`);
192
+ process.exit(1);
193
+ }
194
+ console.log(`Generating from ${type}: ${source}`);
195
+ const result = await (0, api_1.generate)({
196
+ source,
197
+ type,
198
+ outputDir: path.resolve(outputDir),
199
+ serviceName,
200
+ });
201
+ if (result.success) {
202
+ console.log(`\n✓ Successfully generated ${result.filesWritten.length} files`);
203
+ console.log(`\nFolder Structure:\n${result.folderStructure}`);
204
+ }
205
+ else {
206
+ console.error(`\n✗ Generation failed: ${result.errors.join(', ')}`);
207
+ process.exit(1);
208
+ }
209
+ return;
210
+ }
211
+ // Handle config-based generation
212
+ const configIndex = args.indexOf('--config');
213
+ let configPath = null;
214
+ if (configIndex !== -1) {
215
+ configPath = args[configIndex + 1];
216
+ if (!configPath) {
217
+ console.error('Error: Missing config file path');
218
+ process.exit(1);
219
+ }
220
+ }
221
+ else {
222
+ configPath = await findConfigFile();
223
+ }
224
+ if (!configPath) {
225
+ console.error('Error: No configuration file found.');
226
+ console.error('Create a generator-config.ts file or use --config to specify one.');
227
+ console.error('\nRun "swagger-to-playwright init" to create a sample config file.');
228
+ process.exit(1);
229
+ }
230
+ console.log(`Using config: ${configPath}`);
231
+ try {
232
+ const config = await (0, api_1.loadConfig)(configPath);
233
+ const results = await (0, api_1.generateFromConfig)(config);
234
+ console.log('\n' + '='.repeat(60));
235
+ console.log('Generation Complete');
236
+ console.log('='.repeat(60));
237
+ console.log(`Total Sources: ${results.totalSources}`);
238
+ console.log(`Successful: ${results.successful}`);
239
+ console.log(`Failed: ${results.failed}`);
240
+ console.log(`Skipped: ${results.skipped}`);
241
+ if (results.failed > 0) {
242
+ process.exit(1);
243
+ }
244
+ }
245
+ catch (error) {
246
+ const message = error instanceof Error ? error.message : String(error);
247
+ console.error(`Error: ${message}`);
248
+ process.exit(1);
249
+ }
250
+ }
251
+ main().catch((error) => {
252
+ console.error('Fatal error:', error);
253
+ process.exit(1);
254
+ });
255
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}