Skip to content

Commit

Permalink
fix: default specs filename on sdk generation
Browse files Browse the repository at this point in the history
  • Loading branch information
mrednic-1A committed May 24, 2024
1 parent 5aaf11a commit 58dd912
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 20 deletions.
14 changes: 10 additions & 4 deletions packages/@ama-sdk/core/cli/update-spec-from-npm.cts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@ import { extname, join } from 'node:path';
import { copyFile, readFile } from 'node:fs/promises';
import type { PackageJson } from 'type-fest';
import type { OpenApiToolsConfiguration } from '../src/fwk/open-api-tools-configuration';
import { DEFAULT_SPEC_FILENAME_IN_NPM_MODULE, LOCAL_SPEC_FILENAME, SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION, SPEC_YML_EXTENSION } from '../src/utils/generators';

const argv = minimist(process.argv.slice(2));
const packageName = argv._[0];
const { help, output, 'package-path': packagePath, quiet } = argv;
const openApiConfigDefaultPath = './openapitools.json';
const supportedExtensions = ['json', 'yaml', 'yml'];
const noop = () => undefined;
const logger = quiet ? {error: noop, warn: noop, log: noop, info: noop, debug: noop} : console;

const supportedExtensions = [SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION, SPEC_YML_EXTENSION];

if (help) {
// eslint-disable-next-line no-console
console.log(`This script can be used to update your local spec file from a given locally installed npm package.
Usage: amasdk-update-spec-from-npm <package-name> [--package-path] [--output] [--quiet]
Expand All @@ -43,7 +46,7 @@ void (async () => {
const packageJsonPath = appRequire.resolve(`${packageName}/package.json`);
if (!packagePath) {
const packageJson = JSON.parse(await readFile(packageJsonPath, {encoding: 'utf8'})) as PackageJson;
const exportMatcher = new RegExp(`openapi\\.(?:${supportedExtensions.join('|')})$`);
const exportMatcher = new RegExp(`${DEFAULT_SPEC_FILENAME_IN_NPM_MODULE}\\.(?:${supportedExtensions.join('|')})$`);
const matchingExport = packageJson.exports && Object.keys(packageJson.exports).find((exportPath) => exportMatcher.test(exportPath));
if (matchingExport) {
specSourcePath = appRequire.resolve(`${packageName}/${matchingExport}`);
Expand All @@ -58,8 +61,11 @@ void (async () => {

let specDestinationPath = output;
if (!specDestinationPath) {
const specSourceExtension = extname(specSourcePath);
specDestinationPath = `./openapi${specSourceExtension}`;
let specSourceExtension = extname(specSourcePath);
if (specSourceExtension === `.${SPEC_YAML_EXTENSION}` || specSourceExtension === `.${SPEC_YML_EXTENSION}`) {
specSourceExtension = `.${SPEC_YML_EXTENSION}`;
}
specDestinationPath = `./${LOCAL_SPEC_FILENAME}${specSourceExtension}`;
if (existsSync(openApiConfigDefaultPath)) {
const openApiConfig = JSON.parse(await readFile(openApiConfigDefaultPath, {encoding: 'utf8'})) as OpenApiToolsConfiguration;
const generators = Object.values(openApiConfig['generator-cli']?.generators ?? {});
Expand Down
10 changes: 10 additions & 0 deletions packages/@ama-sdk/core/src/utils/generators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/** Name of the specification file copied locally (without extension) */
export const LOCAL_SPEC_FILENAME = 'openapi';
/** Extension of the Specification file in YAML format */
export const SPEC_YAML_EXTENSION = 'yaml';
/** Extension of the Specification file in YAML format */
export const SPEC_YML_EXTENSION = 'yml';
/** Extension of the Specification file in JSON format */
export const SPEC_JSON_EXTENSION = 'json';
/* Default path of the specification file inside npm module (without extension)*/
export const DEFAULT_SPEC_FILENAME_IN_NPM_MODULE = 'openapi';
1 change: 1 addition & 0 deletions packages/@ama-sdk/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './ie11';
export * from './json-token';
export * from './mime-types';
export * from './generic-api';
export * from './generators';
2 changes: 1 addition & 1 deletion packages/@ama-sdk/create/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ npm create @ama-sdk typescript <project-name> -- --package-manager=yarn [...opti

- `--spec-path`: Path to the swagger/open-api specification used to generate the SDK
- `--spec-package-name`: The npm package name where the spec file can be fetched
- `--spec-package-path`: The path inside the package where to find the spec file
- `--spec-package-path`: The path inside the package where to find the spec file. Defaults to _openapi.[yml|yaml|json]_
- `--spec-package-version`: The version to target for the npm package where the spec file can be fetched
- `--spec-package-registry`: The npm registry where the spec file can be fetched

Expand Down
16 changes: 14 additions & 2 deletions packages/@ama-sdk/create/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* eslint-disable no-console */

import { execSync, spawnSync } from 'node:child_process';
import { dirname, join, parse, relative, resolve } from 'node:path';
import { dirname, extname, join, parse, relative, resolve } from 'node:path';
import * as minimist from 'minimist';

const packageManagerEnv = process.env.npm_config_user_agent?.split('/')[0];
Expand Down Expand Up @@ -64,6 +64,17 @@ if (argv['spec-path'] && argv['spec-package-name']) {
console.error('--spec-path cannot be set with --spec-package-name');
process.exit(-4);
}
/* Default path of the specification file inside npm module */
const DEFAUL_SPEC_FILEPATH_IN_NPM_MODULE = './openapi.yml';
/* Name of the specification file copied locally (without extension) */
const LOCAL_SPEC_FILENAME = 'openapi';
/* The local file (path) which will be created in case of generation using specs from an npm module */
let localFilePathToBeCreated: string | undefined;

if (argv['spec-package-name']) {
const specPathInNpmPackage = argv['spec-package-path'] || DEFAUL_SPEC_FILEPATH_IN_NPM_MODULE;
localFilePathToBeCreated = `./${LOCAL_SPEC_FILENAME}${extname(specPathInNpmPackage)}`;
}

const commonSchematicArgs = [
argv.debug !== undefined ? `--debug=${argv.debug as string}` : '--debug=false', // schematics enable debug mode per default when using schematics with relative path
Expand All @@ -88,7 +99,8 @@ const run = () => {
];
const coreSchematicArgs = [
...commonSchematicArgs,
'--spec-path', argv['spec-package-name'] ? './openapi.yml' : isSpecRelativePath ? relative(resolveTargetDirectory, resolve(process.cwd(), argv['spec-path'])) : argv['spec-path']
'--spec-path',
localFilePathToBeCreated || (isSpecRelativePath ? relative(resolveTargetDirectory, resolve(process.cwd(), argv['spec-path'])) : argv['spec-path'])
];

const runner = process.platform === 'win32' ? `${packageManager}.cmd` : packageManager;
Expand Down
1 change: 1 addition & 0 deletions packages/@ama-sdk/schematics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ The generated package comes with the following script in the package.json:
> [!TIP]
> The `--spec-path` parameter supports YAML and JSON file formats based on the file system path or remote URL.
> `--spec-package-name` parameter can be used as an alternative to `--spec-path` if you want to generate an sdk with specs from an npm package. It comes with optional parameters `--spec-package-registry`, `--spec-package-path` to be able to retrive the npm package and the specs file from it. By default the generator expects the `package.json` file inside the npm module containing the specs, to have an export with the key `./openapi.[yaml|yml|json]` and the value will be the relative path to the spec file inside the package.
If you use `Yarn2+` with PnP, you can modify the following `scripts` in `package.json` to generate the SDK based on specifications in a dependency package:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { OpenApiToolsConfiguration } from '@ama-sdk/core';
import { Tree } from '@angular-devkit/schematics';
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
import * as path from 'node:path';
import { LOCAL_SPEC_FILENAME, SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION } from './index';
import { LOCAL_SPEC_FILENAME, SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION } from '@ama-sdk/core';
import type { JsonObject } from 'type-fest';

const collectionPath = path.join(__dirname, '..', '..', '..', 'collection.json');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { OpenApiToolsConfiguration, OpenApiToolsGenerator, PathObject } from '@ama-sdk/core';
import { LOCAL_SPEC_FILENAME, SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION } from '@ama-sdk/core';
import {
apply,
chain,
Expand Down Expand Up @@ -27,15 +28,6 @@ import { generateOperationFinderFromSingleFile } from './helpers/path-extractor'
const JAVA_OPTIONS = ['specPath', 'specConfigPath', 'globalProperty', 'outputPath'];
const OPEN_API_TOOLS_OPTIONS = ['generatorName', 'output', 'inputSpec', 'config', 'globalProperty'];

// TODO: Change to `open-api` when #1735 is done
/** Name of the specification file copied locally (without extension) */
export const LOCAL_SPEC_FILENAME = 'swagger-spec';
/** Extension of the Specification file in YAML format */
export const SPEC_YAML_EXTENSION = 'yaml';
// TODO: Change to `json` when #1735 is done
/** Extension of the Specification file in JSON format */
export const SPEC_JSON_EXTENSION = 'yaml';

const getRegexpTemplate = (regexp: RegExp) => `new RegExp('${regexp.toString().replace(/\/(.*)\//, '$1').replace(/\\\//g, '/')}')`;

const getPathObjectTemplate = (pathObj: PathObject) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ export class JsonFormatter implements Formatter {

const content = JSON.stringify({
...generatePackageJson(artifactName, spec),
main: path.relative(this.cwd, this.filePath)
main: path.relative(this.cwd, this.filePath),
exports: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'./openapi.json': {
default: path.relative(this.cwd, this.filePath)
}
}
}, null, 2);

const res = await fs.promises.writeFile(path.resolve(this.cwd, 'package.json'), content);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,13 @@ export class SplitYamlFormatter implements Formatter {

const content = JSON.stringify({
...generatePackageJson(artifactName, spec),
main: path.relative(this.cwd, this.filePath)
main: path.relative(this.cwd, this.filePath),
exports: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'./openapi.yaml': {
default: path.relative(this.cwd, this.filePath)
}
}
}, null, 2);

await fs.promises.writeFile(path.resolve(this.cwd, 'package.json'), content);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ export class YamlFormatter implements Formatter {

const content = JSON.stringify({
...generatePackageJson(artifactName, spec),
main: path.relative(this.cwd, this.filePath)
main: path.relative(this.cwd, this.filePath),
exports: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'./openapi.yaml': {
default: path.relative(this.cwd, this.filePath)
}
}
}, null, 2);

await fs.promises.writeFile(path.resolve(this.cwd, 'package.json'), content);
Expand Down

0 comments on commit 58dd912

Please sign in to comment.