@@ -38,7 +38,7 @@ function generateAll() {
38
38
// load pkg and interface info (msgs and srvs)
39
39
const generatedPath = path . join ( __dirname , '../generated/' ) ;
40
40
const pkgInfos = getPkgInfos ( generatedPath ) ;
41
-
41
+
42
42
// write message.d.ts file
43
43
const messagesFilePath = path . join ( __dirname , '../types/interfaces.d.ts' ) ;
44
44
const fd = fs . openSync ( messagesFilePath , 'w' ) ;
@@ -56,17 +56,19 @@ function getPkgInfos(generatedRoot) {
56
56
57
57
const pkgInfo = {
58
58
name : pkg ,
59
- messages : [ ]
59
+ messages : [ ] ,
60
+ services : [ ]
60
61
} ;
61
62
62
63
const pkgPath = path . join ( rootDir , pkg ) ;
63
- const files = fs . readdirSync ( pkgPath ) ;
64
+ const files = fs . readdirSync ( pkgPath ) . filter ( fn => fn . endsWith ( '.js' ) ) ;
64
65
65
66
for ( let filename of files ) {
66
67
const typeClass = fileName2Typeclass ( filename ) ;
67
68
68
69
if ( typeClass . type === 'srv' ) { // skip __srv__<action>
69
70
if ( ! typeClass . name . endsWith ( 'Request' ) && ! typeClass . name . endsWith ( 'Response' ) ) {
71
+ pkgInfo . services . push ( typeClass ) ;
70
72
continue ;
71
73
}
72
74
}
@@ -93,10 +95,12 @@ function getPkgInfos(generatedRoot) {
93
95
94
96
95
97
function savePkgInfoAsTSD ( pkgInfos , fd ) {
96
-
97
- let fullMessageNames = [ 'string' ] ;
98
+ let messagesMap = {
99
+ string : 'string' ,
100
+ } ;
98
101
99
102
fs . writeSync ( fd , '/* eslint-disable camelcase */\n' ) ;
103
+ fs . writeSync ( fd , '/* eslint-disable max-len */\n' ) ;
100
104
fs . writeSync ( fd , '// DO NOT EDIT\n' ) ;
101
105
fs . writeSync ( fd , '// This file is generated by the rostsd_gen script\n\n' ) ;
102
106
@@ -115,7 +119,7 @@ function savePkgInfoAsTSD(pkgInfos, fd) {
115
119
for ( const msgInfo of pkgInfo . messages ) {
116
120
117
121
if ( msgInfo . typeClass . type != curNS ) {
118
- if ( curNS ) { // close current ns
122
+ if ( curNS ) { // close current ns
119
123
fs . writeSync ( fd , ' }\n' ) ;
120
124
}
121
125
@@ -129,10 +133,11 @@ function savePkgInfoAsTSD(pkgInfos, fd) {
129
133
}
130
134
131
135
saveMsgInfoAsTSD ( msgInfo , fd ) ;
136
+ saveMsgWrapperAsTSD ( msgInfo , fd ) ;
132
137
133
138
// full path to this msg
134
- const fullMessageName = `${ pkgInfo . name } . ${ msgInfo . typeClass . type } . ${ msgInfo . typeClass . name } ` ;
135
- fullMessageNames . push ( fullMessageName ) ;
139
+ const fullMessageName = `${ pkgInfo . name } / ${ msgInfo . typeClass . type } / ${ msgInfo . typeClass . name } ` ;
140
+ messagesMap [ fullMessageName ] = ` ${ pkgInfo . name } . ${ msgInfo . typeClass . type } . ${ msgInfo . typeClass . name } ` ;
136
141
}
137
142
138
143
if ( curNS ) {
@@ -144,66 +149,112 @@ function savePkgInfoAsTSD(pkgInfos, fd) {
144
149
fs . writeSync ( fd , ' }\n\n' ) ;
145
150
}
146
151
147
- // write type alias for Message
148
- // e.g. type Message =
149
- // string |
150
- // std_msgs.msg.Bool |
151
- // std_msgs.msg.Byte |
152
- // ...
153
- fs . writeSync ( fd , ' type Message = \n' ) ;
154
- for ( let i = 0 ; i < fullMessageNames . length ; i ++ ) {
155
- fs . writeSync ( fd , ' ' + fullMessageNames [ i ] ) ;
156
- if ( i != fullMessageNames . length - 1 ) {
157
- fs . writeSync ( fd , ' |\n' ) ;
158
- }
152
+ // write messages type mappings
153
+ fs . writeSync ( fd , ' type MessagesMap = {\n' ) ;
154
+ for ( const key in messagesMap ) {
155
+ fs . writeSync ( fd , ` '${ key } ': ${ messagesMap [ key ] } ,\n` ) ;
156
+ }
157
+ fs . writeSync ( fd , ' };\n' ) ;
158
+ fs . writeSync ( fd , ' type MessageTypeClassName = keyof MessagesMap;\n' ) ;
159
+ fs . writeSync ( fd , ' type Message = MessagesMap[MessageTypeClassName];\n' ) ;
160
+ fs . writeSync ( fd , ' type MessageType<T> = T extends MessageTypeClassName ? MessagesMap[T] : object;\n\n' ) ;
161
+
162
+ // write message wrappers mappings
163
+ fs . writeSync ( fd , ' type MessageTypeClassWrappersMap = {\n' ) ;
164
+ for ( const key in messagesMap ) {
165
+ if ( key === 'string' ) {
166
+ fs . writeSync ( fd , " 'string': never,\n" ) ;
167
+ continue ;
168
+ }
169
+ fs . writeSync ( fd , ` '${ key } ': ${ messagesMap [ key ] } _WrapperType,\n` ) ;
170
+ }
171
+ fs . writeSync ( fd , ' };\n' ) ;
172
+ fs . writeSync ( fd , ' type MessageWrapperType<T> = T extends MessageTypeClassName ? MessageTypeClassWrappersMap[T] : object;\n\n' ) ;
173
+
174
+ // write service type class string
175
+ const services = [ ] ;
176
+ for ( const pkg of pkgInfos ) {
177
+ services . push ( ...pkg . services ) ;
178
+ }
179
+ if ( ! services . length ) {
180
+ fs . writeSync ( fd , ' type ServiceTypeClassName = never;\n\n' ) ;
181
+ } else {
182
+ fs . writeSync ( fd , ' type ServiceTypeClassName = \n' ) ;
183
+ for ( let i = 0 ; i < services . length ; i ++ ) {
184
+ const srv = services [ i ] ;
185
+ const srvTypeClassStr = `${ srv . package } /${ srv . type } /${ srv . name } ` ;
186
+ fs . writeSync ( fd , ` '${ srvTypeClassStr } '` ) ;
187
+
188
+ if ( i !== services . length - 1 ) {
189
+ fs . writeSync ( fd , ' |\n' ) ;
190
+ }
191
+ }
192
+ fs . writeSync ( fd , ';\n\n' ) ;
159
193
}
160
-
161
- fs . writeSync ( fd , ';\n' ) ;
194
+
195
+ fs . writeSync ( fd , ' type TypeClassName = MessageTypeClassName | ServiceTypeClassName ;\n' ) ;
162
196
163
197
// close module declare
164
198
fs . writeSync ( fd , '}\n' ) ;
199
+
165
200
fs . closeSync ( fd ) ;
166
201
}
167
202
168
203
169
- function saveMsgInfoAsTSD ( msgInfo , fd ) {
170
-
171
- // write type = xxxx {
172
- const typeTemplate =
173
- ` export type ${ msgInfo . typeClass . name } = {\n` ;
174
-
175
- fs . writeSync ( fd , typeTemplate ) ;
176
-
177
- // write constant definitions
178
- for ( let i = 0 ; i < msgInfo . def . constants . length ; i ++ ) {
179
- const constant = msgInfo . def . constants [ i ] ;
204
+ function saveMsgWrapperAsTSD ( msgInfo , fd ) {
205
+ const msgName = msgInfo . typeClass . name ;
206
+ fs . writeSync ( fd , ` export type ${ msgName } _WrapperType = {\n` ) ;
207
+ for ( const constant of msgInfo . def . constants ) {
180
208
const constantType = primitiveType2JSName ( constant . type ) ;
181
- const tmpl = ( constantType == 'string' ) ?
182
- ` ${ constant . name } : '${ constant . value } '` :
183
- ` ${ constant . name } : ${ constant . value } ` ;
184
- fs . writeSync ( fd , tmpl ) ;
185
-
186
- if ( i != msgInfo . def . constants . length - 1 ) {
187
- fs . writeSync ( fd , ',\n' ) ;
188
- } else if ( msgInfo . def . fields . length > 0 ) {
189
- fs . writeSync ( fd , ',\n' ) ;
190
- }
209
+ fs . writeSync ( fd , ` readonly ${ constant . name } : ${ constantType } ,\n` ) ;
191
210
}
211
+ fs . writeSync ( fd , ` new(other?: ${ msgName } ): ${ msgName } ,\n` ) ;
212
+ fs . writeSync ( fd , ' }\n' ) ;
213
+ }
192
214
193
- // write field definitions
215
+
216
+ /**
217
+ * Writes the message fields as typescript definitions.
218
+ *
219
+ * @param {* } msgInfo ros message info
220
+ * @param {* } fd file descriptor
221
+ * @param {string } indent The amount of indent, in spaces
222
+ * @param {string } lineEnd The character to put at the end of each line, usually ','
223
+ * or ';'
224
+ * @param {string } typePrefix The prefix to put before the type name for
225
+ * non-primitive types
226
+ * @returns {undefined }
227
+ */
228
+ function saveMsgFieldsAsTSD ( msgInfo , fd , indent = 0 , lineEnd = ',' , typePrefix = '' ) {
229
+ const indentStr = ' ' . repeat ( indent ) ;
194
230
for ( let i = 0 ; i < msgInfo . def . fields . length ; i ++ ) {
195
231
const field = msgInfo . def . fields [ i ] ;
196
- const fieldType = fieldType2JSName ( field ) ;
197
- const tmpl = ` ${ field . name } : ${ fieldType } ` ;
232
+ let fieldType = fieldType2JSName ( field ) ;
233
+ let tp = field . type . isPrimitiveType ? '' : typePrefix ;
234
+ if ( typePrefix === 'rclnodejs.' ) {
235
+ fieldType = 'any' ;
236
+ tp = '' ;
237
+ }
238
+ const tmpl = `${ indentStr } ${ field . name } : ${ tp } ${ fieldType } ` ;
198
239
fs . writeSync ( fd , tmpl ) ;
199
240
if ( field . type . isArray ) {
200
241
fs . writeSync ( fd , '[]' ) ;
201
242
}
202
- if ( i != msgInfo . def . fields . length - 1 ) {
203
- fs . writeSync ( fd , ',' ) ;
204
- }
243
+ fs . writeSync ( fd , lineEnd ) ;
205
244
fs . writeSync ( fd , '\n' ) ;
206
245
}
246
+ }
247
+
248
+
249
+ function saveMsgInfoAsTSD ( msgInfo , fd ) {
250
+ // write type = xxxx {
251
+ const typeTemplate =
252
+ ` export type ${ msgInfo . typeClass . name } = {\n` ;
253
+
254
+ fs . writeSync ( fd , typeTemplate ) ;
255
+
256
+ // write field definitions
257
+ saveMsgFieldsAsTSD ( msgInfo , fd , 8 ) ;
207
258
208
259
// end of def
209
260
fs . writeSync ( fd , ' };\n' ) ;
@@ -223,7 +274,7 @@ function primitiveType2JSName(type) {
223
274
switch ( type ) {
224
275
case 'char' :
225
276
case 'byte' :
226
- case 'uin8 ' :
277
+ case 'uint8 ' :
227
278
case 'int8' :
228
279
case 'int16' :
229
280
case 'uint16' :
@@ -256,7 +307,7 @@ function fileName2Typeclass(filename) {
256
307
const array = filename . split ( regex ) . filter ( Boolean ) ;
257
308
258
309
if ( ! array || array . length != 3 ) {
259
- // todo: throw error
310
+ // todo: throw error
260
311
console . log ( 'ERRORRROOROR' , array ) ;
261
312
return ;
262
313
}
0 commit comments