Skip to content

Commit

Permalink
feat(nx-plugin): fix angular 15.x and 16.x install support (#481)
Browse files Browse the repository at this point in the history
Co-authored-by: Robin Goetz <tug29225@temple.edu>
  • Loading branch information
jeremyhofer and goetzrobin committed Jul 1, 2023
1 parent 0cca665 commit acbdf14
Show file tree
Hide file tree
Showing 17 changed files with 734 additions and 228 deletions.
2 changes: 1 addition & 1 deletion apps/nx-plugin-e2e/tests/nx-plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('nx-plugin e2e', () => {

it('should create hello-world', async () => {
const project = uniq('app');
const res = await runNxCommandAsync(
await runNxCommandAsync(
`generate @analogjs/platform:app ${project} --addTailwind=true --addTRPC=true`
);
copyNodeModules(['@analogjs']);
Expand Down
237 changes: 196 additions & 41 deletions packages/nx-plugin/src/generators/app/generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import {
import generator from './generator';
import { AnalogNxApplicationGeneratorOptions } from './schema';
import { addDependenciesToPackageJson } from '@nx/devkit';
import { test } from 'vitest';

describe('nx-plugin generator', () => {
const setup = async (options: AnalogNxApplicationGeneratorOptions) => {
const setup = async (
options: AnalogNxApplicationGeneratorOptions,
nxVersion = '16.1.0'
) => {
const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
addDependenciesToPackageJson(tree, { nx: '16.0.0' }, {});
addDependenciesToPackageJson(tree, {}, { nx: nxVersion });
await generator(tree, options);
const config = readProjectConfiguration(tree, options.analogAppName);
return {
Expand All @@ -22,15 +26,56 @@ describe('nx-plugin generator', () => {
};
};

const verifyCoreDependencies = (
const verifyCoreDependenciesNxV16_0_0_AngularV15_X = (
dependencies: Record<string, string>,
devDependencies: Record<string, string>
) => {
expect(dependencies['@analogjs/router']).toBe('0.2.0-beta.19');
expect(dependencies['@angular/platform-server']).toBe('~16.1.0');
expect(dependencies['@analogjs/content']).toBe('0.1.9');
expect(dependencies['@analogjs/router']).toBe('0.1.0-alpha.10');
expect(dependencies['@angular/platform-server']).toBe(
dependencies['@angular/core']
);
expect(dependencies['front-matter']).toBe('^4.0.2');
expect(dependencies['marked']).toBe('^4.2.4');
expect(dependencies['prismjs']).toBe('^1.29.0');

expect(devDependencies['@analogjs/platform']).toBe('0.2.0-beta.19');
expect(devDependencies['@nx/devkit']).toBe('~16.0.0');
expect(devDependencies['@nx/angular']).toBe('~16.0.0');
expect(devDependencies['@analogjs/platform']).toBe('0.1.0-beta.22');
expect(devDependencies['@analogjs/vite-plugin-angular']).toBe(
'0.2.0-alpha.29'
);
expect(devDependencies['@nx/vite']).toBe('~16.0.0');
expect(devDependencies['jsdom']).toBe('^20.0.0');
expect(devDependencies['vite']).toBe('^4.0.3');
expect(devDependencies['vite-tsconfig-paths']).toBe('^4.0.2');
expect(devDependencies['vitest']).toBe('^0.31.0');
};

const verifyCoreDependenciesAngularV16_X = (
dependencies: Record<string, string>,
devDependencies: Record<string, string>
) => {
expect(dependencies['@analogjs/content']).toBe('^0.2.0-beta.19');
expect(dependencies['@analogjs/router']).toBe('^0.2.0-beta.19');
expect(dependencies['@angular/platform-server']).toBe(
dependencies['@angular/core']
);
expect(dependencies['front-matter']).toBe('^4.0.2');
expect(dependencies['marked']).toBe('^5.0.2');
expect(dependencies['prismjs']).toBe('^1.29.0');

expect(devDependencies['@nx/devkit']).toBe('^16.4.0');
expect(devDependencies['@nx/angular']).toBe('^16.4.0');
expect(devDependencies['@analogjs/platform']).toBe('^0.2.0-beta.19');
expect(devDependencies['@analogjs/vite-plugin-angular']).toBe(
'^0.2.0-beta.19'
);
expect(devDependencies['@nx/vite']).toBe('^16.4.0');
expect(devDependencies['jsdom']).toBe('^22.0.0');
expect(devDependencies['vite']).toBe('^4.3.9');
expect(devDependencies['vite-tsconfig-paths']).toBe('^4.2.0');
expect(devDependencies['vitest']).toBe('^0.32.2');
};

const verifyConfig = (config: ProjectConfiguration, name: string) => {
Expand All @@ -49,29 +94,10 @@ describe('nx-plugin generator', () => {
expect(hasWelcomeComponentFile).toBeTruthy();
};

it('creates a default analogjs app in the source directory', async () => {
const analogAppName = 'analog';
const { config, tree } = await setup({ analogAppName });
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependencies(dependencies, devDependencies);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);
});

it('creates an analogjs app in the source directory with tailwind set up', async () => {
const analogAppName = 'tailwind-app';
const { config, tree } = await setup({ analogAppName, addTailwind: true });
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependencies(dependencies, devDependencies);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);

const verifyTailwindIsSetUp = (
tree: Tree,
devDependencies: Record<string, string>
) => {
expect(devDependencies['tailwindcss']).toBeDefined();
const hasTailwindConfigFile = tree.exists(
'apps/tailwind-app/tailwind.config.js'
Expand All @@ -81,19 +107,12 @@ describe('nx-plugin generator', () => {
);
expect(hasTailwindConfigFile).toBeTruthy();
expect(hasPostCSSConfigFile).toBeTruthy();
});

it('creates an analogjs app in the source directory with trpc set up', async () => {
const analogAppName = 'trpc-app';
const { config, tree } = await setup({ analogAppName, addTRPC: true });
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependencies(dependencies, devDependencies);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);
};

const verifyTrpcIsSetUp = (
tree: Tree,
dependencies: Record<string, string>
) => {
expect(dependencies['@analogjs/trpc']).toBeDefined();
const hasTrpcClientFile = tree.exists('apps/trpc-app/src/trpc-client.ts');
const hasNoteFile = tree.exists('apps/trpc-app/src/note.ts');
Expand All @@ -112,5 +131,141 @@ describe('nx-plugin generator', () => {
.includes('injectTrpcClient');
expect(providesTrpcClient).toBeTruthy();
expect(injectsTrpcClient).toBeTruthy();
};

const verifyTrpcIsNotSetUp = (
tree: Tree,
dependencies: Record<string, string>
) => {
expect(dependencies['@analogjs/trpc']).not.toBeDefined();
const hasTrpcClientFile = tree.exists('apps/trpc-app/src/trpc-client.ts');
const hasNoteFile = tree.exists('apps/trpc-app/src/note.ts');
const hasTrpcServerRoute = tree.exists(
'apps/trpc-app/src/server/routes/trpc/[trpc].ts'
);
expect(hasTrpcClientFile).toBeFalsy();
expect(hasNoteFile).toBeFalsy();
expect(hasTrpcServerRoute).toBeFalsy();

const providesTrpcClient = tree
.read('apps/trpc-app/src/app/app.config.ts')
.includes('provideTrpcClient');
const injectsTrpcClient = tree
.read('apps/trpc-app/src/app/pages/analog-welcome.component.ts')
.includes('injectTrpcClient');
expect(providesTrpcClient).toBeFalsy();
expect(injectsTrpcClient).toBeFalsy();
};

describe('Nx latest, Angular 16.x', () => {
it('creates a default analogjs app in the source directory', async () => {
const analogAppName = 'analog';
const { config, tree } = await setup({ analogAppName });
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependenciesAngularV16_X(dependencies, devDependencies);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);
});

it('creates an analogjs app in the source directory with tailwind set up', async () => {
const analogAppName = 'tailwind-app';
const { config, tree } = await setup({
analogAppName,
addTailwind: true,
});
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependenciesAngularV16_X(dependencies, devDependencies);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);

verifyTailwindIsSetUp(tree, devDependencies);
});

it('creates an analogjs app in the source directory with trpc set up', async () => {
const analogAppName = 'trpc-app';
const { config, tree } = await setup({ analogAppName, addTRPC: true });
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependenciesAngularV16_X(dependencies, devDependencies);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);
verifyTrpcIsSetUp(tree, dependencies);
});
});

describe('Nx 16.0.0, Angular ~15.2.0', () => {
it('creates a default analogjs app in the source directory', async () => {
const analogAppName = 'analog';
const { config, tree } = await setup({ analogAppName }, '16.0.0');
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependenciesNxV16_0_0_AngularV15_X(
dependencies,
devDependencies
);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);
});

it('creates an analogjs app in the source directory with tailwind set up', async () => {
const analogAppName = 'tailwind-app';
const { config, tree } = await setup(
{
analogAppName,
addTailwind: true,
},
'16.0.0'
);
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependenciesNxV16_0_0_AngularV15_X(
dependencies,
devDependencies
);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);

verifyTailwindIsSetUp(tree, devDependencies);
});

it('creates an analogjs app in the source directory without trpc due to unsupported Nx version', async () => {
const analogAppName = 'trpc-app';
const { config, tree } = await setup(
{ analogAppName, addTRPC: true },
'16.0.0'
);
const { dependencies, devDependencies } = readJson(tree, 'package.json');

verifyCoreDependenciesNxV16_0_0_AngularV15_X(
dependencies,
devDependencies
);

verifyConfig(config, analogAppName);

verifyHomePageExists(tree, analogAppName);
verifyTrpcIsNotSetUp(tree, dependencies);
});
});

describe('Nx 15.1.0', () => {
test('should error out due to unsupported Nx version', async () => {
const analogAppName = 'analog';
await expect(setup({ analogAppName }, '15.1.0')).rejects.toThrow(
'Nx v15.2.0 or newer is required to install Analog'
);
});
});
});
29 changes: 23 additions & 6 deletions packages/nx-plugin/src/generators/app/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@ import {
Tree,
} from '@nx/devkit';
import { AnalogNxApplicationGeneratorOptions } from './schema';
import { major } from 'semver';
import { major, coerce } from 'semver';
import { getInstalledPackageVersion } from '../../utils/version-utils';
import { addAnalogProjectConfig } from './lib/add-analog-project-config';
import { addAnalogDependencies } from './lib/add-analog-dependencies';
import { initializeAngularWorkspace } from './lib/initialize-analog-workspace';
import { addFiles } from './lib/add-files';
import { addTailwindConfig } from './lib/add-tailwind-config';
import { addTRPC } from './lib/add-trpc';
import { addTrpc } from './lib/add-trpc';
import { addHomePage } from './lib/add-home-page';
import {
belowMinimumSupportedNxVersion,
belowMinimumSupportedNxtRPCVersion,
} from './versions/minimum-supported-versions';

export interface NormalizedOptions
extends AnalogNxApplicationGeneratorOptions,
Expand Down Expand Up @@ -73,16 +77,29 @@ export async function appGenerator(
throw new Error(stripIndents`Nx must be installed to execute this plugin`);
}

if (belowMinimumSupportedNxVersion(nxVersion)) {
throw new Error(
stripIndents`Nx v15.2.0 or newer is required to install Analog`
);
}

if (belowMinimumSupportedNxtRPCVersion(nxVersion) && options.addTRPC) {
console.warn(
'Nx v16.1.0 or newer is required to use tRPC with Analog. Skipping installation.'
);
options.addTRPC = false;
}

const normalizedOptions = normalizeOptions(tree, options, nxVersion);
const angularVersion = await initializeAngularWorkspace(
tree,
nxVersion,
normalizedOptions
);
const majorNxVersion = major(nxVersion);
const majorAngularVersion = major(angularVersion);
const majorAngularVersion = major(coerce(angularVersion));

await addAnalogDependencies(tree, majorAngularVersion, majorNxVersion);
await addAnalogDependencies(tree, nxVersion, angularVersion);

const {
projectRoot,
Expand Down Expand Up @@ -114,10 +131,10 @@ export async function appGenerator(
}

if (normalizedOptions.addTRPC) {
await addTRPC(
await addTrpc(
tree,
normalizedOptions.projectRoot,
majorAngularVersion,
nxVersion,
normalizedOptions
);
}
Expand Down

0 comments on commit acbdf14

Please sign in to comment.