Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80669 views
1
/**
2
* Copyright 2013 Facebook, Inc.
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
*
8
* http://www.apache.org/licenses/LICENSE-2.0
9
*
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*/
16
/*jslint proto:true*/
17
18
var inherits = require('util').inherits;
19
var node_path = path = require('path');
20
var fs = require('fs');
21
22
var Resource = require('./Resource');
23
24
/**
25
* Resource for package.json files
26
* @extends {Resource}
27
* @class
28
* @param {String} path path of the resource
29
* @param {Object} data source code of the resource
30
*/
31
function ProjectConfiguration(path, data) {
32
this.path = node_path.normalize(path);
33
this.id = path;
34
this.data = data;
35
}
36
inherits(ProjectConfiguration, Resource);
37
ProjectConfiguration.__proto__ = Resource;
38
39
ProjectConfiguration.prototype.type = 'ProjectConfiguration';
40
41
/**
42
* Returns haste specific prefix
43
* @return {String}
44
*/
45
ProjectConfiguration.prototype.getHastePrefix = function() {
46
return this.data.haste && this.data.haste.prefix !== undefined ?
47
this.data.haste.prefix :
48
path.basename(path.dirname(this.path));
49
};
50
51
/**
52
* Returns all roots affected by this package
53
* @return {Array.<String>}
54
*/
55
ProjectConfiguration.prototype.getHasteRoots = function() {
56
var dirname = path.dirname(this.path);
57
if (this.data.haste && this.data.haste.roots) {
58
return this.data.haste.roots.map(function(root) {
59
return path.join(dirname, root);
60
});
61
}
62
return [dirname];
63
};
64
65
/**
66
* The "Project Path" is the absolute path of the directory where "projects"
67
* live. Projects consist of a root folder `myProject` which contains a
68
* `package.json` file at `myProject/package.json`.
69
*
70
* If a `package.json` lives at /some/dir/myProject/package.json then, the
71
* inferred project dir would be /some/dir/
72
*
73
* Note that the project path is the directory *above* the module root.
74
*/
75
ProjectConfiguration.prototype.getInferredProjectPath = function() {
76
return path.resolve(this.path, '..', '..');
77
};
78
79
/**
80
* Simple convention for determining uniqueness of commonJS style modules.
81
*
82
* We don't try to "pre-resolve" any IDs here - To do this properly, we'd need a
83
* more complete picture of the resource map, that is only available at
84
* `postProcess` time. Our only job at this point is to come up with *something*
85
* to uniquely identify the 'JS' resource. The convention used here is to take
86
* the project (`package.json` "name" field) and append the path to the physical
87
* file.
88
*
89
* Attempting to choose an ID that has _meaning_ (by trying to pre-resolve
90
* `projectName/index.js` to `projectName` etc) is impossible at this time. An
91
* ambiguity occurs when we later discover that the `package.json` pointed the
92
* "main" module to another file. We couldn't possibly know which should claim
93
* the `projectName` ID until we've processed all resources. This is why
94
* dependency resolution can't *properly* happen until `postProcess`.
95
*
96
* By convention, the ID that we use to store commonJS resources is the
97
* `package.json` project name followed by the relative path from `package.json`
98
* to the file.
99
*
100
* > projectName/index.js
101
* > projectName/path/to.js
102
*
103
* A nice side effect of the particular convention chosen here, is when
104
* statically analyzing dependencies in `postProcess`:
105
*
106
* > require('x/y/z.js')
107
*
108
* requiring files by IDs always resolves to the module with that ID. Other
109
* conventions don't have this property. So if you can simply lookup 'JS'
110
* resource `'x/y/z.js'` and quickly get a hit, you don't need to fall back to
111
* more expensive path resolutions - which must analyze `package.json` files
112
* etc.
113
*
114
* Another loader will assign IDs to `@providesModule` JS files.
115
*
116
* Any resource "path" identifies the physical resource, but the resource ID
117
* doesn't yet identify a physical resource, until the "type" of resource is
118
* specified. You might have two resources, with the same ID and different
119
* types. For example {id: 'hello/hello.js'} does not identify a physical file,
120
* but {type: 'JS', id: 'hello/hello.js'} might.
121
*
122
* Two physical files might have the same module ID, but different types, as is
123
* the case with mock files.
124
*
125
* A:
126
* id: myProject/x.js
127
* path: /home/myProject/x.js
128
* type: 'JS'
129
*
130
* A-mock:
131
* id: myProject/x.js
132
* path: /home/myProject/x-mock.js
133
* type: 'JSMock'
134
*
135
* However, no two distinct files have the same resource ID and the same
136
* resource type and obviously no two distinct files have the same absolute
137
* "path".
138
*
139
*
140
* @param {String} filePath
141
* @return {String|null}
142
*/
143
ProjectConfiguration.prototype.resolveID = function(filePath) {
144
var hasteDirectories = this.getHasteRoots();
145
var prefix = this.getHastePrefix();
146
147
for (var i = 0; i < hasteDirectories.length; i++) {
148
var hasteDirectory = hasteDirectories[i];
149
if (filePath.indexOf(hasteDirectory + path.sep) === 0) {
150
var result = path.relative(hasteDirectory, filePath);
151
if (prefix) {
152
result = path.join(prefix, result);
153
}
154
return result;
155
}
156
}
157
158
return null;
159
};
160
161
module.exports = ProjectConfiguration;
162
163