Skip to content

Commit 7fc9e74

Browse files
committed
Pods / Pods + Classic Support
1 parent 683c5de commit 7fc9e74

21 files changed

Lines changed: 713 additions & 11 deletions

File tree

bin/ember-module-migrator

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// Provide a title to the process in `ps`
99
process.title = 'ember-module-migrator';
1010

11+
var fs = require('fs');
12+
1113
var Migrator = require('../lib');
1214

1315
var nopt = require("nopt");
@@ -20,10 +22,15 @@ var parsed = nopt(options);
2022

2123
var projectRoot = parsed['project-root'] || process.cwd();
2224
var projectName = parsed['project-name'];
25+
26+
var environment = require(projectRoot + '/config/environment.js');
27+
28+
var modulePrefix = environment.modulePrefix;
29+
var podModulePrefix = (environment.podModulePrefix || '').replace(modulePrefix + '\/', '');
30+
2331
if (!projectName) {
2432
// determine name from package.json in projectRoot
2533
try {
26-
var fs = require('fs');
2734
projectName = JSON.parse(fs.readFileSync(projectRoot + '/package.json', 'utf8')).name;
2835
} catch (e) {}
2936
}
@@ -32,6 +39,7 @@ var migrator = new Migrator({
3239
projectRoot: projectRoot,
3340
projectName: projectName,
3441
engine: parsed['engine'],
42+
podModulePrefix: podModulePrefix || undefined,
3543
verbose: true
3644
});
3745

lib/engines/classic/index.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ var MainFileInfo = require('./main-file-info');
1010
var MixinFileInfo = require('./mixin-file-info');
1111
var ConfigFileInfo = require('./config-file-info');
1212
var MiscFileInfo = require('./misc-file-info');
13+
var PodsSupport = require('../../utils/pods-support');
14+
var typeForPodFile = PodsSupport.typeForPodFile;
15+
var hasPodNamespace = PodsSupport.hasPodNamespace;
1316

1417
module.exports = {
1518
buildFor: function(sourceRelativePath, options) {
@@ -41,12 +44,14 @@ module.exports = {
4144

4245
topLevelDirectory = pathParts[1];
4346

44-
options.type = inflection.singularize(topLevelDirectory);
47+
var typeBasedOnFolder = inflection.singularize(topLevelDirectory);
48+
options.type = typeForPodFile(sourceRelativePath) || typeBasedOnFolder;
49+
4550

4651
if (ext === '.hbs') {
4752
options.type = 'template';
4853

49-
if (/^app\/(templates\/)?components/.test(sourceRelativePath)) {
54+
if (/^app\/(.+\/)?(templates\/)?components/.test(sourceRelativePath)) {
5055
return new ComponentTemplateFileInfo(options);
5156
} else {
5257
return new TemplateFileInfo(options);
@@ -65,12 +70,37 @@ module.exports = {
6570
}
6671
} else if (sourceRoot === 'tests') {
6772
var testType = pathParts[1];
73+
6874
var testSubjectType;
6975

7076
if (testType === 'unit' || testType === 'integration') {
77+
7178
options.base = 'src';
7279
options.testType = testType;
7380

81+
var podType = typeForPodFile(options.sourceRelativePath);
82+
var arePodsNamespaced = hasPodNamespace(options.podModulePrefix);
83+
84+
if (podType) {
85+
var fileName = pathParts[pathParts.length - 1];
86+
testSubjectType = fileName.replace(new RegExp('-test.js$'), '');
87+
options.testSubjectType = testSubjectType;
88+
options.type = testSubjectType + '-' + testType + '-test';
89+
90+
if (arePodsNamespaced) {
91+
topLevelDirectory = pathParts[3];
92+
93+
94+
return new TestFileInfo(options);
95+
}
96+
97+
topLevelDirectory = pathParts[3];
98+
99+
return new TestFileInfo(options);
100+
}
101+
102+
103+
74104
topLevelDirectory = pathParts[2];
75105
testSubjectType = inflection.singularize(topLevelDirectory);
76106
options.testSubjectType = testSubjectType;

lib/engines/classic/test-file-info.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
var path = require('path');
22
var ClassicFileInfo = require('./classic-file-info');
33
var calculateCollectionInfo = require('../../utils/calculate-collection-info');
4+
var inflection = require('inflection');
5+
var PodsSupport = require('../../utils/pods-support');
6+
var typeForPodFile = PodsSupport.typeForPodFile;
7+
var hasPodNamespace = PodsSupport.hasPodNamespace;
48

59
var TestFileInfo = ClassicFileInfo.extend({
610
populate: function() {
@@ -27,12 +31,43 @@ var TestFileInfo = ClassicFileInfo.extend({
2731
var pathParts = this.sourceRelativePath.split('/');
2832
var testTypeFolder = pathParts[1];
2933
var typeFolder = pathParts[2];
34+
var typeOfTest = '';
3035

31-
var strippedRelativePath = this.sourceRelativePath
36+
var podType = typeForPodFile(this.sourceRelativePath);
37+
if (podType) {
38+
var fileName = pathParts[pathParts.length - 1];
39+
typeOfTest = fileName.replace(new RegExp('-test.js$'), '');
40+
typeFolder = inflection.pluralize(typeOfTest);
41+
}
42+
43+
var strippedRelativePath;
44+
45+
if (podType) {
46+
if (!hasPodNamespace(this.podModulePrefix)) {
47+
// pods without namespace
48+
strippedRelativePath = this.sourceRelativePath
49+
.replace(new RegExp('^' + this.sourceRoot + '/' + testTypeFolder + '/(' + typeFolder + '/)?'), '') // remove leading type dir
50+
.replace(new RegExp('-test.js$'), '') // remove extension
51+
.replace(new RegExp('/' + typeOfTest + '$'), ''); // remove type name if pods
52+
} else {
53+
// pods with namespace
54+
var pathRootRegex = new RegExp(this.podModulePrefix + '\/');
55+
strippedRelativePath = this.sourceRelativePath
56+
.replace(pathRootRegex, '') // don't care if the top directory is pods
3257
.replace(new RegExp('^' + this.sourceRoot + '/' + testTypeFolder + '/(' + typeFolder + '/)?'), '') // remove leading type dir
33-
.replace(new RegExp('-test.js$'), ''); // remove extension
58+
.replace(new RegExp('-test.js$'), '') // remove extension
59+
.replace(new RegExp('/' + typeOfTest + '$'), ''); // remove type name if pods
60+
}
61+
} else {
62+
// classic
63+
strippedRelativePath = this.sourceRelativePath
64+
.replace(pathRootRegex, '') // don't care if the top directory is pods
65+
.replace(new RegExp('^' + this.sourceRoot + '/' + testTypeFolder + '/(' + typeFolder + '/)?'), '') // remove leading type dir
66+
.replace(new RegExp('-test.js$'), ''); // remove extension
67+
}
3468

3569
var parts = strippedRelativePath.split('/');
70+
3671
this.name = parts.pop();
3772
this.namespace = parts.join('/');
3873
},

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ var Engine = CoreObject.extend({
144144
var fileInfo = this.engine.buildFor(path, {
145145
projectRoot: this.projectRoot,
146146
projectName: this.projectName,
147+
podModulePrefix: this.podModulePrefix !== undefined ? this.podModulePrefix : 'pods',
147148
_fileInfoCollection: this._fileInfoCollection
148149
});
149150

lib/models/file-info.js

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ var isTypeInSingleTypeCollection = require('../utils/is-type-in-single-type-coll
77
var defaultTypeForCollection = require('../utils/default-type-for-collection');
88
var calculateCollectionInfo = require('../utils/calculate-collection-info');
99
var importDeclarationsTransform = require('../transforms/import-declarations');
10+
var inflection = require('inflection');
11+
var PodsSupport = require('../utils/pods-support');
12+
var typeForPodFile = PodsSupport.typeForPodFile;
13+
var hasPodNamespace = PodsSupport.hasPodNamespace;
1014

1115
var FileInfo = CoreObject.extend({
1216
type: 'FileInfo',
@@ -17,6 +21,7 @@ var FileInfo = CoreObject.extend({
1721
var options = _options || {};
1822
this.options = options;
1923
this.projectRoot = options.projectRoot;
24+
this.podModulePrefix = options.podModulePrefix;
2025

2126
this.sourceRelativePath = options.sourceRelativePath;
2227
this.type = options.type;
@@ -70,10 +75,70 @@ var FileInfo = CoreObject.extend({
7075
var pathParts = this.sourceRelativePath.split('/');
7176
var typeFolder = pathParts[1];
7277

73-
var strippedRelativePath = this.sourceRelativePath
74-
.replace(new RegExp('^' + this.sourceRoot + '/' + typeFolder + '/'), '') // remove leading type dir
78+
79+
80+
var podType = typeForPodFile(this.sourceRelativePath);
81+
var arePodsNamespaced = hasPodNamespace(this.podModulePrefix);
82+
83+
var strippedRelativePath;
84+
var pathRootRegex;
85+
var fileName;
86+
var type;
87+
88+
if (typeFolder === this.podModulePrefix) {
89+
if (pathParts[2] === 'components') {
90+
typeFolder = 'components';
91+
} else {
92+
fileName = pathParts[pathParts.length - 1];
93+
type = fileName.split('.')[0];
94+
typeFolder = inflection.pluralize(type);
95+
}
96+
}
97+
98+
// default/classic/namespaced-pods
99+
pathRootRegex = new RegExp('(app\/)?' + this.podModulePrefix + '\/(components\/)?');
100+
101+
strippedRelativePath = this.sourceRelativePath
102+
.replace(pathRootRegex, '') // don't care if path begins with pods
103+
.replace(new RegExp('^' + this.sourceRoot + '/' + typeFolder + '/'), '') // remove leading type dir
104+
.replace(new RegExp(this.ext + '$'), '') // remove extension
105+
.replace(new RegExp('/' + this.type + '$'), ''); // remove trailing type
106+
107+
108+
if (!arePodsNamespaced) {
109+
if (podType) {
110+
fileName = pathParts[pathParts.length - 1];
111+
type = fileName.split('.')[0];
112+
typeFolder = inflection.pluralize(type);
113+
114+
pathRootRegex = new RegExp('(app\/)?');
115+
var podTypeRegex = new RegExp('(components\/)?');
116+
117+
strippedRelativePath = this.sourceRelativePath
118+
.replace(pathRootRegex, '')
119+
.replace(podTypeRegex, '')
120+
.replace(new RegExp(typeFolder + '/'), '') // remove leading type dir
75121
.replace(new RegExp(this.ext + '$'), '') // remove extension
76122
.replace(new RegExp('/' + this.type + '$'), ''); // remove trailing type
123+
}
124+
125+
// for other files (adapters, serializers, helpers, initializers, etc)
126+
if (type === undefined){
127+
pathRootRegex = new RegExp('(app\/)?');
128+
type = pathParts[1];
129+
fileName = pathParts[pathParts.length - 1];
130+
typeFolder = inflection.pluralize(type);
131+
132+
133+
strippedRelativePath = this.sourceRelativePath
134+
.replace(pathRootRegex, '')
135+
.replace(new RegExp(type + '/'), '')
136+
.replace(new RegExp('^' + this.sourceRoot + '/' + typeFolder + '/'), '') // remove leading type dir
137+
.replace(new RegExp(this.ext + '$'), '') // remove extension
138+
.replace(new RegExp('/' + this.type), ''); // remove trailing type
139+
140+
}
141+
}
77142

78143
var parts = strippedRelativePath.split('/');
79144
this.name = parts.pop();
@@ -213,7 +278,7 @@ Object.defineProperty(FileInfo.prototype, 'destRelativePath', {
213278
}
214279
var destRelativePath;
215280

216-
if (this.shouldUseDotFormNaming()) {
281+
if (this.shouldUseDotFormNaming() && this.type !== 'component') {
217282
destRelativePath = path.join(
218283
baseRelativePath,
219284
this.namespace,

lib/utils/pods-support.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
const podFileTypes = [
3+
'component',
4+
'template',
5+
'controller',
6+
'route',
7+
'model',
8+
'adapter',
9+
'serializer'
10+
];
11+
12+
function typeForPodFile(path) {
13+
const parts = path.split('/');
14+
const fileName = parts[parts.length - 1];
15+
16+
const type = podFileTypes.find(f => fileName.startsWith(f));
17+
18+
return type;
19+
}
20+
21+
function hasPodNamespace(namespace) {
22+
return (
23+
namespace !== undefined &&
24+
namespace !== null &&
25+
namespace !== ''
26+
);
27+
}
28+
29+
module.exports = {
30+
typeForPodFile,
31+
hasPodNamespace
32+
};

test/engines/classic-test.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,20 @@ describe('classic engine', function() {
145145
var fixturePath = path.join(fixturesPath, entry);
146146
var input = require(fixturePath + '/input');
147147
var expected = require(fixturePath + '/output');
148+
var migratorConfig = {};
149+
try {
150+
migratorConfig = require(fixturePath + '/config');
151+
} catch (e) {
152+
// fixture uses default config...
153+
}
148154

149155
fixturify.writeSync(tmpPath, input);
150-
151-
var engine = new Migrator({
156+
var migratorOptions = Object.assign({}, {
152157
projectRoot: tmpPath,
153158
projectName: 'my-app'
154-
});
159+
}, migratorConfig);
160+
161+
var engine = new Migrator(migratorOptions);
155162

156163
return engine.processFiles()
157164
.then(function() {

test/fixtures/directory-cleanup/input.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ module.exports = {
77
'templates': {
88
'.gitkeep': '',
99
'post.hbs': 'post route template'
10+
},
11+
'pods': {
12+
'posts': {
13+
'.gitkeep': ''
14+
}
1015
}
1116
},
1217
'tests': {

0 commit comments

Comments
 (0)