-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathcreateTypes.mjs
198 lines (171 loc) · 5.56 KB
/
createTypes.mjs
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import jsdoc2md from 'jsdoc-to-markdown'
import fs from 'fs'
/* input and output paths */
const inputFile = './src/allCFunctions.mjs'
const functionsFile = './src/addGeosFunctions.mjs'
const outputDir = './build/package'
const helpersDir = './build/package/helpers'
const emscriptenTypes = fs.readFileSync('./node_modules/@types/emscripten/index.d.ts', 'utf8')
/* create output directory if it doesn't exist */
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir)
/* get template data */
const templateData = await jsdoc2md.getTemplateData({
files: [inputFile, functionsFile],
configure: './jsdoc.conf'
})
function createFunctionString (identifier, returnType, functionName, params) {
let functionString = '/**' + '\n'
if (identifier.description) {
functionString +=
` * ${identifier.description.replace(/\n/g, '\n* ')}` + '\n'
}
identifier.params?.forEach((param) => {
functionString += ` * @param ${param.name} - ${param.description}` + '\n'
})
if (identifier.returns?.[0]?.description) {
functionString +=
` * @returns ${returnType} - ${identifier.returns[0].description}` +
'\n'
}
if (identifier.see) {
functionString += ` * @see ${identifier.see[0]}` + '\n'
}
functionString += ' */' + '\n'
functionString += ` ${functionName}(${params.join(', ')}): ${returnType};`
return functionString
}
// Create a TypeScript interface property for each function as a string, in the format
// function(param1: string, param2: number): number;
const allFunctionsTypes = templateData
.map((identifier) => {
if (
(identifier.kind === 'member' || identifier.kind === 'function') &&
identifier.name.includes('GEOS')
) {
const params =
identifier.params?.map((param) => {
return `${param.name}: ${param.type.names[0]}`
}) || []
const returnType = identifier.returns?.[0]?.type?.names[0] || 'void'
// remove geos. from the function name
const functionName = identifier.name.replace('geos.', '')
const functionString = createFunctionString(
identifier,
returnType,
functionName,
params
)
return functionString
}
return ''
})
.filter(Boolean)
const allModuleFunctions = templateData
.map((identifier) => {
if (identifier.kind === 'member' && !identifier.name.includes('GEOS')) {
const params =
identifier.params?.map((param) => {
return `${param.name}: ${param.type.names[0]}`
}) || []
const returnType = identifier.returns?.[0]?.type?.names[0] || 'void'
// remove geos. from the function name
const functionName = identifier.name.replace('geos.', '')
const functionString = createFunctionString(
identifier,
returnType,
functionName,
params
)
return functionString
}
return ''
})
.filter(Boolean)
// All typedefs
const allTypedefs = templateData.map((identifier) => {
if (identifier.kind === 'typedef') {
return `type ${identifier.name} = ${identifier.type.names[0]}`
}
return ''
}).filter(Boolean)
// All callbacks
const allCallbacks = templateData.map((identifier) => {
if (identifier.kind === 'callback') {
const params = identifier.params.map((param) => {
return `${param.name}: ${param.type.names[0]}`
})
return `type ${identifier.name} = (${params.join(', ')}) => void`
}
return ''
}).filter(Boolean)
// All enums
const allEnums = templateData.map((identifier) => {
if (identifier.kind === 'enum') {
const values = identifier.properties.map((prop, i) => {
return `${prop.name} = ${prop.defaultvalue}${i === identifier.properties.length - 1 ? '' : ','}`
})
return `export enum ${identifier.name.replace('geos.', '')} {
${values.join('\n ')}
}`
}
return ''
}).filter(Boolean)
const output = `
${emscriptenTypes}
interface Module extends EmscriptenModule {
${allModuleFunctions.join('\n ')}
}
${allTypedefs.join('\n')}
${allCallbacks.join('\n')}
${allEnums.join('\n')}
interface geos {
${templateData.filter((identifier) => identifier.kind === 'enum').map(({ name }) => `${name.replace('geos.', '')}: typeof ${name.replace('geos.', '')}`).join('\n ')}
${allFunctionsTypes.join('\n ')}
Module: Module;
}
interface Config {
/**
* If autoInit is true, the GEOS library will be initialized when the geos object is created.
* @default true
*/
autoInit?: boolean;
errorHandler?: (message: string) => void;
noticeHandler?: (message: string) => void;
}
declare module 'geos-wasm' {
export default function initGeosJs(config?: Config): Promise<geos>;
}`
fs.writeFileSync(`${outputDir}/geos.esm.d.ts`, output)
// and for the helper module
const helperTemplateData = await jsdoc2md.getTemplateData({
files: './src/helpers/*.mjs',
configure: './jsdoc.conf'
})
const helperFunctions = helperTemplateData
.map((identifier) => {
if (identifier.kind === 'function') {
const params =
identifier.params?.map((param) => {
return `${param.name}: ${param.type.names[0]}`
}) || []
const returnType = identifier.returns?.[0]?.type?.names[0] || 'void'
const functionName = 'export function ' + identifier.name
const functionString = createFunctionString(
identifier,
returnType,
functionName,
params
)
return functionString
}
return ''
})
.filter(Boolean)
const helperOutput = `// <reference types="geojson">
${helperFunctions.join('\n ')}
export default {
geojsonToGeosGeom,
geosGeomToGeojson
}
`
fs.writeFileSync(`${helpersDir}/geos.helpers.esm.d.ts`, helperOutput)