Generates list of migrations on the plugin overview page and a standalone `/migrations` page. To add sample code changes for a migration that has an implementation file, create a `.md` file with the same name as the implementation file in the same folder as the implementation file. i.e. `move-cache-directory.md` for `move-cache-directory.ts`. Migrations that have `packages` defined will have a table generated with the package updates listed. Separate PRs will be created to add sample code changes for each migration with an implementation. The migration list on the plugin overview page: [Angular migrations](https://nx-dev-git-docs-migration-details-nrwl.vercel.app/nx-api/angular#migrations) Standalone migration list page: [Angular migrations](https://nx-dev-git-docs-migration-details-nrwl.vercel.app/nx-api/angular/migrations) Sample migration with added markdown file details: [17.0.0-move-cache-directory](https://nx-dev-git-docs-migration-details-nrwl.vercel.app/nx-api/nx#1700movecachedirectory) Sample migration with only package updates: [Angular 20.4.0](https://nx-dev-git-docs-migration-details-nrwl.vercel.app/nx-api/angular#2040packageupdates) Sample migration without any markdown file details: [update-angular-cli-version-19-1-0](https://nx-dev-git-docs-migration-details-nrwl.vercel.app/nx-api/angular#updateangularcliversion1910) - This last sample is very bare-bones and the reason why we need these pages in the first place. People don't know what migrations are actually doing. Follow up PRs will address pages like this.
240 lines
7.2 KiB
TypeScript
240 lines
7.2 KiB
TypeScript
/*
|
|
* Lookup for all the schema.json and add create a list with their path and related package information
|
|
* */
|
|
import { createDocumentMetadata } from '@nx/nx-dev/models-document';
|
|
import * as chalk from 'chalk';
|
|
import { join, resolve } from 'path';
|
|
import { compare } from 'semver';
|
|
import {
|
|
getSchemaFromReference,
|
|
InternalLookup,
|
|
} from '@nx/nx-dev/data-access-packages';
|
|
import { NxSchema, PackageMetadata } from '@nx/nx-dev/models-package';
|
|
import { generateJsonFile, generateMarkdownFile } from '../utils';
|
|
import { findPackageMetadataList } from './package-metadata';
|
|
import { schemaResolver, getExamplesFileFromPath } from './schema.resolver';
|
|
|
|
function processSchemaData(data: NxSchema, path: string): NxSchema {
|
|
const lookup = new InternalLookup(data);
|
|
const schema = getSchemaFromReference('#', lookup) as NxSchema;
|
|
|
|
if (schema === undefined)
|
|
throw new Error('ERROR: Could not look up the schema at: ' + data.title);
|
|
|
|
if (typeof schema === 'boolean')
|
|
throw new Error('ERROR: Boolean schema not supported.');
|
|
|
|
const resolver = schemaResolver(schema, lookup, path);
|
|
resolver.resolveReferences();
|
|
resolver.resolveExamplesFile();
|
|
return resolver.getSchema();
|
|
}
|
|
|
|
function updateMigration(migration: any, absoluteRoot: string): any {
|
|
if (!migration.implementation) {
|
|
if (migration.packages) {
|
|
migration.name = migration.name + '-package-updates';
|
|
}
|
|
return migration;
|
|
}
|
|
migration.examplesFile = getExamplesFileFromPath(
|
|
absoluteRoot,
|
|
migration.implementation.replace('.ts', '.md')
|
|
);
|
|
return migration;
|
|
}
|
|
|
|
function pathResolver(root: string): (path: string) => string {
|
|
return (path) => join(root, path.replace('schema.json', ''));
|
|
}
|
|
|
|
export function generateLocalPackageSchemas(): Promise<void[]> {
|
|
return generatePackageSchemas();
|
|
}
|
|
|
|
export function generateExternalPackageSchemas(): Promise<any> {
|
|
const sourceRepositoryRelativePath = process.env.NX_OCEAN_RELATIVE_PATH;
|
|
if (!sourceRepositoryRelativePath) {
|
|
return Promise.all([]);
|
|
}
|
|
const sourcePackagesDirectory = 'libs/nx-packages';
|
|
const sourcePackagesNamePrefix = 'powerpack-';
|
|
return generatePackageSchemas(
|
|
sourceRepositoryRelativePath,
|
|
sourcePackagesDirectory,
|
|
sourcePackagesNamePrefix
|
|
);
|
|
}
|
|
|
|
export function generatePackageSchemas(
|
|
sourceRepositoryRelativePath = '',
|
|
sourcePackagesDirectory = 'packages',
|
|
sourcePackagesNamePrefix = ''
|
|
): Promise<void[]> {
|
|
console.log(`${chalk.blue('i')} Generating Package Schemas`);
|
|
const absoluteRoot = resolve(join(__dirname, '../../../'));
|
|
const sourceRepositoryRoot = resolve(
|
|
join(__dirname, '../../../', sourceRepositoryRelativePath)
|
|
);
|
|
const generatedFolderName = sourceRepositoryRelativePath
|
|
? 'external-generated'
|
|
: 'generated';
|
|
|
|
const packages = findPackageMetadataList(
|
|
sourceRepositoryRoot,
|
|
sourcePackagesDirectory,
|
|
sourcePackagesNamePrefix
|
|
).map((packageMetadata) => {
|
|
const getCurrentSchemaPath = pathResolver(absoluteRoot);
|
|
if (!!packageMetadata.executors.length) {
|
|
packageMetadata.executors = packageMetadata.executors.map((item) => ({
|
|
...item,
|
|
schema: processSchemaData(
|
|
item.schema as NxSchema,
|
|
getCurrentSchemaPath(item['path'].replace('schema.json', ''))
|
|
),
|
|
}));
|
|
}
|
|
if (!!packageMetadata.generators.length) {
|
|
packageMetadata.generators = packageMetadata.generators.map((item) => ({
|
|
...item,
|
|
schema: processSchemaData(
|
|
item.schema as NxSchema,
|
|
getCurrentSchemaPath(item['path'].replace('schema.json', ''))
|
|
),
|
|
}));
|
|
}
|
|
if (!!packageMetadata.migrations.length) {
|
|
packageMetadata.migrations = packageMetadata.migrations
|
|
.map((item) => ({
|
|
...updateMigration(item, absoluteRoot),
|
|
}))
|
|
.sort((m1, m2) => compare(m1.version, m2.version) * -1);
|
|
}
|
|
return packageMetadata;
|
|
});
|
|
const packagesMetadata = packages.map(
|
|
(p): PackageMetadata => ({
|
|
description: p.description,
|
|
documents: p.documents.map((d) => ({
|
|
...createDocumentMetadata({
|
|
description: d.description || p.description,
|
|
file: [
|
|
generatedFolderName,
|
|
'packages',
|
|
p.name,
|
|
'documents',
|
|
d.id,
|
|
].join('/'),
|
|
id: d.id,
|
|
itemList: d.itemList,
|
|
name: d.name,
|
|
path: [p.name, 'documents', d.id].join('/'),
|
|
tags: d.tags,
|
|
}),
|
|
originalFilePath: d.file,
|
|
})),
|
|
executors: p.executors.map((e) => ({
|
|
description: e.description,
|
|
file: [
|
|
generatedFolderName,
|
|
'packages',
|
|
p.name,
|
|
'executors',
|
|
e.name + '.json',
|
|
].join('/'),
|
|
hidden: e.hidden,
|
|
name: e.name,
|
|
originalFilePath: e.path,
|
|
path: [p.name, 'executors', e.name].join('/'),
|
|
type: 'executor',
|
|
})),
|
|
generators: p.generators.map((g) => ({
|
|
description: g.description,
|
|
file: [
|
|
generatedFolderName,
|
|
'packages',
|
|
p.name,
|
|
'generators',
|
|
g.name + '.json',
|
|
].join('/'),
|
|
hidden: g.hidden,
|
|
name: g.name,
|
|
originalFilePath: g.path,
|
|
path: [p.name, 'generators', g.name].join('/'),
|
|
type: 'generator',
|
|
})),
|
|
migrations: p.migrations.map((m) => ({
|
|
description: m.description,
|
|
file: [
|
|
generatedFolderName,
|
|
'packages',
|
|
p.name,
|
|
'migrations',
|
|
m.name + '.json',
|
|
].join('/'),
|
|
hidden: m.hidden,
|
|
name: m.name,
|
|
version: (m as any).version,
|
|
originalFilePath: m.path,
|
|
path: [p.name, 'migrations', m.name].join('/'),
|
|
type: 'migration',
|
|
})),
|
|
githubRoot: p.githubRoot,
|
|
name: p.name,
|
|
packageName: p.packageName,
|
|
root: p.root,
|
|
source: p.source,
|
|
})
|
|
);
|
|
|
|
const outputPath: string = join(absoluteRoot, 'docs', generatedFolderName);
|
|
const outputPackagesPath: string = join(outputPath, 'packages');
|
|
const fileGenerationPromises: Promise<void>[] = [];
|
|
|
|
// Generates all documents and schemas into their own directories per packages.
|
|
packages.forEach((p) => {
|
|
p.documents.forEach((d) =>
|
|
fileGenerationPromises.push(
|
|
generateMarkdownFile(join(outputPackagesPath, p.name, 'documents'), {
|
|
name: d.id,
|
|
template: d.content,
|
|
})
|
|
)
|
|
);
|
|
p.executors.forEach((e) =>
|
|
fileGenerationPromises.push(
|
|
generateJsonFile(
|
|
join(outputPackagesPath, p.name, 'executors', e.name + '.json'),
|
|
e
|
|
)
|
|
)
|
|
);
|
|
p.generators.forEach((g) =>
|
|
fileGenerationPromises.push(
|
|
generateJsonFile(
|
|
join(outputPackagesPath, p.name, 'generators', g.name + '.json'),
|
|
g
|
|
)
|
|
)
|
|
);
|
|
p.migrations.forEach((g) =>
|
|
fileGenerationPromises.push(
|
|
generateJsonFile(
|
|
join(outputPackagesPath, p.name, 'migrations', g.name + '.json'),
|
|
g
|
|
)
|
|
)
|
|
);
|
|
});
|
|
|
|
// Generates the packages-metadata.json file.
|
|
fileGenerationPromises.push(
|
|
generateJsonFile(
|
|
join(outputPath, 'packages-metadata.json'),
|
|
packagesMetadata
|
|
)
|
|
);
|
|
return Promise.all(fileGenerationPromises);
|
|
}
|