Skip to content

Commit

Permalink
[cascading] from release/10.4.0-rc to main (#1856)
Browse files Browse the repository at this point in the history
<!--
{"currentBranch":"release/10.4.0-rc","targetBranch":"main","bypassReviewers":false,"isConflicting":false}
-->

## Cascading from release/10.4.0-rc to main

---

:heavy_exclamation_mark: The pull request is conflicting with the target
branch.
You can fix the issue locally with the following commands:

<details open>
  <summary>Using <b>gh CLI</b></summary>

  ```shell
  gh pr checkout 1856
  git pull --ff origin main
  ```

  and update this Pull Request with

  ```shell
  gh pr push 1856
  ```
</details>

<details>
  <summary>Using <b>git</b> only</summary>

  ```shell
  git fetch origin
  git checkout origin/cascading/10.4.0-rc-main
  git pull --ff origin main
  ```

  and update this Pull Request with

  ```shell
  git push origin HEAD:cascading/10.4.0-rc-main
  ```
</details>

---

<small>This Pull Request has been generated with :heart: by the
[Otter](https://github.com/AmadeusITGroup/otter) cascading tool.</small>
  • Loading branch information
mrednic-1A committed Jun 4, 2024
2 parents a2870b2 + b0ff6d3 commit 3cd2769
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 57 deletions.
23 changes: 15 additions & 8 deletions packages/@ama-sdk/core/cli/update-spec-from-npm.cts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@
import * as minimist from 'minimist';
import { existsSync } from 'node:fs';
import { createRequire } from 'node:module';
import { extname, join } from 'node:path';
import { extname, posix } from 'node:path';
import { copyFile, readFile } from 'node:fs/promises';
import type { PackageJson } from 'type-fest';
import type { OpenApiToolsConfiguration, OpenApiToolsGenerator } from '@ama-sdk/core';
import { LOCAL_SPEC_FILENAME, SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION } from '@ama-sdk/core';

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 SPEC_YML_EXTENSION = 'yml';
const DEFAULT_SPEC_EXPORT_PATH_IN_NPM_MODULE = 'openapi';

const supportedExtensions = [SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION, SPEC_YML_EXTENSION];

if (help) {
// eslint-disable-next-line no-console
Expand All @@ -27,7 +31,7 @@ if (help) {
package-name The full identifier of the npm package (e.g. @my-scope/my-package)
--package-path The relative path inside the npm package where to find the spec file (default: './openapi.yml')
--output The path where the spec file should be copied (default: './openapi.yml')
--output The path where the spec file should be copied (default: './${LOCAL_SPEC_FILENAME}.${SPEC_YAML_EXTENSION}')
--quiet Don't log anything
`);
process.exit(0);
Expand All @@ -40,14 +44,14 @@ if (!packageName) {

void (async () => {
let specSourcePath;
const appRequire = createRequire(join(process.cwd(), 'package.json'));
const appRequire = createRequire(posix.join(process.cwd(), 'package.json'));
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_EXPORT_PATH_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}`);
specSourcePath = appRequire.resolve(posix.join(packageName, matchingExport));
}
} else {
specSourcePath = packageJsonPath.replace(/package.json$/, packagePath);
Expand All @@ -59,8 +63,11 @@ void (async () => {

let specDestinationPath = output;
if (!specDestinationPath) {
const specSourceExtension = extname(specSourcePath);
specDestinationPath = `./openapi${specSourceExtension}`;
let specSourceExtension = extname(specSourcePath);
if (specSourceExtension === `.${SPEC_YML_EXTENSION}`) {
specSourceExtension = `.${SPEC_YAML_EXTENSION}`;
}
specDestinationPath = `./${LOCAL_SPEC_FILENAME}${specSourceExtension}`;
if (existsSync(openApiConfigDefaultPath)) {
const openApiConfig = JSON.parse(await readFile(openApiConfigDefaultPath, {encoding: 'utf8'})) as OpenApiToolsConfiguration;
const generators: OpenApiToolsGenerator[] = 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 @@
// TODO: Change to `openapi` in v11 (ref: #1745)
/** 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` in v11 (ref: #1745)
/** Extension of the Specification file in JSON format */
export const SPEC_JSON_EXTENSION = 'yaml';
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 export path inside the package.json 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
14 changes: 12 additions & 2 deletions packages/@ama-sdk/create/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
/* 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';
import { LOCAL_SPEC_FILENAME, SPEC_JSON_EXTENSION, SPEC_YAML_EXTENSION } from '@ama-sdk/core';

const packageManagerEnv = process.env.npm_config_user_agent?.split('/')[0];
const binPath = resolve(require.resolve('@angular-devkit/schematics-cli/package.json'), '../bin/schematics.js');
Expand Down Expand Up @@ -65,6 +66,14 @@ if (argv['spec-path'] && argv['spec-package-name']) {
process.exit(-4);
}

/* 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 localSpecFileComputedExtension = argv['spec-package-path'] && extname(argv['spec-package-path']) === '.json' ? `.${SPEC_JSON_EXTENSION}` : `.${SPEC_YAML_EXTENSION}`;
localFilePathToBeCreated = `./${LOCAL_SPEC_FILENAME}${localSpecFileComputedExtension}`;
}

const commonSchematicArgs = [
argv.debug !== undefined ? `--debug=${argv.debug as string}` : '--debug=false', // schematics enable debug mode per default when using schematics with relative path
...(name ? ['--name', name] : []),
Expand All @@ -88,7 +97,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.
> The `--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 the optional parameters `--spec-package-registry` and `--spec-package-path` to be able to retrieve 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 @@ -114,4 +114,63 @@ describe('Typescript Shell Generator', () => {
const {name} = tree.readJson('/package.json') as PackageJson;
expect(name).toEqual('test-sdk');
});

it('should generate renovate config with otter presets for npm', () => {
const renovateConfig = npmTree.readJson('/.renovaterc.json') as PackageJson;
const renovatePresets = renovateConfig.extends;
expect(renovatePresets).toEqual([
'github>AmadeusITGroup/otter//tools/renovate/base',
'github>AmadeusITGroup/otter//tools/renovate/group/otter',
'github>AmadeusITGroup/otter//tools/renovate/tasks/base',
'github>AmadeusITGroup/otter//tools/renovate/tasks/sdk-regenerate(npm)'
]);
});

it('should generate renovate config with otter presets for npm with packageName', async () => {
const runner = new SchematicTestRunner('@ama-sdk/schematics', collectionPath);
const tree = await runner.runSchematic('typescript-shell', {
name: 'test-scope',
package: 'test-sdk',
skipInstall: true,
packageManager: 'npm',
specPackageName: '@my-spec-scope/my-spec'
}, Tree.empty());
const renovateConfig = tree.readJson('/.renovaterc.json') as PackageJson;
const renovatePresets = renovateConfig.extends;
expect(renovatePresets).toEqual([
'github>AmadeusITGroup/otter//tools/renovate/base',
'github>AmadeusITGroup/otter//tools/renovate/group/otter',
'github>AmadeusITGroup/otter//tools/renovate/tasks/base',
'github>AmadeusITGroup/otter//tools/renovate/tasks/sdk-regenerate(npm)',
'github>AmadeusITGroup/otter//tools/renovate/group/sdk-spec(@my-spec-scope/my-spec)',
'github>AmadeusITGroup/otter//tools/renovate/tasks/sdk-spec-regenerate(npm, @my-spec-scope/my-spec)'
]);
});

it('should generate renovate config with otter presets for yarn', () => {
const renovateConfig = yarnTree.readJson('/.renovaterc.json') as PackageJson;
const renovatePresets = renovateConfig.extends;
expect(renovatePresets).toEqual([
'github>AmadeusITGroup/otter//tools/renovate/base',
'github>AmadeusITGroup/otter//tools/renovate/sdk'
]);
});

it('should generate renovate config with otter presets for yarn with packageName', async () => {
const runner = new SchematicTestRunner('@ama-sdk/schematics', collectionPath);
const tree = await runner.runSchematic('typescript-shell', {
name: 'test-scope',
package: 'test-sdk',
skipInstall: true,
packageManager: 'yarn',
specPackageName: '@my-spec-scope/my-spec'
}, Tree.empty());
const renovateConfig = tree.readJson('/.renovaterc.json') as PackageJson;
const renovatePresets = renovateConfig.extends;
expect(renovatePresets).toEqual([
'github>AmadeusITGroup/otter//tools/renovate/base',
'github>AmadeusITGroup/otter//tools/renovate/sdk',
'github>AmadeusITGroup/otter//tools/renovate/sdk-spec-upgrade(@my-spec-scope/my-spec)'
]);
});
});
37 changes: 27 additions & 10 deletions packages/@ama-sdk/schematics/schematics/typescript/shell/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,15 @@ function ngGenerateTypescriptSDKFn(options: NgGenerateTypescriptSDKShellSchemati
const specScope = options.specPackageName?.startsWith('@') ? options.specPackageName.substring(1).split('/')[0] : undefined;

if (properties.packageManager === 'yarn') {
const yarnrcPath = posix.join(tree.root.path, '.yarnrc.yml');
const yarnrc = (load(tree.exists(yarnrcPath) ? tree.readText(yarnrcPath) : '') || {}) as any;
const workspaceRootYarnRcPath = posix.join(tree.root.path, '.yarnrc.yml');
const standaloneYarnRcPath = posix.join(targetPath, '.yarnrc.yml');

let yarnrc;
if (tree.exists(workspaceRootYarnRcPath)) {
yarnrc = load(tree.readText(workspaceRootYarnRcPath));
} else {
yarnrc = (load(tree.exists(standaloneYarnRcPath) ? tree.readText(standaloneYarnRcPath) : '') || {}) as any;
}
yarnrc.nodeLinker ||= 'pnp';
yarnrc.packageExtensions ||= {};
yarnrc.packageExtensions['@ama-sdk/schematics@*'] = {
Expand All @@ -103,20 +110,30 @@ function ngGenerateTypescriptSDKFn(options: NgGenerateTypescriptSDKShellSchemati
};
}

if (tree.exists(yarnrcPath)) {
tree.overwrite(yarnrcPath, dump(yarnrc, {indent: 2}));
if (tree.exists(workspaceRootYarnRcPath)) {
tree.overwrite(workspaceRootYarnRcPath, dump(yarnrc, {indent: 2}));
} else if (tree.exists(standaloneYarnRcPath)){
tree.overwrite(standaloneYarnRcPath, dump(yarnrc, {indent: 2}));
} else {
tree.create(yarnrcPath, dump(yarnrc, {indent: 2}));
tree.create(standaloneYarnRcPath, dump(yarnrc, {indent: 2}));
}
} else if (properties.packageManager === 'npm') {
if (options.specPackageRegistry && specScope) {
const npmrcPath = posix.join(tree.root.path, '.npmrc');
let npmrc = tree.exists(npmrcPath) ? tree.readText(npmrcPath) : '';
const workspaceRootNpmrcPath = posix.join(tree.root.path, '.npmrc');
const standaloneNpmrcPath = posix.join(targetPath, '.npmrc');
let npmrc;
if (tree.exists(workspaceRootNpmrcPath)) {
npmrc = tree.readText(workspaceRootNpmrcPath);
} else {
npmrc = tree.exists(standaloneNpmrcPath) ? tree.readText(standaloneNpmrcPath) : '';
}
npmrc += `\n@${specScope}:registry=${options.specPackageRegistry}\n`;
if (tree.exists(npmrcPath)) {
tree.overwrite(npmrcPath, npmrc);
if (tree.exists(workspaceRootNpmrcPath)) {
tree.overwrite(workspaceRootNpmrcPath, npmrc);
} else if (tree.exists(standaloneNpmrcPath)){
tree.overwrite(standaloneNpmrcPath, npmrc);
} else {
tree.create(npmrcPath, npmrc);
tree.create(standaloneNpmrcPath, npmrc);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"github>AmadeusITGroup/otter//tools/renovate/base",
"github>AmadeusITGroup/otter//tools/renovate/sdk",
"github>AmadeusITGroup/otter//tools/renovate/sdk-spec-upgrade(my-specification-package)"
"github>AmadeusITGroup/otter//tools/renovate/base",<% if (packageManager === 'yarn') { %>
"github>AmadeusITGroup/otter//tools/renovate/sdk"<% if (specPackageName) { %>,
"github>AmadeusITGroup/otter//tools/renovate/sdk-spec-upgrade(<%= specPackageName %>)"<% } %><% } else { %>
"github>AmadeusITGroup/otter//tools/renovate/group/otter",
"github>AmadeusITGroup/otter//tools/renovate/tasks/base",
"github>AmadeusITGroup/otter//tools/renovate/tasks/sdk-regenerate(npm)"<% if (specPackageName) { %>,
"github>AmadeusITGroup/otter//tools/renovate/group/sdk-spec(<%= specPackageName %>)",
"github>AmadeusITGroup/otter//tools/renovate/tasks/sdk-spec-regenerate(npm, <%= specPackageName %>)"<% } %><% } %>
],
"prConcurrentLimit": 0,
"prHourlyLimit": 0,
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
8 changes: 5 additions & 3 deletions packages/@o3r/workspace/schematics/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ function generateSdkFn(options: NgGenerateSdkSchema): Rule {
]), MergeStrategy.Overwrite);

const packageManager = getPackageManager({ workspaceConfig });
const specExtension = options.specPackagePath ? path.extname(options.specPackagePath) : '.yml';
const specPath = options.specPackageName ? `openapi${specExtension}` : options.specPath;
const specExtension = options.specPackagePath ? path.extname(options.specPackagePath) : '.yaml';
// TODO: Change `swagger-spec` to `openapi` in v11 (ref: #1745)
const specPath = options.specPackageName ? `swagger-spec${specExtension}` : options.specPath;
return chain([
externalSchematic('@ama-sdk/schematics', 'typescript-shell', {
...options,
Expand All @@ -68,7 +69,8 @@ function generateSdkFn(options: NgGenerateSdkSchema): Rule {
c.addTask(new NpmExecTask('amasdk-update-spec-from-npm', [
options.specPackageName,
...options.specPackagePath ? ['--package-path', options.specPackagePath] : [],
'--output', path.join(process.cwd(), targetPath, `openapi${specExtension}`)
// TODO: Change `swagger-spec` to `openapi` in v11 (ref: #1745)
'--output', path.join(process.cwd(), targetPath, `swagger-spec${specExtension}`)
], targetPath), [installTask])
] : [];
c.addTask(new RunSchematicTask('@ama-sdk/schematics', 'typescript-core', {
Expand Down
Loading

0 comments on commit 3cd2769

Please sign in to comment.