fix: Support Prettier v3 in repo-tools (#27559)
Signed-off-by: Gabriel Dugny <gabriel.dugny@believe.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/repo-tools': patch
|
||||
---
|
||||
|
||||
Support Prettier v3 for api-reports
|
||||
@@ -14,10 +14,8 @@ type-docs
|
||||
# old reports
|
||||
api-report.md
|
||||
api-report-*.md
|
||||
# new reports
|
||||
report.api.md
|
||||
report-*.api.md
|
||||
|
||||
knip-report.md
|
||||
cli-report.md
|
||||
plugins/scaffolder-backend/sample-templates
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
"@microsoft/api-documenter": "^7.28.1",
|
||||
"@microsoft/api-extractor": "^7.55.1",
|
||||
"@openapitools/openapi-generator-cli": "^2.7.0",
|
||||
"@prettier/sync": "^0.6.1",
|
||||
"@stoplight/spectral-core": "^1.18.0",
|
||||
"@stoplight/spectral-formatters": "^1.1.0",
|
||||
"@stoplight/spectral-functions": "^1.7.2",
|
||||
@@ -99,7 +100,7 @@
|
||||
"@microsoft/tsdoc": "*",
|
||||
"@microsoft/tsdoc-config": "*",
|
||||
"@useoptic/optic": "^1.0.0",
|
||||
"prettier": "^2.8.1",
|
||||
"prettier": "^2.8.1 || ^3.8.1",
|
||||
"typedoc": "^0.28.0",
|
||||
"typescript": "> 3.0.0"
|
||||
},
|
||||
|
||||
+9
-3
@@ -17,7 +17,8 @@
|
||||
import { ExtractorMessage } from '@microsoft/api-extractor';
|
||||
import { AstDeclaration } from '@microsoft/api-extractor/lib/analyzer/AstDeclaration';
|
||||
import { Program } from 'typescript';
|
||||
import { tryRunPrettier } from '../common';
|
||||
import { tryRunPrettier } from '../common/tryRunPrettier';
|
||||
import { paths as cliPaths } from '../../../lib/paths';
|
||||
|
||||
let applied = false;
|
||||
|
||||
@@ -152,12 +153,17 @@ export function patchApiReportGeneration() {
|
||||
* the middle of the process as API Extractor does a comparison of the contents of the old
|
||||
* and new files during generation. This inserts the formatting just before that comparison.
|
||||
*/
|
||||
|
||||
const content = originalGenerateReviewFileContent.call(
|
||||
this,
|
||||
collector,
|
||||
...moreArgs,
|
||||
);
|
||||
|
||||
return tryRunPrettier(content);
|
||||
return tryRunPrettier(content, {
|
||||
parser: 'markdown',
|
||||
// We need a real-looking filepath for proper config resolution, not just a directory
|
||||
// Ideally, the real filepath would be better, but it would require too much patching, for very little gain.
|
||||
filepath: `${cliPaths.targetRoot}/report.api.md`,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { tryRunPrettier } from './tryRunPrettier';
|
||||
export { tryRunPrettier, tryRunPrettierAsync } from './tryRunPrettier';
|
||||
export { logApiReportInstructions } from './logApiReportInstructions';
|
||||
|
||||
@@ -17,19 +17,104 @@
|
||||
import { paths as cliPaths } from '../../../lib/paths';
|
||||
import type { Config } from 'prettier';
|
||||
|
||||
/**
|
||||
* Tries to run prettier asynchronously, with Prettier v2 or v3.
|
||||
* @param content - The content to format.
|
||||
* @param extraConfig - Additional prettier config options (defaults to markdown parser). Providing a filepath is recommended for proper config resolution.
|
||||
* @returns A promise that resolves to the formatted content or the original content if the formatting fails.
|
||||
* @internal
|
||||
*/
|
||||
export async function tryRunPrettierAsync(
|
||||
content: string,
|
||||
extraConfig: Config = { parser: 'markdown' },
|
||||
): Promise<string> {
|
||||
try {
|
||||
const prettier = require('prettier') as typeof import('prettier');
|
||||
// Filepath for proper config resolution
|
||||
const filepath =
|
||||
extraConfig.filepath ??
|
||||
`${cliPaths.targetRoot}/should-not-be-ignored.any`;
|
||||
const config =
|
||||
(await prettier.resolveConfig(filepath, { editorconfig: true })) ?? {};
|
||||
const formattedContent = prettier.format(content, {
|
||||
...config,
|
||||
...extraConfig,
|
||||
});
|
||||
// XXX: Remove once only v3 is supported
|
||||
if (typeof formattedContent === 'string') {
|
||||
return Promise.resolve(formattedContent);
|
||||
}
|
||||
return formattedContent;
|
||||
} catch (e) {
|
||||
return Promise.resolve(content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a synchronous prettier formatter function for v2 or v3 via `@prettier/sync`.
|
||||
*
|
||||
* @param prettierSync - The prettier instance, either v2 or v3 via `@prettier/sync`.
|
||||
* @param extraConfig - Additional prettier config options (defaults to markdown parser)
|
||||
* @returns A function that formats content using the prettier instance and config
|
||||
*/
|
||||
export function createPrettierSyncFormatter(
|
||||
prettierSync:
|
||||
| typeof import('prettier')
|
||||
| typeof import('@prettier/sync').default,
|
||||
extraConfig: Config = {},
|
||||
): (content: string) => string {
|
||||
return function tryRunPrettierInner(content: string): string {
|
||||
try {
|
||||
// We need a filepath for proper config resolution, not just a directory
|
||||
const filepath =
|
||||
extraConfig.filepath ??
|
||||
`${cliPaths.targetRoot}/should-not-be-ignored.any`;
|
||||
const resolveConfig =
|
||||
// @ts-expect-error: v2 requires .sync, @prettier/sync v3 does not
|
||||
prettierSync.resolveConfig?.sync ?? prettierSync.resolveConfig;
|
||||
const config =
|
||||
resolveConfig(filepath, {
|
||||
editorconfig: true,
|
||||
}) ?? {};
|
||||
return prettierSync.format(content, {
|
||||
...config,
|
||||
...extraConfig,
|
||||
});
|
||||
} catch (e) {
|
||||
return content;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the prettier instance, either v2 or v3 via @prettier/sync.
|
||||
* XXX: Remove once only v3 is supported
|
||||
* @returns The prettier instance, either v2 or v3 via @prettier/sync.
|
||||
*/
|
||||
function loadPrettierSync():
|
||||
| typeof import('prettier')
|
||||
| typeof import('@prettier/sync').default {
|
||||
const prettier = require('prettier') as typeof import('prettier');
|
||||
if (prettier.version.startsWith('2')) {
|
||||
return prettier;
|
||||
}
|
||||
return require('@prettier/sync').default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to run prettier synchronously, with Prettier v2 or v3.
|
||||
* @param content - The content to format.
|
||||
* @param extraConfig - Additional prettier config options (defaults to markdown parser)
|
||||
* @returns The formatted content.
|
||||
* @internal
|
||||
*/
|
||||
export function tryRunPrettier(
|
||||
content: string,
|
||||
extraConfig: Config = { parser: 'markdown' },
|
||||
): string {
|
||||
try {
|
||||
const prettier = require('prettier') as typeof import('prettier');
|
||||
|
||||
const config = prettier.resolveConfig.sync(cliPaths.targetRoot) ?? {};
|
||||
return prettier.format(content, {
|
||||
...config,
|
||||
...extraConfig,
|
||||
});
|
||||
} catch (e) {
|
||||
return content;
|
||||
}
|
||||
const formatter = createPrettierSyncFormatter(
|
||||
loadPrettierSync(),
|
||||
extraConfig,
|
||||
);
|
||||
return formatter(content);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { SchemaInfo } from './types';
|
||||
import { getPgSchemaInfo } from './getPgSchemaInfo';
|
||||
import { generateSqlReport } from './generateSqlReport';
|
||||
import type { Knex } from 'knex';
|
||||
import { logApiReportInstructions, tryRunPrettier } from '../common';
|
||||
import { logApiReportInstructions, tryRunPrettierAsync } from '../common';
|
||||
|
||||
interface SqlExtractionOptions {
|
||||
packageDirs: string[];
|
||||
@@ -152,19 +152,19 @@ async function runSingleSqlExtraction(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const report = tryRunPrettier(
|
||||
const reportPath = cliPaths.resolveTargetRoot(
|
||||
targetDir,
|
||||
`report${migrationTarget === '.' ? '' : `-${migrationTarget}`}.sql.md`,
|
||||
);
|
||||
const report = await tryRunPrettierAsync(
|
||||
generateSqlReport({
|
||||
reportName,
|
||||
failedDownMigration,
|
||||
schemaInfo,
|
||||
}),
|
||||
{ filepath: reportPath },
|
||||
);
|
||||
|
||||
const reportPath = cliPaths.resolveTargetRoot(
|
||||
targetDir,
|
||||
`report${migrationTarget === '.' ? '' : `-${migrationTarget}`}.sql.md`,
|
||||
);
|
||||
const existingReport = await fs.readFile(reportPath, 'utf8').catch(error => {
|
||||
if (error.code === 'ENOENT') {
|
||||
return undefined;
|
||||
|
||||
@@ -7868,6 +7868,7 @@ __metadata:
|
||||
"@microsoft/api-documenter": "npm:^7.28.1"
|
||||
"@microsoft/api-extractor": "npm:^7.55.1"
|
||||
"@openapitools/openapi-generator-cli": "npm:^2.7.0"
|
||||
"@prettier/sync": "npm:^0.6.1"
|
||||
"@stoplight/spectral-core": "npm:^1.18.0"
|
||||
"@stoplight/spectral-formatters": "npm:^1.1.0"
|
||||
"@stoplight/spectral-functions": "npm:^1.7.2"
|
||||
@@ -7907,7 +7908,7 @@ __metadata:
|
||||
"@microsoft/tsdoc": "*"
|
||||
"@microsoft/tsdoc-config": "*"
|
||||
"@useoptic/optic": ^1.0.0
|
||||
prettier: ^2.8.1
|
||||
prettier: ^2.8.1 || ^3.8.1
|
||||
typedoc: ^0.28.0
|
||||
typescript: "> 3.0.0"
|
||||
peerDependenciesMeta:
|
||||
@@ -14355,6 +14356,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@prettier/sync@npm:^0.6.1":
|
||||
version: 0.6.1
|
||||
resolution: "@prettier/sync@npm:0.6.1"
|
||||
dependencies:
|
||||
make-synchronized: "npm:^0.8.0"
|
||||
peerDependencies:
|
||||
prettier: "*"
|
||||
checksum: 10/2c53cd4ee718e2ebd2fb31aa5ec4773f743b9c29fcc6db6794dc3553bc87aa8fe7db47b51add6809cab655520b7550329d1cce2ca837f6f4643991eff44abad1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2":
|
||||
version: 1.1.2
|
||||
resolution: "@protobufjs/aspromise@npm:1.1.2"
|
||||
@@ -38013,6 +38025,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"make-synchronized@npm:^0.8.0":
|
||||
version: 0.8.0
|
||||
resolution: "make-synchronized@npm:0.8.0"
|
||||
checksum: 10/e744bafcd61ee1ecabe6fb2c295ecb4b06a7bfe4e844222b80b7a5ae80a4d27ba657abc4892d1c702fa2f6ae568d8505e801c1498fe1379dd824ded5483d978c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"makeerror@npm:1.0.12":
|
||||
version: 1.0.12
|
||||
resolution: "makeerror@npm:1.0.12"
|
||||
|
||||
Reference in New Issue
Block a user