Skip to content

Commit

Permalink
feat: implement proper v2 plugin code
Browse files Browse the repository at this point in the history
  • Loading branch information
BioPhoton committed Sep 24, 2024
1 parent 13606e9 commit 8c81c96
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 50 deletions.
2 changes: 1 addition & 1 deletion nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"plugins": [
"./examples/e2e/cli-e2e-original/tooling/original.plugin.ts",
{
"plugin": "./projects/build-env/src/plugin/build-env.plugin.ts",
"plugin": "./projects/build-env/src/index.ts",
"options": {
"packages": {
"filterByTags": ["publishable"]
Expand Down
2 changes: 1 addition & 1 deletion projects/build-env/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { createNodes } from './plugin/build-env.plugin';
export { createNodes, createNodesV2 } from './plugin/build-env.plugin';
190 changes: 142 additions & 48 deletions projects/build-env/src/plugin/build-env.plugin.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,159 @@
import {
type CreateNodes,
CreateNodesContext,
createNodesFromFiles,
CreateNodesResult,
CreateNodesV2,
logger,
type ProjectConfiguration,
readJsonFile,
writeJsonFile,
} from '@nx/devkit';
import { dirname, join } from 'node:path';
import {
getEnvTargets,
isEnvProject,
updateEnvTargetNames,
verdaccioTargets,
} from './targets/environment.targets';
import { getPkgTargets, isPkgProject } from './targets/package.targets';
import type { BuildEnvPluginCreateNodeOptions } from './schema';
import { normalizeCreateNodesOptions } from './normalize-create-nodes-options';
import {basename, dirname, join} from 'node:path';
import {existsSync} from 'node:fs';
import {getEnvTargets, isEnvProject, updateEnvTargetNames, verdaccioTargets,} from './targets/environment.targets';
import {getPkgTargets, isPkgProject} from './targets/package.targets';
import type {BuildEnvPluginCreateNodeOptions} from './schema';
import {normalizeCreateNodesOptions,} from './normalize-create-nodes-options';
import {workspaceDataDirectory} from 'nx/src/utils/cache-directory';
import {hashObject} from 'nx/src/hasher/file-hasher';
import {PLUGIN_NAME} from './constants';

export const createNodes: CreateNodes = [
'**/project.json',
(projectConfigurationFile: string, opt: BuildEnvPluginCreateNodeOptions) => {
const { environments, packages } = normalizeCreateNodesOptions(opt);
function readTargetsCache(
cachePath: string
): Record<string, CreateNodesResult['projects']> {
return process.env.NX_CACHE_PROJECT_GRAPH !== 'false' && existsSync(cachePath)
? readJsonFile(cachePath)
: {};
}

const projectConfiguration: ProjectConfiguration = readJsonFile(
join(process.cwd(), projectConfigurationFile)
);
function writeTargetsToCache(
cachePath: string,
results: Record<string, CreateNodesResult['projects']>
) {
writeJsonFile(cachePath, results);
}

if (
!('name' in projectConfiguration) ||
typeof projectConfiguration.name !== 'string'
) {
throw new Error('Project name is required');
}
const projectRoot = dirname(projectConfigurationFile);
const CREATE_NODES_FILE_GLOB = '**/project.json';

if (
!isEnvProject(projectConfiguration, environments) &&
!isPkgProject(projectConfiguration, packages)
) {
return {};
export const createNodesV2: CreateNodesV2<BuildEnvPluginCreateNodeOptions> = [
CREATE_NODES_FILE_GLOB,
async (configFiles, options, context) => {
logger.info('`createNodesV2` is used.');
const normalizedOptions = normalizeCreateNodesOptions(options);
const optionsHash = hashObject(normalizedOptions);
const cachePath = join(
workspaceDataDirectory,
`push-based--${PLUGIN_NAME}-${optionsHash}.hash`
);
const targetsCache = readTargetsCache(cachePath);
try {
return await createNodesFromFiles(
(configFile, internalOptions, context) =>
createNodesInternal(
configFile,
internalOptions,
context,
targetsCache
),
configFiles,
options,
context
);
} finally {
writeTargetsToCache(cachePath, targetsCache);
}
},
];

export const createNodes: CreateNodes = [
CREATE_NODES_FILE_GLOB,
(
projectConfigurationFile: string,
options: BuildEnvPluginCreateNodeOptions,
context: CreateNodesContext
) => {
logger.warn(
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
);
const normalizedOptions = normalizeCreateNodesOptions(options);
return createNodesInternal(
projectConfigurationFile,
normalizedOptions,
context,
{}
);
},
];

async function createNodesInternal(
projectConfigurationFile: string,
options: BuildEnvPluginCreateNodeOptions,
context: CreateNodesContext,
targetsCache?: Record<string, CreateNodesResult['projects']>
): Promise<CreateNodesResult> {
const { environments, packages } = normalizeCreateNodesOptions(options);

const projectConfiguration: ProjectConfiguration = readJsonFile(
join(process.cwd(), projectConfigurationFile)
);

if (
!('name' in projectConfiguration) ||
typeof projectConfiguration.name !== 'string'
) {
throw new Error('Project name is required');
}
const projectRoot = dirname(projectConfigurationFile);

const projectFolder = basename(dirname(projectConfigurationFile));
const cacheKey = `${projectFolder}-${hashObject({
options,
projectConfigurationFile,
context,
})}`;

if (targetsCache[cacheKey]) {
return {
projects: {
[projectRoot]: {
targets: {
// === environment targets ===
...(isEnvProject(projectConfiguration, environments) && {
// start-verdaccio, stop-verdaccio
...verdaccioTargets(projectConfiguration, {
environmentsDir: environments.environmentsDir,
}),
// bootstrap-env, setup-env, install-env (intermediate target to run dependency targets)
...getEnvTargets(projectConfiguration, environments),
// adjust targets to run setup-env
...updateEnvTargetNames(projectConfiguration, environments),
}),
// === package targets ===
// npm-publish, npm-install
...(isPkgProject(projectConfiguration, packages) &&
getPkgTargets()),
},
targets: targetsCache[cacheKey],
},
},
};
},
];
}

if (
!isEnvProject(projectConfiguration, environments) &&
!isPkgProject(projectConfiguration, packages)
) {
return {};
}

const targets = {
// === environment targets ===
...(isEnvProject(projectConfiguration, environments) && {
// start-verdaccio, stop-verdaccio
...verdaccioTargets(projectConfiguration, {
environmentsDir: environments.environmentsDir,
}),
// bootstrap-env, setup-env, install-env (intermediate target to run dependency targets)
...getEnvTargets(projectConfiguration, environments),
// adjust targets to run setup-env
...updateEnvTargetNames(projectConfiguration, environments),
}),
// === package targets ===
// npm-publish, npm-install
...(isPkgProject(projectConfiguration, packages) && getPkgTargets()),
};

targetsCache[cacheKey] = targets;

return {
projects: {
[projectRoot]: {
targets,
},
},
};
}
1 change: 1 addition & 0 deletions projects/build-env/src/plugin/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { join } from 'node:path';

export const PLUGIN_NAME = 'build-env';
export const DEFAULT_OPTION_ENVIRONMENT_TARGET_NAMES = ['e2e'];
export const DEFAULT_ENVIRONMENTS_OUTPUT_DIR = join('tmp', 'environments');

0 comments on commit 8c81c96

Please sign in to comment.