-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcodegen.js
115 lines (104 loc) · 4.85 KB
/
codegen.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
const fs = require('fs')
const path = require('path')
const queryTsTempate = fs.readFileSync(path.join(__dirname, 'server', 'queries', 'query.ts.template'), 'utf8')
const codegenWarning = '// WARNING: THIS CODE IS AUTO-GENERATED. ANY MANUAL EDITS WILL BE OVERWRITTEN WITHOUT WARNING\n'
function getQueryTs(queryName, argumentFields, resultFields, helperFunction, extraImports, extendResultString, extendArgString) {
let contents = codegenWarning + queryTsTempate
contents = contents.replace(new RegExp('@extraImports', 'g'), extraImports.join('\n'))
contents = contents.replace(new RegExp('@queryName', 'g'), queryName)
contents = contents.replace(new RegExp('@argumentFields', 'g'), ' ' + argumentFields.join('\n '))
contents = contents.replace(new RegExp('@resultFields', 'g'), ' ' + resultFields.join('\n '))
contents = contents.replace(new RegExp('@helperFunction', 'g'), helperFunction)
contents = contents.replace(new RegExp('@extendResult', 'g'), extendResultString)
contents = contents.replace(new RegExp('@extendArg', 'g'), extendArgString)
return contents
}
function getCodegenItems(sql) {
codegenItems = []
sql.split('\n').forEach(line => {
const match = line.trim().match(new RegExp('--[\\s]*@([A-Za-z0-9]+)(?: (.*))?$'))
if (match) {
codegenItems.push({
type: match[1],
value: match[2],
})
}
})
return codegenItems
}
function writeIfChanged(filePath, fileContents) {
try {
const oldContents = fs.readFileSync(filePath, 'utf8')
if (oldContents == fileContents) return
} catch (error) {
// File doesn't exist. Continue
}
fs.writeFileSync(filePath, fileContents)
console.info(`codegen: wrote ${filePath}`)
}
const rootDir = path.join(__dirname, 'server', 'queries')
fs.readdirSync(rootDir).forEach(dirItem => {
dirItemAbs = path.join(rootDir, dirItem)
if (!fs.statSync(dirItemAbs).isDirectory()) {
return
}
const generatedQueryNames = []
// Create new ts files
fs.readdirSync(dirItemAbs).forEach(subdirItem => {
subdirItemAbs = path.join(dirItemAbs, subdirItem)
if (fs.statSync(subdirItemAbs).isDirectory() || !subdirItemAbs.endsWith('.query.sql')) {
return
}
const sqlFile = fs.readFileSync(subdirItemAbs, 'utf8')
const items = getCodegenItems(sqlFile)
if (items.length == 0) {
return
}
const extraImports = []
let extendResultString = ''
let extendArgString = ''
const argumentFields = items.filter(item => item['type'] == 'arg').map(item => item['value'])
const resultFields = items.filter(item => item['type'] == 'return').map(item => item['value'])
const extendResult = items.filter(item => item['type'] == 'extendsResults').map(item => item['value'])
const extendArg = items.filter(item => item['type'] == 'extendsArgs').map(item => item['value'])
const helperFunction = items.filter(item => item['type'] == 'unique').length > 0 ? 'buildQueryWithUniqueResult' : 'buildQuery'
const queryName = subdirItem.replace('.query.sql', '')
if (items.filter(item => ['arg', 'return'].includes(item['type']) && item['value'].includes('Moment;')).length > 0) {
// hack: import Moment if the argument string contains 'Moment'
extraImports.push("import { Moment } from 'moment';")
}
if (items.filter(item => ['arg', 'return', 'extendsResults', 'extendsArgs'].includes(item['type']) && item['value'].includes('dt.')).length > 0) {
extraImports.push("import * as dt from '../../../common/DataTypes';")
}
if (extendResult.length > 0) {
extendResultString = ' extends ' + extendResult[0]
}
if (extendArg.length > 0) {
extendArgString = ' extends ' + extendArg[0]
}
const fileName = queryName + '.query.ts'
const filePath = path.join(dirItemAbs, fileName)
const fileContents = getQueryTs(queryName, argumentFields, resultFields, helperFunction, extraImports, extendResultString, extendArgString)
writeIfChanged(filePath, fileContents)
generatedQueryNames.push(queryName)
})
// Delete old ts files
fs.readdirSync(dirItemAbs).forEach(subdirItem => {
subdirItemAbs = path.join(dirItemAbs, subdirItem)
if (fs.statSync(subdirItemAbs).isDirectory() || !subdirItemAbs.endsWith('.query.ts')) {
return
}
const tsFile = fs.readFileSync(subdirItemAbs, 'utf8')
const queryName = subdirItem.replace('.query.ts', '')
if (tsFile.startsWith(codegenWarning) && !generatedQueryNames.includes(queryName)) {
fs.unlinkSync(subdirItemAbs)
console.info(`codegen: deleted ${subdirItemAbs}`)
}
})
// Write exports file
const exportsFileBody =
generatedQueryNames.length > 0
? generatedQueryNames.map(queryName => `export { ${queryName}, Result as ${queryName}Result, Arguments as ${queryName}Args } from './${queryName}.query';`).join('\n') + '\n'
: ''
writeIfChanged(path.join(dirItemAbs, 'index.ts'), codegenWarning + exportsFileBody)
})