-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
168 lines (162 loc) · 5.92 KB
/
index.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
#!/usr/bin/env node
/**
* This script converts the ORM generated by sequelize auto to a form
* accepted by hapi sequelize js
*/
const fs = require("fs");
const readline = require('readline');
const assert = require("assert");
const commander = require('commander');
const program = new commander.Command();
program.version('0.0.1');
program
.description('This application converts models generated by sequelize auto to models accepted by hapi-sequelizejs')
.option('-i, --input <inputPath>', 'input path for models generated from sequelize auto.','./models')
.option('-o, --output <outputPath>','output path for models converted to use with hapi sequelize js.','./convertedModels');
program.parse();
const options = program.opts();
const INPUT_PATH = options.input;
const OUTPUT_PATH = options.output;
(async function () {
let {modelMap2assoc,fileName2modelName,modelName2FileName} = await readAllModels(`${INPUT_PATH}/init-models.js`);
for (let [modelName,assoc] of modelMap2assoc.entries()){
let fileName = modelName2FileName.get(modelName);
await makeFile(fileName,modelName,modelMap2assoc.get(modelName));
}
})();
/**
* @param {string} fileName
* This function reads the init file generated by sequelize auto and generates
* 3 maps
* modelname -> associations
* modelname -> filename
* filename -> modelname
*/
async function readAllModels(fileName) {
const fileStream = fs.createReadStream(fileName);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
let modelMap2assoc = new Map();
let modelFileNames = [];
let modelNames = [];
const assocSet = new Set(["belongsTo","belongsToMany","hasMany","hasOne"]);
let inFunction = false;
for await (let line of rl) {
if (line.includes("function initModels(sequelize)")) {
inFunction = true;
}
if(!inFunction){
if(line.includes("var") && !line.includes("DataTypes")){
let startIndex = line.indexOf("/");
let endIndex = line.indexOf(`"`,startIndex);
let modelfileName = line.substring(startIndex+1,endIndex);
modelFileNames.push(modelfileName+".js");
}
}
else{
if (line.includes("var")){
index = line.indexOf("var");
line = line.substring(index);
let firstWhiteSpace = line.indexOf(" ");
let secondWhiteSpace = line.indexOf(" ",firstWhiteSpace+1);
let modelName = line.substring(firstWhiteSpace+1,secondWhiteSpace);
modelNames.push(modelName);
modelMap2assoc.set(modelName,[]);
}else{
line = line.trim()
let dotIndex = line.indexOf(".");
let endIndex = line.indexOf("(");
let association = line.substring(dotIndex+1,endIndex);
let modelName = line.substring(0,dotIndex);
if(assocSet.has(association)){
modelMap2assoc.get(modelName).push(line);
}
}
}
}
console.log(modelNames);
console.log(modelFileNames);
assert.strictEqual(modelNames.length,modelFileNames.length);
let fileName2modelName = new Map();
let modelName2FileName = new Map();
for(let i=0;i<modelNames.length;i++){
fileName2modelName.set(modelFileNames[i],modelNames[i]);
modelName2FileName.set(modelNames[i],modelFileNames[i]);
}
return {modelMap2assoc,fileName2modelName,modelName2FileName};
}
/**
* @param {string} fileName
* Get sequelize definition without associations from filename
*/
async function getSequelizeDefine(fileName,modelName){
const fileStream = fs.createReadStream(fileName);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
let start = false;
let strings = [];
let stack = []; // stack to find matching parethesis end where sequelize define ends
loop:
for await(let line of rl){
if(line.includes("return")){
start = true;
line = line.replace("return",`const ${modelName} =`);
stack.push("(");
strings.push(line);
continue;
}
if(start){
strings.push(line);
for(let c of line){
if(stack.length===0){
break loop;
}else{
if(c==="(" && "("===stack[stack.length-1]){
stack.push("(");
}else if(c===")" && "("===stack[stack.length-1]){
stack.pop();
}
}
}
}
}
return strings.join("\n")
}
async function makeFile(fileName,modelName,associations){
let sqlDefString = await getSequelizeDefine(`${INPUT_PATH}/${fileName}`,modelName);
let modelSet = new Set();
let modelsPlate = ` const ${modelName} = model.${modelName};\n`
modelSet.add(modelsPlate);
let models = [modelName];
let associationsPlate = "";
for (assoc of associations){
let startIndex = assoc.indexOf("(") + 1;
let endIndex = assoc.indexOf(",");
let modelName = assoc.substring(startIndex,endIndex);
let modelString = ` const ${modelName} = model.${modelName};\n`;
if (!modelSet.has(modelString)){
modelsPlate += modelString;
modelSet.add(modelString);
}
associationsPlate += ` ${assoc}\n`;
}
let template =
`const Sequelize = require('sequelize');
module.exports = (sequelize, DataTypes) => {
${sqlDefString}
${modelName}.associate = function(model) {
initRelations(model);
}
return ${modelName};
}
const initRelations = (model) =>{
${modelsPlate}
${associationsPlate}
}
`
fs.writeFileSync(`${OUTPUT_PATH}/${fileName}`,template)
}