Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit 2943188

Browse files
authored
feat(deep-linking): upgrade script to generate NgModules for pages with @deeplink decorator
1 parent 08534d7 commit 2943188

File tree

3 files changed

+201
-2
lines changed

3 files changed

+201
-2
lines changed

src/deep-linking/util.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,8 @@ export function addDeepLinkArgumentToAppNgModule(appNgModuleFileContent: string,
353353
return updatedFileContent;
354354
}
355355

356-
export function generateDefaultDeepLinkNgModuleContent(filePath: string, className: string) {
357-
const importFrom = basename(filePath, '.ts');
356+
export function generateDefaultDeepLinkNgModuleContent(pageFilePath: string, className: string) {
357+
const importFrom = basename(pageFilePath, '.ts');
358358

359359
return `
360360
import { NgModule } from '@angular/core';
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import * as fs from 'fs';
2+
import { join } from 'path';
3+
4+
import * as upgradeScript from './add-default-ngmodules';
5+
import * as deeplinkUtils from '../deep-linking/util';
6+
import { FileCache } from '../util/file-cache';
7+
import * as globUtil from '../util/glob-util';
8+
import * as helpers from '../util/helpers';
9+
10+
describe('add default ngmodules upgrade script', () => {
11+
describe('getTsFilePaths', () => {
12+
it('should return a list of absolute file paths', () => {
13+
const srcDirectory = join('Users', 'noone', 'this', 'path', 'is', 'fake', 'src');
14+
const context = {
15+
srcDir: srcDirectory
16+
};
17+
18+
const knownFileOne = join(srcDirectory, 'pages', 'page-one', 'page-one.ts');
19+
const knownFileTwo = join(srcDirectory, 'pages', 'page-two', 'page-two.ts');
20+
const knownFileThree = join(srcDirectory, 'pages', 'page-three', 'page-three.ts');
21+
const knownFileFour = join(srcDirectory, 'util', 'some-util.ts');
22+
const globResults = [
23+
{ absolutePath: knownFileOne},
24+
{ absolutePath: knownFileTwo},
25+
{ absolutePath: knownFileThree},
26+
{ absolutePath: knownFileFour},
27+
];
28+
spyOn(globUtil, globUtil.globAll.name).and.returnValue(Promise.resolve(globResults));
29+
const promise = upgradeScript.getTsFilePaths(context);
30+
31+
return promise.then((filePaths: string[]) => {
32+
expect(filePaths.length).toEqual(4);
33+
expect(filePaths[0]).toEqual(knownFileOne);
34+
expect(filePaths[1]).toEqual(knownFileTwo);
35+
expect(filePaths[2]).toEqual(knownFileThree);
36+
expect(filePaths[3]).toEqual(knownFileFour);
37+
});
38+
});
39+
});
40+
41+
describe('readTsFiles', () => {
42+
it('should read the ts files', () => {
43+
const context = {
44+
fileCache: new FileCache()
45+
};
46+
const srcDirectory = join('Users', 'noone', 'this', 'path', 'is', 'fake', 'src');
47+
const knownFileOne = join(srcDirectory, 'pages', 'page-one', 'page-one.ts');
48+
const knownFileTwo = join(srcDirectory, 'pages', 'page-two', 'page-two.ts');
49+
const knownFileThree = join(srcDirectory, 'pages', 'page-three', 'page-three.ts');
50+
const knownFileFour = join(srcDirectory, 'util', 'some-util.ts');
51+
52+
const fileList = [knownFileOne, knownFileTwo, knownFileThree, knownFileFour];
53+
54+
spyOn(helpers, helpers.readFileAsync.name).and.callFake((filePath: string) => {
55+
// just set the file content to the path name + 'content' to keep things simple
56+
return Promise.resolve(filePath + 'content');
57+
});
58+
59+
const promise = upgradeScript.readTsFiles(context, fileList);
60+
61+
return promise.then(() => {
62+
// the files should be cached now
63+
const fileOne = context.fileCache.get(knownFileOne);
64+
expect(fileOne.content).toEqual(knownFileOne + 'content');
65+
66+
const fileTwo = context.fileCache.get(knownFileTwo);
67+
expect(fileTwo.content).toEqual(knownFileTwo + 'content');
68+
69+
const fileThree = context.fileCache.get(knownFileThree);
70+
expect(fileThree.content).toEqual(knownFileThree + 'content');
71+
72+
const fileFour = context.fileCache.get(knownFileFour);
73+
expect(fileFour.content).toEqual(knownFileFour + 'content');
74+
});
75+
});
76+
});
77+
78+
describe('generateAndWriteNgModules', () => {
79+
it('should generate NgModules for only the pages with deeplink decorator AND if the module.ts file doesnt exist', () => {
80+
const srcDirectory = join('Users', 'noone', 'this', 'path', 'is', 'fake', 'src');
81+
const knownFileOne = join(srcDirectory, 'pages', 'page-one', 'page-one.ts');
82+
const knownFileTwo = join(srcDirectory, 'pages', 'page-two', 'page-two.ts');
83+
const knownFileThree = join(srcDirectory, 'pages', 'page-three', 'page-three.ts');
84+
const knownFileThreeModule = join(srcDirectory, 'pages', 'page-three', 'page-three.module.ts');
85+
const knownFileFour = join(srcDirectory, 'util', 'some-util.ts');
86+
const knownFileFive = join(srcDirectory, 'pages', 'page-three', 'provider.ts');
87+
const knownFileSix = join(srcDirectory, 'modals', 'modal-one', 'modal-one.ts');
88+
89+
const context = {
90+
fileCache: new FileCache()
91+
};
92+
93+
context.fileCache.set(knownFileOne, { path: knownFileOne, content: getClassContent('PageOne', 'page-one')});
94+
context.fileCache.set(knownFileTwo, { path: knownFileTwo, content: getClassContent('PageTwo', 'page-two')});
95+
context.fileCache.set(knownFileThree, { path: knownFileThree, content: getClassContent('PageThree', 'page-three')});
96+
context.fileCache.set(knownFileThreeModule, { path: knownFileThreeModule, content: deeplinkUtils.generateDefaultDeepLinkNgModuleContent(knownFileThree, 'PageThree')});
97+
context.fileCache.set(knownFileFour, { path: knownFileFour, content: `${knownFileFour} content`});
98+
context.fileCache.set(knownFileFive, { path: knownFileFive, content: `${knownFileFive} content`});
99+
context.fileCache.set(knownFileSix, { path: knownFileSix, content: getClassContent('ModalOne', 'modal-one')});
100+
101+
const ngModuleFileExtension = '.module.ts';
102+
103+
spyOn(helpers, helpers.getStringPropertyValue.name).and.returnValue(ngModuleFileExtension);
104+
const fsSpy = spyOn(fs, 'writeFileSync');
105+
106+
upgradeScript.generateAndWriteNgModules(context.fileCache);
107+
108+
expect(fsSpy.calls.count()).toEqual(3);
109+
expect(fsSpy.calls.argsFor(0)[0]).toEqual(helpers.changeExtension(knownFileOne, ngModuleFileExtension));
110+
expect(fsSpy.calls.argsFor(0)[1]).toEqual(deeplinkUtils.generateDefaultDeepLinkNgModuleContent(knownFileOne, 'PageOne'));
111+
112+
expect(fsSpy.calls.argsFor(1)[0]).toEqual(helpers.changeExtension(knownFileTwo, ngModuleFileExtension));
113+
expect(fsSpy.calls.argsFor(1)[1]).toEqual(deeplinkUtils.generateDefaultDeepLinkNgModuleContent(knownFileTwo, 'PageTwo'));
114+
115+
expect(fsSpy.calls.argsFor(2)[0]).toEqual(helpers.changeExtension(knownFileSix, ngModuleFileExtension));
116+
expect(fsSpy.calls.argsFor(2)[1]).toEqual(deeplinkUtils.generateDefaultDeepLinkNgModuleContent(knownFileSix, 'ModalOne'));
117+
});
118+
});
119+
});
120+
121+
function getClassContent(className: string, folderName: string) {
122+
return `
123+
import { Component } from '@angular/core';
124+
import { DeepLink, NavController } from 'ionic-angular';
125+
126+
@DeepLink()
127+
@Component({
128+
selector: '${folderName}',
129+
templateUrl: './${folderName}.html'
130+
})
131+
export class ${className} {
132+
133+
constructor(public navCtrl: NavController) {}
134+
135+
}
136+
`;
137+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { writeFileSync } from 'fs';
2+
import { join } from 'path';
3+
4+
import { generateDefaultDeepLinkNgModuleContent, getDeepLinkDecoratorContentForSourceFile, getNgModulePathFromCorrespondingPage } from '../deep-linking/util';
5+
import { generateContext } from '../util/config';
6+
import * as Constants from '../util/constants';
7+
import { FileCache } from '../util/file-cache';
8+
import { globAll, GlobResult } from '../util/glob-util';
9+
import { changeExtension, getStringPropertyValue, readFileAsync } from '../util/helpers';
10+
import { BuildContext, File } from '../util/interfaces';
11+
12+
import { getTypescriptSourceFile } from '../util/typescript-utils';
13+
14+
export function getTsFilePaths(context: BuildContext) {
15+
const tsFileGlobString = join(context.srcDir, '**', '*.ts');
16+
return globAll([tsFileGlobString]).then((results: GlobResult[]) => {
17+
return results.map(result => result.absolutePath);
18+
});
19+
}
20+
21+
export function readTsFiles(context: BuildContext, tsFilePaths: string[]) {
22+
const promises = tsFilePaths.map(tsFilePath => {
23+
const promise = readFileAsync(tsFilePath);
24+
promise.then((fileContent: string) => {
25+
context.fileCache.set(tsFilePath, { path: tsFilePath, content: fileContent});
26+
});
27+
return promise;
28+
});
29+
return Promise.all(promises);
30+
}
31+
32+
export function generateAndWriteNgModules(fileCache: FileCache) {
33+
fileCache.getAll().forEach(file => {
34+
const sourceFile = getTypescriptSourceFile(file.path, file.content);
35+
const deepLinkDecoratorData = getDeepLinkDecoratorContentForSourceFile(sourceFile);
36+
if (deepLinkDecoratorData) {
37+
// we have a valid DeepLink decorator
38+
const correspondingNgModulePath = getNgModulePathFromCorrespondingPage(file.path);
39+
const ngModuleFile = fileCache.get(correspondingNgModulePath);
40+
if (!ngModuleFile) {
41+
// the ngModule file does not exist, so go ahead and create a default one
42+
const defaultNgModuleContent = generateDefaultDeepLinkNgModuleContent(file.path, deepLinkDecoratorData.className);
43+
const ngModuleFilePath = changeExtension(file.path, getStringPropertyValue(Constants.ENV_NG_MODULE_FILE_NAME_SUFFIX));
44+
writeFileSync(ngModuleFilePath, defaultNgModuleContent);
45+
}
46+
}
47+
});
48+
}
49+
50+
function run() {
51+
const context = generateContext();
52+
53+
// find out what files to read
54+
return getTsFilePaths(context).then((filePaths: string[]) => {
55+
// read the files
56+
return readTsFiles(context, filePaths);
57+
}).then(() => {
58+
generateAndWriteNgModules(context.fileCache);
59+
});
60+
}
61+
62+
run();

0 commit comments

Comments
 (0)