Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 115 additions & 58 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,115 +1,172 @@
var resolve = require('resolve')
var path = require('path')
var assign = require('object-assign')
var fs = require('fs')
const resolve = require('resolve');
const path = require('path');
const fs = require('fs');

const notNodeModuleRe = /^(\.|\/)/
const clientRe = /\/client(\/|$)/
const serverRe = /\/server(\/|$)/
const packageNameRe = /name:[\s]*["']([a-z0-9A-Z\:\-_]+)["']/;
exports.interfaceVersion = 2

var notNodeModuleRe = /^(\.|\/)/
var clientRe = /\/client(\/|$)/
var serverRe = /\/server(\/|$)/

exports.interfaceVersion = 2
let packageCacheTimeout = 5 * 60 * 1000;
let cacheUpdatedAt = new Date(0);
let packageCache = [];
let cachedMeteorRoot;
let localPackageCache = [];

exports.resolve = function (source, file, config) {

const meteorDir = config && config.meteorDir;
if (resolve.isCore(source)) return { found: true, path: null }
if (resolve.isCore(source)) {
return { found: true, path: null }
}

if (source.startsWith('meteor/')) {
var meteorRoot = findMeteorRoot(file, meteorDir)
return resolveMeteorPackage(source, meteorRoot)
if (!cachedMeteorRoot) {
cachedMeteorRoot = findMeteorRoot(file, meteorDir);
}
return resolveMeteorPackage(source, cachedMeteorRoot);
}

var meteorSource = source
let meteorSource = source;
if (source.startsWith('/')) {
var meteorRoot = findMeteorRoot(file, meteorDir)
meteorSource = path.resolve(meteorRoot, source.substr(1))
const meteorRoot = findMeteorRoot(file, meteorDir);
meteorSource = path.resolve(meteorRoot, source.substr(1));
}

var fileUsingSlash = file.split(path.sep).join('/')
const fileUsingSlash = file.split(path.sep).join('/')
if (!isNodeModuleImport(source) && (isClientInServer(source, fileUsingSlash) || isServerInClient(source, fileUsingSlash))) {
return { found: false }
return { found: false };
}

try {
return { found: true, path: resolve.sync(meteorSource, opts(file, config)) }
return { found: true, path: resolve.sync(meteorSource, opts(file, config)) };
} catch (err) {
return { found: false }
return { found: false };
}
}

function opts(file, config) {
return assign({},
return Object.assign({},
config,
{
// path.resolve will handle paths relative to CWD
basedir: path.dirname(path.resolve(file)),
packageFilter: packageFilter,
})
});
}

function packageFilter(pkg, path, relativePath) {
if (pkg['jsnext:main']) {
pkg['main'] = pkg['jsnext:main']
pkg['main'] = pkg['jsnext:main'];
}
return pkg
return pkg;
}

function findMeteorRoot(start, meteorDir) {
start = start || module.parent.filename
function findMeteorRoot(start, meteorDir = '') {
meteorDir = meteorDir || '';

start = start || module.parent.filename;

if (typeof start === 'string') {
if (start[start.length-1] !== path.sep) {
start += path.sep
if (start[start.length - 1] !== path.sep) {
start += path.sep;
}
start = start.split(path.sep)
start = start.split(path.sep);
}
if(!start.length) {
throw new Error('.meteor not found in path')

if (!start.length) {
throw new Error('.meteor not found in path');
}
start.pop()
var dir = start.join(path.sep)
start.pop();
const dir = start.join(path.sep);

try {
fs.statSync(path.join(dir, meteorDir, '.meteor'))
return path.join(dir, meteorDir)
} catch (e) {}
return findMeteorRoot(start, meteorDir)
fs.statSync(path.join(dir, meteorDir, '.meteor'));
return path.join(dir, meteorDir);
} catch (e) { }
return findMeteorRoot(start, meteorDir);
}

function isNodeModuleImport(source) {
return !notNodeModuleRe.test(source)
return !notNodeModuleRe.test(source);
}

function isClientInServer(source, file) {
return serverRe.test(source) && clientRe.test(file)
return serverRe.test(source) && clientRe.test(file);
}

function isServerInClient(source, file) {
return clientRe.test(source) && serverRe.test(file)
return clientRe.test(source) && serverRe.test(file);
}

function resolveMeteorPackage(source, meteorRoot) {
try {
var package = source.split('/')[1]
var packageCheckFile = package.indexOf(':') !== -1 ?
getPackageFile(meteorRoot) :
getVersionFile(meteorRoot)
var found = new RegExp('^' + package + '(?:@.*?)?(?:[ \s\t]*#.*)?$', 'm').test(packageCheckFile)
return found ?
{ found: found, path: null } :
{ found: false }
} catch (e) {
return { found: false }
}
function isCacheOutdated() {
return Date.now() - cacheUpdatedAt.getTime() > packageCacheTimeout;
}

function getVersionFile(meteorRoot) {
var filePath = path.join(meteorRoot, '.meteor', 'versions')
var fileBuffer = fs.readFileSync(filePath)
return fileBuffer.toString()
const filePath = path.join(meteorRoot, '.meteor', 'versions');
const fileBuffer = fs.readFileSync(filePath);
return fileBuffer.toString();
}

function getPackageFile(meteorRoot) {
var filePath = path.join(meteorRoot, '.meteor', 'packages')
var fileBuffer = fs.readFileSync(filePath)
return fileBuffer.toString()
function cachePackages(meteorRoot) {
packageCache = getVersionFile(meteorRoot)
.split('\n')
.filter(p => !!p.trim())
.map(p => p.split('@')[0]);
}

function cacheLocalPackages(meteorRoot) {

const packageDir = path.join(meteorRoot, 'packages');
localPackageCache = {};
fs.readdirSync(packageDir)
.filter(f => fs.existsSync(path.join(packageDir, f, 'package.js')))
.forEach((f) => {
const packageContent = fs.readFileSync(path.join(packageDir, f, 'package.js'), 'utf-8');
const extract = packageContent.match(packageNameRe);
if (Array.isArray(extract) && extract.length > 1) {
localPackageCache[extract[1]] = f;
} else {
localPackageCache[f] = f;
}
});
}

function updateCache(meteorRoot) {
cachePackages(meteorRoot);
cacheLocalPackages(meteorRoot);
cacheUpdatedAt = new Date();
}

function resolveMeteorPackage(source, meteorRoot) {
try {
const [_, packageName, ...file] = source.split('/');

if (isCacheOutdated()) {
updateCache(meteorRoot);
}

if (packageCache.includes(packageName)) {
if (Object.keys(localPackageCache).includes(packageName)) {
const baseName = path.join(meteorRoot, 'packages', localPackageCache[packageName], ...file);
const names = [
baseName,
baseName + '.js',
path.join(baseName, 'index.js'),
];
const realPath = names.find(n => fs.existsSync(n));
if (realPath) {
return { found: true, path: realPath };
}
return { found: false };
}
return { found: true, path: null };
}
return { found: false };
} catch (e) {
return { found: false };
}
}
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
},
"homepage": "https://github.com/clayne11/eslint-import-resolver-meteor",
"dependencies": {
"object-assign": "^4.0.1",
"resolve": "^1.1.6"
},
"peerDependencies": {
Expand Down