Skip to content

Commit b2c1a71

Browse files
committed
refactor(nx-plugin): enhance plugin handling and directory management
- Replace direct mkdir calls with makeDir utility for consistent directory creation. - Update plugin handling in client generation to support additional plugins. - Modify tests and schemas to reflect changes in plugin structure and options. - Improve error handling and logging in updateApi executor. - Add formatting functionality for generated files and update README for clarity.
1 parent 4e9e5d0 commit b2c1a71

File tree

13 files changed

+198
-301
lines changed

13 files changed

+198
-301
lines changed

packages/nx-plugin/src/executors/update-api/schema.d.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { Plugin } from '../../utils';
2+
13
export interface UpdateApiExecutorSchema {
24
client: string;
35
directory: string;
@@ -6,7 +8,7 @@ export interface UpdateApiExecutorSchema {
68
*/
79
force?: boolean;
810
name: string;
9-
plugins: string[];
11+
plugins: Plugin[];
1012
scope: string;
1113
spec: string;
1214
/**

packages/nx-plugin/src/executors/update-api/updateApi.spec.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { existsSync } from 'node:fs';
2-
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
2+
import { readFile, rm, writeFile } from 'node:fs/promises';
33
import { join } from 'node:path';
44

55
import type { initConfigs } from '@hey-api/openapi-ts/internal';
@@ -9,6 +9,7 @@ import { afterAll, describe, expect, it, vi } from 'vitest';
99

1010
import generator from '../../generators/openapi-client/openapiClient';
1111
import { getGeneratorOptions, TestOptions } from '../../test-utils';
12+
import { makeDir } from '../../utils';
1213
import { CONSTANTS } from '../../vars';
1314
import type { UpdateApiExecutorSchema } from './schema';
1415
import executor from './updateApi';
@@ -55,7 +56,7 @@ const getExecutorOptions = async (name: string) => {
5556
// Create the API directory and spec file
5657
const absoluteApiDir = join(process.cwd(), apiDir);
5758
if (!existsSync(absoluteApiDir)) {
58-
await mkdir(absoluteApiDir, { recursive: true });
59+
await makeDir(absoluteApiDir);
5960
}
6061
const specPath = join(apiDir, testSpecName);
6162
const absoluteSpecPath = join(process.cwd(), specPath);
@@ -140,9 +141,7 @@ describe('UpdateApi Executor', () => {
140141
'api',
141142
'invalid.yaml',
142143
);
143-
await mkdir(join(process.cwd(), options.directory, options.name, 'api'), {
144-
recursive: true,
145-
});
144+
await makeDir(join(process.cwd(), options.directory, options.name, 'api'));
146145
await writeFile(invalidSpecPath, 'invalid: yaml');
147146
options.spec = invalidSpecPath;
148147

@@ -197,16 +196,13 @@ describe('UpdateApi Executor', () => {
197196
'new-spec.yaml',
198197
);
199198
const existingSpec = await readFile(existingSpecPath, 'utf-8');
200-
await mkdir(
199+
await makeDir(
201200
join(
202201
process.cwd(),
203202
options.directory,
204203
options.name,
205204
CONSTANTS.SPEC_DIR_NAME,
206205
),
207-
{
208-
recursive: true,
209-
},
210206
);
211207
await writeFile(newSpecPath, existingSpec);
212208
options.spec = newSpecPath;
@@ -257,9 +253,7 @@ paths:
257253
`;
258254
await generator(tree, generatorOptions);
259255

260-
await mkdir(absoluteApiDir, {
261-
recursive: true,
262-
});
256+
await makeDir(absoluteApiDir);
263257
if (existsSync(v2SpecPath)) {
264258
logger.debug(`Spec file already exists: ${v2SpecPath}`);
265259
await writeFile(v2SpecPath, v2Spec);

packages/nx-plugin/src/executors/update-api/updateApi.ts

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { existsSync, writeFileSync } from 'node:fs';
2-
import { cp, mkdir, readFile, rm } from 'node:fs/promises';
2+
import { cp, readFile, rm } from 'node:fs/promises';
33
import { join } from 'node:path';
44

55
import type { PromiseExecutor } from '@nx/devkit';
6-
import { logger } from '@nx/devkit';
6+
import { logger, names } from '@nx/devkit';
7+
import { format } from 'prettier';
78

89
import {
910
bundleAndDereferenceSpecFile,
1011
compareSpecs,
12+
formatFiles,
1113
generateClientCode,
14+
makeDir,
1215
} from '../../utils';
1316
import { CONSTANTS } from '../../vars';
1417
import type { UpdateApiExecutorSchema } from './schema';
@@ -40,7 +43,7 @@ async function setup({
4043

4144
if (!existsSync(absoluteTempApiFolder)) {
4245
logger.debug(`Creating executor temp api folder: ${absoluteTempApiFolder}`);
43-
await mkdir(absoluteTempApiFolder, { recursive: true });
46+
await makeDir(absoluteTempApiFolder);
4447
logger.debug(`Created temp API folder: ${absoluteTempApiFolder}`);
4548
} else {
4649
logger.debug(`Temp API folder already exists: ${absoluteTempApiFolder}`);
@@ -129,7 +132,11 @@ const runExecutor: PromiseExecutor<UpdateApiExecutorSchema> = async (
129132
// eslint-disable-next-line @typescript-eslint/no-unused-vars
130133
_context,
131134
) => {
132-
const tempFolder = options.tempFolder ?? CONSTANTS.TMP_DIR_NAME;
135+
const tempFolder =
136+
// use the provided temp folder or use the default temp folder and append the project name to it
137+
// we append the project name to the temp folder to avoid conflicts between different projects using the same temp folder
138+
options.tempFolder ??
139+
join(CONSTANTS.TMP_DIR_NAME, names(options.name).fileName);
133140
const absoluteTempFolder = join(process.cwd(), tempFolder);
134141
const force = options.force ?? false;
135142

@@ -160,6 +167,7 @@ const runExecutor: PromiseExecutor<UpdateApiExecutorSchema> = async (
160167
logger.info('No changes detected in the API spec.');
161168
if (!force) {
162169
logger.info('Force flag is false. Skipping client code generation.');
170+
await cleanup(absoluteTempFolder);
163171
return { success: true };
164172
} else {
165173
logger.info('Force flag is true. Generating new client code...');
@@ -175,7 +183,7 @@ const runExecutor: PromiseExecutor<UpdateApiExecutorSchema> = async (
175183
const absoluteGeneratedTempDir = join(process.cwd(), generatedTempDir);
176184

177185
if (!existsSync(absoluteGeneratedTempDir)) {
178-
await mkdir(absoluteGeneratedTempDir);
186+
await makeDir(absoluteGeneratedTempDir);
179187
}
180188

181189
// Generate new client code
@@ -200,7 +208,10 @@ const runExecutor: PromiseExecutor<UpdateApiExecutorSchema> = async (
200208
} else {
201209
logger.debug('No existing spec file found. Creating...');
202210
}
203-
writeFileSync(absoluteExistingSpecPath, newSpecString);
211+
const formattedSpec = await format(newSpecString, {
212+
parser: 'yaml',
213+
});
214+
writeFileSync(absoluteExistingSpecPath, formattedSpec);
204215
logger.debug(`Spec file updated successfully`);
205216
} else {
206217
logger.error(
@@ -224,34 +235,50 @@ const runExecutor: PromiseExecutor<UpdateApiExecutorSchema> = async (
224235

225236
// Remove old generated directory if it exists
226237
if (existsSync(absoluteProjectGeneratedDir)) {
238+
logger.debug(
239+
`Removing old generated directory: ${absoluteProjectGeneratedDir}`,
240+
);
227241
await rm(absoluteProjectGeneratedDir, {
228242
force: true,
229243
recursive: true,
230244
});
245+
logger.debug(
246+
`Old generated directory removed successfully: ${absoluteProjectGeneratedDir}`,
247+
);
231248
}
232249

233250
// Copy new generated directory
234251
await cp(absoluteGeneratedTempDir, absoluteProjectGeneratedDir, {
235252
recursive: true,
236253
});
237254

255+
logger.debug('Formatting generated directory...');
256+
await formatFiles(absoluteProjectGeneratedDir);
257+
238258
logger.info('Successfully updated API client and spec files.');
259+
await cleanup(absoluteTempFolder);
239260
return { success: true };
240261
} catch (error) {
241262
const errorMessage = error instanceof Error ? error.message : String(error);
242-
logger.debug(`Error details: ${errorMessage}.`);
243-
return { success: false };
244-
} finally {
263+
logger.error(`Error details: ${errorMessage}.`);
245264
await cleanup(absoluteTempFolder);
265+
return { error: errorMessage, success: false };
246266
}
247267
};
248268

249-
async function cleanup(tempFolder: string) {
250-
const absoluteTempFolder = join(process.cwd(), tempFolder);
269+
async function cleanup(absoluteTempFolder: string) {
270+
logger.debug('Cleaning up executor environment...');
251271

252272
if (existsSync(absoluteTempFolder)) {
273+
logger.debug(`Removing temp folder: ${absoluteTempFolder}`);
253274
await rm(absoluteTempFolder, { force: true, recursive: true });
275+
logger.debug(`Temp folder removed successfully: ${absoluteTempFolder}`);
276+
} else {
277+
logger.debug(
278+
`Temp folder does not exist: ${absoluteTempFolder}. Skipping cleanup.`,
279+
);
254280
}
281+
logger.debug('Executor cleaned up successfully.');
255282
}
256283

257284
export default runExecutor;

packages/nx-plugin/src/generators/openapi-client/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,4 @@ The generator adds the following dependencies to the created project:
9494
- [x] Support additional client types
9595
- [x] Dogfood the spec bundling and dereferencing
9696
- [ ] Support different test frameworks
97-
- [ ] Add linting generation for
97+
- [ ] Add linting generation

packages/nx-plugin/src/generators/openapi-client/files/openapi-ts.config.ts.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default defineConfig({
66
plugins: [
77
'<%= clientType %>',
88
<% for(let x = 0; x < plugins.length; x++) { %>
9-
'<%= plugins[x] %>'
9+
'<%= plugins[x] %>',
1010
<% } %>
1111
],
1212
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './generated';
2+
export * from './generated/client.gen';

packages/nx-plugin/src/generators/openapi-client/openapiClient.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@
6161
"type": "boolean",
6262
"description": "Whether to make the generated package private, put false if you want to publish the package.",
6363
"default": true
64+
},
65+
"asClass": {
66+
"type": "boolean",
67+
"description": "** not working ** Whether to use the class style for the generated code, defaults to `false`",
68+
"default": false
6469
}
6570
},
6671
"required": ["name", "spec", "scope"]

packages/nx-plugin/src/generators/openapi-client/openapiClient.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { randomUUID } from 'node:crypto';
2-
import { existsSync, mkdirSync, rmSync } from 'node:fs';
2+
import { existsSync, rmSync } from 'node:fs';
33
import { join } from 'node:path';
44

55
import type { initConfigs } from '@hey-api/openapi-ts/internal';
66
import { readJson } from '@nx/devkit';
77
import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest';
88

99
import { getGeneratorOptions } from '../../test-utils';
10-
import { generateClientCode } from '../../utils';
10+
import { generateClientCode, makeDir } from '../../utils';
1111
import generator, { updateTsConfig } from './openapiClient';
1212
import {
1313
generateApi,
@@ -78,7 +78,7 @@ describe('openapi-client generator', () => {
7878
expect(normalized).toEqual({
7979
clientType: '@hey-api/client-fetch',
8080
isPrivate: true,
81-
plugins: [],
81+
plugins: ['@hey-api/typescript', '@hey-api/sdk'],
8282
projectDirectory: `${tempDirectory}/test-api-${uuid}`,
8383
projectName: 'test-api',
8484
projectRoot: `${tempDirectory}/test-api-${uuid}/test-api`,
@@ -107,7 +107,7 @@ describe('openapi-client generator', () => {
107107
expect(normalized).toEqual({
108108
clientType: '@hey-api/client-fetch',
109109
isPrivate: true,
110-
plugins: [],
110+
plugins: ['@hey-api/typescript', '@hey-api/sdk'],
111111
projectDirectory: 'custom-dir',
112112
projectName: 'test-api',
113113
projectRoot: 'custom-dir/test-api',
@@ -330,7 +330,7 @@ describe('openapi-client generator', () => {
330330
// Create necessary directories
331331
const fullProjectRoot = join(process.cwd(), projectRoot);
332332
if (!existsSync(fullProjectRoot)) {
333-
mkdirSync(fullProjectRoot, { recursive: true });
333+
await makeDir(fullProjectRoot);
334334
}
335335

336336
await expect(

0 commit comments

Comments
 (0)