forked from slively/loopback-discover-models
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli.js
169 lines (147 loc) · 6.43 KB
/
cli.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/bin/env node
var cli = require('cli'),
prompt = require('cli-prompt'),
fs = require('fs'),
flags = {
prompt: [false, 'Use prompts instead of arguments', 'boolean', false],
serverPath: [false, 'Path to server.js (relative to CWD)', 'path', '/server/server.js'],
modelConfigPath: [false, 'Path to model-config.json (relative to CWD)', 'path', '/server/model-config.json'],
modelDir: [false, 'Path to models folder (relative to CWD)', 'path', '/server/models'],
dataSource: [false, 'Name of the data source from data sources.json (required)', 'string', 'db'],
allNewModels: [false, 'Discover and create all models not in modelDir', 'boolean', 'false' ],
modelName: [false, 'Name of a single model/table/collection to create (if not all models)', 'string' ],
owner: [false, 'Name of owner/schema/database for the models', 'string'],
relations: [false, 'Include relations', 'boolean', 'false'],
allOwners: [false, 'Include All Owners', 'boolean', 'false'],
views: [false, 'Include views', 'boolean', 'false'],
skip: [false, 'Comma separate model names to skip when discovering new models', 'string', '']
};
cli.width = 120;
cli.parse(flags);
cli.main(function checkPrompt(args, options) {
if (options.prompt) {
// map cli flags into cli-prompt options
prompt.multi(Object.keys(flags)
.filter(function(key){
return key !== 'prompt';
})
.map(function(key) {
var flag = flags[key];
return {
key: key,
label: flag[1],
type: flag[2],
default: flag[3]
}
}), main);
return;
}
main(options);
});
function main(options) {
var serverPath = process.cwd() + options.serverPath,
modelConfigPath = process.cwd() + options.modelConfigPath,
modelsPath = process.cwd() + options.modelDir,
dataSource,
discoveryOptions = {
owner: options.owner,
relations: options.relations !== 'false',
all: options.allOwners !== 'false',
views: options.views !== 'false'
};
try {
server = require(serverPath);
dataSource = server.dataSources[options.dataSource];
} catch(e) {
cli.error(e);
cli.fatal('Unable to require() server.js from ' + serverPath);
}
if (!dataSource) {
cli.fatal('data source ' + options.dataSource + ' not found on server object.');
}
if (options.allNewModels !== 'false') {
var currentModels = fs.readdirSync(modelsPath)
.filter(function(fname){
return fname.match(/.*.json/g)
})
.map(function(fname){
return fs.readFileSync(modelsPath + '/' + fname);
})
.map(function(contents){
return JSON.parse(contents).name.toLowerCase();
}),
skips = (options.skip || '').split(',').map(function(name){
return name.trim().toLowerCase();
});
dataSource.discoverModelDefinitions(discoveryOptions, function(err, models){
if (err) {
cli.fatal(err);
} else if (!models || models.length === 0) {
cli.info('No models found in data source with options:',JSON.stringify(discoveryOptions));
process.exit();
}
var callCnt = models.length;
models.forEach(function (def) {
dataSource.discoverSchema(def.name, { owner: discoveryOptions.owner, associations: discoveryOptions.relations }, function (err, schema) {
if (err) {
cli.fatal(err);
}
// Move relations to top-level properties
var schemaRelations = schema.options.relations;
delete schema.options.relations;
schema.relations = schemaRelations;
// doesn't already exist and not skipping
if (currentModels.indexOf(schema.name.toLowerCase()) === -1) {
if (skips.indexOf(schema.name.toLowerCase()) === -1) {
cli.ok('Writing new model files for ' + schema.name);
writeFilesForModelSchema(schema);
} else {
cli.info(schema.name + ' skipped.');
}
} else {
cli.info(schema.name + ' already exists.');
}
callCnt--;
if (callCnt === 0) {
process.exit();
}
});
});
});
} else if (options.modelName) {
dataSource.discoverSchema(options.modelName, { owner: discoveryOptions.owner, associations: discoveryOptions.relations }, function (err, schema) {
if (err) {
cli.fatal(err);
}
// Move relations to top-level properties
var schemaRelations = schema.options.relations;
delete schema.options.relations;
schema.relations = schemaRelations;
cli.info('Writing new model files for ' + schema.name);
writeFilesForModelSchema(schema);
process.exit();
});
} else {
cli.fatal('You must either specify --allNewModels or --modelName <model/table/collection>');
}
function convertModelNameToFileName(modelName) {
return modelName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
function defaultJsFileContents(modelName) {
return 'module.exports = function(/*'+modelName+'*/){};'
}
function updateModelConfig(schema) {
var cfg = JSON.parse(fs.readFileSync(modelConfigPath));
cfg[schema.name] = {
dataSource: options.dataSource,
public: true
};
fs.writeFileSync(modelConfigPath, JSON.stringify(cfg, null, 2));
}
function writeFilesForModelSchema(schema) {
var filePath = modelsPath + '/' + convertModelNameToFileName(schema.name);
fs.writeFileSync(filePath + '.json', JSON.stringify(schema,null,2));
fs.writeFileSync(filePath + '.js', defaultJsFileContents(schema.name));
updateModelConfig(schema);
}
}