Skip to content

Commit 67e0b97

Browse files
wb-hx510875yndu13
wb-hx510875
authored andcommitted
refactor: resolve dependencies
1 parent f21a419 commit 67e0b97

File tree

5 files changed

+152
-180
lines changed

5 files changed

+152
-180
lines changed

src/generator.js

+124-147
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,140 @@
22

33
const path = require('path');
44
const fs = require('fs');
5-
const debug = require('./lib/debug');
65

76
const { _deepClone, _assignObject } = require('./lib/helper');
87
const ClientResolver = require('./resolver/client');
98
const ModelResolver = require('./resolver/model');
109

10+
function readLock(pkg_dir) {
11+
const filepath = path.join(pkg_dir, '.libraries.json');
12+
if (!fs.existsSync(filepath)) {
13+
throw new Error('The `.libraries.json` file could not be found. Please execute "dara install" first.');
14+
}
15+
return JSON.parse(fs.readFileSync(filepath, 'utf8'));
16+
}
17+
18+
function readModuleMeta(module_dir, pkg_dir, lock) {
19+
if (!path.isAbsolute(module_dir)) {
20+
if (module_dir.startsWith('./') || module_dir.startsWith('../')) {
21+
module_dir = path.join(pkg_dir, module_dir);
22+
} else {
23+
module_dir = path.join(pkg_dir, lock[module_dir]);
24+
}
25+
}
26+
const filepath = fs.existsSync(path.join(module_dir, 'Teafile'))
27+
? path.join(module_dir, 'Teafile')
28+
: path.join(module_dir, 'Darafile');
29+
return JSON.parse(fs.readFileSync(filepath));
30+
}
31+
32+
function resolveDependencies(ast) {
33+
const imports = ast.imports;
34+
const dependencies = {
35+
// Package ID : { meta, scope, package_name, client_name, client_alias }
36+
};
37+
if (!imports || !imports.length) {
38+
return dependencies;
39+
}
40+
41+
const self_client_name = this.config.clientName ? this.config.clientName.toLowerCase() : this.config.client.name.toLowerCase();
42+
const libraries = this.config.libraries;
43+
const lock = readLock(this.config.pkgDir);
44+
const lang = this.lang;
45+
const default_client_name = this.config.client.name;
46+
const default_model_dir = this.config.model.dir;
47+
48+
let package_sets = [];
49+
let client_sets = [];
50+
ast.imports.forEach((item) => {
51+
const aliasId = item.lexeme;
52+
const meta = readModuleMeta(libraries[aliasId], this.config.pkgDir, lock);
53+
const scope = meta.scope;
54+
let package_name = meta.name;
55+
let client_name = default_client_name;
56+
let model_dir = default_model_dir;
57+
let lang_config = !meta[lang] ? {} : meta[lang];
58+
if (lang_config.package) {
59+
package_name = lang_config.package;
60+
}
61+
if (lang_config.clientName) {
62+
client_name = lang_config.clientName;
63+
}
64+
if (lang_config.modelDirName) {
65+
model_dir = lang_config.modelDirName;
66+
}
67+
// check package name duplication
68+
if (package_sets.indexOf(package_name.toLowerCase()) > 0) {
69+
throw new Error(`The package name (${package_name}) has been defined in ${aliasId} dara package.`);
70+
}
71+
package_sets.push(package_name.toLowerCase());
72+
73+
// check client name duplication
74+
let client_name_lower = client_name.toLowerCase();
75+
let client_alias = '';
76+
if (client_sets.indexOf(client_name_lower) > -1 || client_name_lower === self_client_name) {
77+
client_alias = package_name.split('.').join('') + '->' + client_name.split('.').join('');
78+
} else {
79+
client_sets.push(client_name_lower);
80+
}
81+
dependencies[aliasId] = {
82+
meta,
83+
scope,
84+
package_name,
85+
client_name,
86+
client_alias,
87+
model_dir
88+
};
89+
});
90+
return dependencies;
91+
}
92+
93+
function getCombinator(lang, configOriginal, denpendencies) {
94+
const config = _deepClone(configOriginal);
95+
96+
// init combinator
97+
const Combinator = require(`./langs/${lang}/combinator`);
98+
return new Combinator(config, denpendencies);
99+
}
100+
101+
function resolveAST(type, ast, globalAST) {
102+
const combinator = getCombinator(this.lang, this.config);
103+
let resolver;
104+
switch (type) {
105+
case 'client':
106+
resolver = new ClientResolver(ast, combinator, ast);
107+
break;
108+
case 'model':
109+
resolver = new ModelResolver(ast, combinator, globalAST);
110+
break;
111+
}
112+
const objectItem = resolver.resolve();
113+
objectItem.includeList = combinator.includeList;
114+
objectItem.includeModelList = combinator.includeModelList;
115+
return objectItem;
116+
}
117+
11118
class Generator {
12119
constructor(meta = {}, lang = 'php') {
13120
if (!meta.outputDir) {
14121
throw new Error('`option.outputDir` should not empty');
15122
}
16123
this.lang = lang;
17-
this.initConfig(meta);
124+
const langDir = path.join(__dirname, `./langs/${lang}/`);
125+
if (!fs.existsSync(langDir)) {
126+
throw new Error(`Not supported language : ${lang}`);
127+
}
128+
const lang_config = require(`./langs/${lang}/config`);
129+
const common_config = _deepClone(require('./langs/common/config'));
130+
const config = {
131+
dir: meta.outputDir,
132+
};
133+
const meta_lang_config = !meta[lang] ? {} : meta[lang];
134+
this.config = _assignObject(config, common_config, lang_config, meta, meta_lang_config);
18135
}
19136

20137
visit(ast) {
21-
this.imports = this.resolveImports(ast);
138+
const dependencies = resolveDependencies.call(this, ast);
22139
if (this.config.clientName) {
23140
this.config.client.name = this.config.clientName;
24141
}
@@ -29,171 +146,31 @@ class Generator {
29146
const objects = [];
30147

31148
// combine client code
32-
const clientObjectItem = this.resolve('client', ast, ast);
149+
const clientObjectItem = resolveAST.call(this, 'client', ast, ast);
33150
objects.push(clientObjectItem);
34151

35152
// combine model code
36153
ast.moduleBody.nodes.filter((item) => {
37154
return item.type === 'model';
38155
}).forEach((model) => {
39156
const modelName = model.modelName.lexeme;
40-
const modelObjectItem = this.resolve('model', model, ast);
157+
const modelObjectItem = resolveAST.call(this, 'model', model, ast);
41158
if (ast.models) {
42159
Object.keys(ast.models).filter((key) => {
43160
return key.startsWith(modelName + '.');
44161
}).forEach((key) => {
45162
const subModel = ast.models[key];
46-
const subModelObjectItem = this.resolve('model', subModel, ast);
163+
const subModelObjectItem = resolveAST.call(this, 'model', subModel, ast);
47164
modelObjectItem.subObject.push(subModelObjectItem);
48165
});
49166
}
50167
objects.push(modelObjectItem);
51168
});
52169

53-
const combinator = this.getCombinator(this.config);
170+
const combinator = getCombinator(this.lang, this.config, dependencies);
54171
combinator.combine(objects);
55172
return objects;
56173
}
57-
58-
resolve(type, ast, globalAST) {
59-
const combinator = this.getCombinator(this.config);
60-
let resolver;
61-
switch (type) {
62-
case 'client':
63-
resolver = new ClientResolver(ast, combinator, ast);
64-
break;
65-
case 'model':
66-
resolver = new ModelResolver(ast, combinator, globalAST);
67-
break;
68-
}
69-
const objectItem = resolver.resolve();
70-
objectItem.includeList = combinator.includeList;
71-
objectItem.includeModelList = combinator.includeModelList;
72-
return objectItem;
73-
}
74-
75-
getCombinator(configOriginal) {
76-
const config = _deepClone(configOriginal);
77-
78-
// init combinator
79-
const Combinator = require(`./langs/${this.lang}/combinator`);
80-
return new Combinator(config, this.imports);
81-
}
82-
83-
initConfig(meta) {
84-
const langDir = path.join(__dirname, `./langs/${this.lang}/`);
85-
if (!fs.existsSync(langDir)) {
86-
throw new Error(`Not supported language : ${this.lang}`);
87-
}
88-
const langConfig = require(`./langs/${this.lang}/config`);
89-
90-
const config = _deepClone(require('./langs/common/config'));
91-
_assignObject(config, {
92-
dir: meta.outputDir,
93-
}, langConfig, meta);
94-
if (meta[this.lang]) {
95-
_assignObject(config, meta[this.lang]);
96-
}
97-
this.config = config;
98-
}
99-
100-
resolveImports(ast) {
101-
const imports = ast.imports;
102-
103-
let requirePackage = [];
104-
let thirdPackageDaraMeta = {};
105-
let thirdPackageScope = {};
106-
let thirdPackageNamespace = {};
107-
let thirdPackageModel = {};
108-
let thirdPackageClient = {};
109-
let thirdPackageClientAlias = {};
110-
let libraries = {};
111-
112-
const selfClientName = this.config.clientName ? this.config.clientName : this.config.client.name;
113-
114-
if (imports.length > 0) {
115-
const lockPath = path.join(this.config.pkgDir, '.libraries.json');
116-
const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
117-
let packageNameSet = [];
118-
let clientNameSet = [];
119-
Object.keys(lock).forEach(key => {
120-
const tmp = key.split(':');
121-
const name = tmp[1];
122-
libraries[name] = lock[key];
123-
});
124-
ast.imports.forEach((item) => {
125-
const aliasId = item.lexeme;
126-
const moduleDir = this.config.libraries[aliasId];
127-
let targetPath;
128-
if (moduleDir.startsWith('./') || moduleDir.startsWith('../')) {
129-
targetPath = path.join(this.config.pkgDir, moduleDir);
130-
} else if (moduleDir.startsWith('/')) {
131-
targetPath = moduleDir;
132-
} else {
133-
targetPath = path.join(this.config.pkgDir, lock[moduleDir]);
134-
}
135-
// get dara meta
136-
const daraFilePath = fs.existsSync(path.join(targetPath, 'Teafile'))
137-
? path.join(targetPath, 'Teafile')
138-
: path.join(targetPath, 'Darafile');
139-
const daraMeta = JSON.parse(fs.readFileSync(daraFilePath));
140-
thirdPackageDaraMeta[aliasId] = daraMeta;
141-
thirdPackageScope[aliasId] = daraMeta.scope;
142-
143-
// init package name, client name, model dir name
144-
let packageName, clientName, modelDir;
145-
if (daraMeta[this.lang]) {
146-
packageName = daraMeta[this.lang].package ? daraMeta[this.lang].package : daraMeta.name;
147-
clientName = daraMeta[this.lang].clientName
148-
? daraMeta[this.lang].clientName
149-
: this.config.client.name;
150-
modelDir = daraMeta[this.lang].modelDirName
151-
? daraMeta[this.lang].modelDirName
152-
: this.config.model.dir;
153-
} else {
154-
packageName = daraMeta.name;
155-
clientName = this.config.client.name;
156-
modelDir = this.config.model.dir;
157-
}
158-
159-
// resolve third package namespace
160-
if (packageNameSet.indexOf(packageName.toLowerCase()) < 0) {
161-
thirdPackageNamespace[aliasId] = packageName;
162-
packageNameSet.push(packageName.toLowerCase());
163-
} else {
164-
debug.stack('Duplication namespace');
165-
}
166-
167-
// resolve third package model client name
168-
if (
169-
clientNameSet.indexOf(clientName.toLowerCase()) > -1 ||
170-
clientName.toLowerCase() === selfClientName.toLowerCase()
171-
) {
172-
const alias = packageName.split('.').join('') + '->' + clientName.split('.').join('');
173-
thirdPackageClientAlias[aliasId] = alias;
174-
thirdPackageClient[aliasId] = clientName;
175-
} else {
176-
thirdPackageClient[aliasId] = clientName;
177-
clientNameSet.push(clientName.toLowerCase());
178-
}
179-
if (daraMeta.releases && daraMeta.releases[this.lang]) {
180-
requirePackage.push(daraMeta.releases[this.lang]);
181-
}
182-
// third package model dir name
183-
thirdPackageModel[aliasId] = modelDir;
184-
});
185-
}
186-
return {
187-
libraries,
188-
requirePackage,
189-
thirdPackageDaraMeta,
190-
thirdPackageScope,
191-
thirdPackageNamespace,
192-
thirdPackageClient,
193-
thirdPackageClientAlias,
194-
thirdPackageModel,
195-
};
196-
}
197174
}
198175

199176
module.exports = Generator;

src/langs/common/combinator.js

+3-12
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const {
2222
} = require('../../lib/helper.js');
2323

2424
class BaseCombinator {
25-
constructor(config = {}, imports = {}) {
25+
constructor(config = {}, dependencies = {}) {
2626
this.level = 0;
2727
this.eol = '';
2828

@@ -31,16 +31,7 @@ class BaseCombinator {
3131
this.includeSet = [];
3232

3333
this.config = config;
34-
this.imports = imports;
35-
36-
this.libraries = imports.libraries;
37-
this.requirePackage = imports.requirePackage;
38-
this.thirdPackageDaraMeta = imports.thirdPackageDaraMeta;
39-
this.thirdPackageScope = imports.thirdPackageScope;
40-
this.thirdPackageNamespace = imports.thirdPackageNamespace;
41-
this.thirdPackageClient = imports.thirdPackageClient;
42-
this.thirdPackageClientAlias = imports.thirdPackageClientAlias;
43-
this.thirdPackageModel = imports.thirdPackageModel;
34+
this.dependencies = dependencies;
4435

4536
_config(this.config);
4637
}
@@ -81,7 +72,7 @@ class BaseCombinator {
8172
return null;
8273
}
8374
const name = grammer.path[0].name.substr(1);
84-
const scope = this.thirdPackageScope[name];
75+
const scope = this.dependencies[name].scope;
8576
if (!scope) {
8677
return null;
8778
}

src/langs/common/package_info.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ const debug = require('../../lib/debug');
66
const { _render } = require('../../lib/helper');
77

88
class BasePackageInfo {
9-
constructor(config) {
9+
constructor(config, dependencies) {
1010
this.config = config;
11+
this.dependencies = dependencies;
1112
this.outputDir = '';
1213
}
1314

0 commit comments

Comments
 (0)