Skip to content

Commit ced1106

Browse files
committed
feat(commerce): schematic generates daff.json
1 parent af3b9d4 commit ced1106

3 files changed

Lines changed: 227 additions & 1 deletion

File tree

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import { Tree } from '@angular-devkit/schematics';
2+
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
3+
import * as path from 'path';
4+
import { firstValueFrom } from 'rxjs';
5+
6+
import {
7+
DEFAULT_MAGENTO_VERSION,
8+
addBuildCondition,
9+
createDaffJson,
10+
} from './daff-config';
11+
import { NgAddOptions } from '../../schema';
12+
13+
const collectionPath = path.join(__dirname, '../../../collection.json');
14+
15+
const buildAngularJson = (projectName: string) => ({
16+
version: 1,
17+
newProjectRoot: 'projects',
18+
projects: {
19+
[projectName]: {
20+
projectType: 'application',
21+
root: `projects/${projectName}`,
22+
sourceRoot: `projects/${projectName}/src`,
23+
architect: {
24+
build: {
25+
builder: '@angular-devkit/build-angular:application',
26+
options: {},
27+
configurations: {
28+
production: {},
29+
},
30+
},
31+
},
32+
},
33+
},
34+
});
35+
36+
describe('createDaffJson', () => {
37+
let tree: Tree;
38+
const projectName = 'test-app';
39+
40+
beforeEach(() => {
41+
tree = Tree.empty();
42+
});
43+
44+
it('creates daff.json with the default magento version when driver is magento', () => {
45+
const options: NgAddOptions = { project: projectName, driver: 'magento' };
46+
const rule = createDaffJson(options, projectName);
47+
48+
rule(tree, <any>{ logger: { warn: () => undefined }});
49+
50+
expect(tree.exists('daff.json')).toBe(true);
51+
const body = JSON.parse(tree.read('daff.json')?.toString() ?? '');
52+
expect(body.projects[projectName].drivers.magento).toBe(DEFAULT_MAGENTO_VERSION);
53+
});
54+
55+
it('creates daff.json for the demo driver', () => {
56+
const options: NgAddOptions = { project: projectName, driver: 'demo' };
57+
const rule = createDaffJson(options, projectName);
58+
59+
rule(tree, <any>{ logger: { warn: () => undefined }});
60+
61+
expect(tree.exists('daff.json')).toBe(true);
62+
const body = JSON.parse(tree.read('daff.json')?.toString() ?? '');
63+
expect(body.projects[projectName].drivers.magento).toBe(DEFAULT_MAGENTO_VERSION);
64+
});
65+
66+
it('does not create daff.json for shopify or in-memory drivers', () => {
67+
for (const driver of <const>['shopify', 'in-memory']) {
68+
const scopedTree = Tree.empty();
69+
const options: NgAddOptions = { project: projectName, driver };
70+
const rule = createDaffJson(options, projectName);
71+
72+
rule(scopedTree, <any>{ logger: { warn: () => undefined }});
73+
74+
expect(scopedTree.exists('daff.json')).toBe(false);
75+
}
76+
});
77+
78+
it('leaves an existing daff.json untouched', () => {
79+
const existing = '{"projects":{"other":{"drivers":{"magento":"2.4.1"}}}}\n';
80+
tree.create('daff.json', existing);
81+
const options: NgAddOptions = { project: projectName, driver: 'magento' };
82+
const rule = createDaffJson(options, projectName);
83+
84+
rule(tree, <any>{ logger: { warn: () => undefined }});
85+
86+
expect(tree.read('daff.json')?.toString()).toBe(existing);
87+
});
88+
});
89+
90+
describe('addBuildCondition', () => {
91+
const projectName = 'test-app';
92+
let runner: SchematicTestRunner;
93+
let tree: Tree;
94+
95+
beforeEach(() => {
96+
runner = new SchematicTestRunner('schematics', collectionPath);
97+
tree = Tree.empty();
98+
tree.create('/angular.json', JSON.stringify(buildAngularJson(projectName), null, 2));
99+
});
100+
101+
it('adds the magento condition to the production build configuration', async () => {
102+
const options: NgAddOptions = { project: projectName, driver: 'magento' };
103+
const rule = addBuildCondition(options, projectName);
104+
105+
const resultTree = await firstValueFrom(runner.callRule(rule, tree));
106+
107+
const angular = JSON.parse(resultTree.read('/angular.json')?.toString() ?? '');
108+
const conditions = angular.projects[projectName].architect.build.configurations.production.conditions;
109+
expect(conditions).toEqual([`magento-${DEFAULT_MAGENTO_VERSION}`]);
110+
});
111+
112+
it('adds the magento condition for the demo driver', async () => {
113+
const options: NgAddOptions = { project: projectName, driver: 'demo' };
114+
const rule = addBuildCondition(options, projectName);
115+
116+
const resultTree = await firstValueFrom(runner.callRule(rule, tree));
117+
118+
const angular = JSON.parse(resultTree.read('/angular.json')?.toString() ?? '');
119+
const conditions = angular.projects[projectName].architect.build.configurations.production.conditions;
120+
expect(conditions).toEqual([`magento-${DEFAULT_MAGENTO_VERSION}`]);
121+
});
122+
123+
it('leaves conditions untouched for shopify or in-memory drivers', async () => {
124+
for (const driver of <const>['shopify', 'in-memory']) {
125+
const scopedTree = Tree.empty();
126+
scopedTree.create('/angular.json', JSON.stringify(buildAngularJson(projectName), null, 2));
127+
const options: NgAddOptions = { project: projectName, driver };
128+
const rule = addBuildCondition(options, projectName);
129+
130+
const resultTree = await firstValueFrom(runner.callRule(rule, scopedTree));
131+
132+
const angular = JSON.parse(resultTree.read('/angular.json')?.toString() ?? '');
133+
expect(angular.projects[projectName].architect.build.configurations.production.conditions).toBeUndefined();
134+
}
135+
});
136+
137+
it('deduplicates when the condition is already present', async () => {
138+
const baseline = buildAngularJson(projectName);
139+
(<any>baseline.projects[projectName].architect.build.configurations.production).conditions = [
140+
`magento-${DEFAULT_MAGENTO_VERSION}`,
141+
];
142+
tree.overwrite('/angular.json', JSON.stringify(baseline, null, 2));
143+
144+
const options: NgAddOptions = { project: projectName, driver: 'magento' };
145+
const rule = addBuildCondition(options, projectName);
146+
147+
const resultTree = await firstValueFrom(runner.callRule(rule, tree));
148+
149+
const angular = JSON.parse(resultTree.read('/angular.json')?.toString() ?? '');
150+
const conditions = angular.projects[projectName].architect.build.configurations.production.conditions;
151+
expect(conditions).toEqual([`magento-${DEFAULT_MAGENTO_VERSION}`]);
152+
});
153+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {
2+
Rule,
3+
SchematicContext,
4+
Tree,
5+
} from '@angular-devkit/schematics';
6+
import { updateWorkspace } from '@schematics/angular/utility/workspace';
7+
import chalk from 'chalk';
8+
9+
import { NgAddOptions } from '../../schema';
10+
11+
export const DEFAULT_MAGENTO_VERSION = '2.4.3';
12+
13+
const DAFF_JSON_PATH = 'daff.json';
14+
15+
const shouldScaffoldDaffConfig = (options: NgAddOptions): boolean =>
16+
options.driver === 'magento' || options.driver === 'demo';
17+
18+
export const createDaffJson = (options: NgAddOptions, projectName: string): Rule =>
19+
(tree: Tree, context: SchematicContext) => {
20+
if (!shouldScaffoldDaffConfig(options)) {
21+
return tree;
22+
}
23+
24+
if (tree.exists(DAFF_JSON_PATH)) {
25+
context.logger.warn(
26+
chalk.yellow(`[WARN] daff.json already exists at the workspace root; leaving it unchanged.`),
27+
);
28+
return tree;
29+
}
30+
31+
const body = {
32+
projects: {
33+
[projectName]: {
34+
drivers: {
35+
magento: DEFAULT_MAGENTO_VERSION,
36+
},
37+
},
38+
},
39+
};
40+
41+
tree.create(DAFF_JSON_PATH, JSON.stringify(body, null, 2) + '\n');
42+
return tree;
43+
};
44+
45+
export const addBuildCondition = (options: NgAddOptions, projectName: string): Rule => {
46+
if (!shouldScaffoldDaffConfig(options)) {
47+
return (tree: Tree) => tree;
48+
}
49+
50+
const workspaceRule = updateWorkspace((workspace) => {
51+
const project = workspace.projects.get(projectName);
52+
const build = project?.targets.get('build');
53+
if (!build) {
54+
return;
55+
}
56+
57+
build.configurations ??= {};
58+
const production = <{ conditions?: string[] }>(build.configurations.production ??= {});
59+
const cond = `magento-${DEFAULT_MAGENTO_VERSION}`;
60+
production.conditions = Array.from(new Set([...(production.conditions ?? []), cond]));
61+
});
62+
63+
return <Rule><unknown>workspaceRule;
64+
};

tools/schematics/ng-add/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
88
import { getWorkspace } from '@schematics/angular/utility/workspace';
99
import chalk from 'chalk';
1010

11+
import {
12+
addBuildCondition,
13+
createDaffJson,
14+
} from './generators/daff-config/daff-config';
1115
import { addDependenciesToPackageJson } from './generators/dependencies';
1216
import { initAppProviders } from './generators/providers/init';
1317
import { initAppRouting } from './generators/routing/init';
@@ -31,7 +35,8 @@ export function ngAdd(options: NgAddOptions): Rule {
3135
}
3236

3337
const workspace = await getWorkspace(tree);
34-
const project = workspace.projects.get(options.project || <string>workspace.extensions.defaultProject);
38+
const projectName = options.project || <string>workspace.extensions.defaultProject;
39+
const project = workspace.projects.get(projectName);
3540

3641
if (!project) {
3742
throw new Error(`Project "${options.project}" not found.`);
@@ -53,6 +58,10 @@ export function ngAdd(options: NgAddOptions): Rule {
5358
// Add template files for demo components
5459
rules.push(addTemplateFiles(options, project));
5560

61+
// Scaffold daff.json and pre-populate angular.json build conditions (magento only)
62+
rules.push(createDaffJson(options, projectName));
63+
rules.push(addBuildCondition(options, projectName));
64+
5665
// Schedule package installation
5766
if (!options.skipPackageJson) {
5867
context.addTask(new NodePackageInstallTask());

0 commit comments

Comments
 (0)