1
- import {
2
- Project ,
3
- PropertySignature ,
4
- SourceFile ,
5
- CodeBlockWriter ,
6
- IndentationText ,
7
- } from "ts-morph" ;
1
+ import { file_fig as file } from "@aws/amazon-q-developer-cli-proto/fig" ;
2
+ import { CodeBlockWriter , IndentationText , Project } from "ts-morph" ;
8
3
import { readFileSync } from "node:fs" ;
9
4
import { join , dirname } from "node:path" ;
10
5
import { fileURLToPath } from "node:url" ;
@@ -30,21 +25,13 @@ const normalize = (type: string): string => {
30
25
return capitalizeFirstLetter ( normalized ) ;
31
26
} ;
32
27
33
- const getSubmessageTypes = ( bindings : SourceFile , interfaceName : string ) => {
34
- const interfaceRef = bindings . getInterface ( interfaceName ) ! ;
35
- const submessage = interfaceRef . getProperties ( ) [ 1 ] ;
36
-
37
- const submessageUnion = submessage
38
- . getChildren ( )
39
- . filter ( ( elm ) => elm . getKindName ( ) === "UnionType" ) [ 0 ] ;
40
- const literals = submessageUnion
41
- . getChildren ( ) [ 0 ]
42
- . getChildren ( )
43
- . filter ( ( elm ) => elm . getKindName ( ) === "TypeLiteral" ) ;
44
- const types = literals
45
- . map ( ( elm ) => elm . getChildren ( ) [ 1 ] )
46
- . map ( ( elm ) => elm . getChildren ( ) [ 1 ] ) ;
47
- return types . map ( ( prop ) => ( prop as PropertySignature ) . getName ( ) ) ;
28
+ const getSubmessageTypes = ( interfaceName : string ) => {
29
+ const message = file . messages . find (
30
+ ( message ) => message . name === interfaceName ,
31
+ ) ;
32
+ return (
33
+ message ?. fields . map ( ( type ) => type . message ?. name ! ) . filter ( Boolean ) ?? [ ]
34
+ ) ;
48
35
} ;
49
36
50
37
const writeGenericSendRequestWithResponseFunction = (
@@ -54,23 +41,23 @@ const writeGenericSendRequestWithResponseFunction = (
54
41
const lowercasedEndpoint = lowercaseFirstLetter ( endpoint ) ;
55
42
56
43
const template = `export async function send${ endpoint } Request(
57
- request: ${ endpoint } Request
44
+ request: Omit< ${ endpoint } Request, "$typeName" | "$unknown">
58
45
): Promise<${ endpoint } Response> {
59
46
return new Promise((resolve, reject) => {
60
47
sendMessage(
61
- { $ case: "${ lowercasedEndpoint } Request", ${ lowercasedEndpoint } Request: request },
48
+ { case: "${ lowercasedEndpoint } Request", value: create( ${ endpoint } RequestSchema, request) },
62
49
(response) => {
63
- switch (response?.$ case) {
50
+ switch (response?.case) {
64
51
case "${ lowercasedEndpoint } Response":
65
- resolve(response.${ lowercasedEndpoint } Response );
52
+ resolve(response.value );
66
53
break;
67
54
case "error":
68
- reject(Error(response.error ));
55
+ reject(Error(response.value ));
69
56
break;
70
57
default:
71
58
reject(
72
59
Error(
73
- \`Invalid response '\${response?.$ case}' for '${ endpoint } Request'\`
60
+ \`Invalid response '\${response?.case}' for '${ endpoint } Request'\`
74
61
)
75
62
);
76
63
}
@@ -89,23 +76,23 @@ const writeGenericSendRequestFunction = (
89
76
const lowercasedEndpoint = lowercaseFirstLetter ( endpoint ) ;
90
77
91
78
const template = `export async function send${ endpoint } Request(
92
- request: ${ endpoint } Request
79
+ request: Omit< ${ endpoint } Request, "$typeName" | "$unknown">
93
80
): Promise<void> {
94
81
return new Promise((resolve, reject) => {
95
82
sendMessage(
96
- { $ case: "${ lowercasedEndpoint } Request", ${ lowercasedEndpoint } Request: request },
83
+ { case: "${ lowercasedEndpoint } Request", value: create( ${ endpoint } RequestSchema, request) },
97
84
(response) => {
98
- switch (response?.$ case) {
85
+ switch (response?.case) {
99
86
case "success":
100
87
resolve();
101
88
break;
102
89
case "error":
103
- reject(Error(response.error ));
90
+ reject(Error(response.value ));
104
91
break;
105
92
default:
106
93
reject(
107
94
Error(
108
- \`Invalid response '\${response?.$ case}' for '${ endpoint } Request'\`
95
+ \`Invalid response '\${response?.case}' for '${ endpoint } Request'\`
109
96
)
110
97
);
111
98
}
@@ -124,28 +111,20 @@ const project = new Project({
124
111
125
112
project . addSourceFilesAtPaths ( join ( __dirname , "../src/*.ts" ) ) ;
126
113
127
- const text = readFileSync (
128
- "node_modules/@aws/amazon-q-developer-cli-proto/dist/fig.pb.ts" ,
129
- "utf8" ,
130
- ) ;
131
- const protobufBindings = project . createSourceFile ( "fig.pb.ts" , text ) ;
132
-
133
- const requestTypes = getSubmessageTypes (
134
- protobufBindings ,
135
- "ClientOriginatedMessage" ,
114
+ const requestTypes = getSubmessageTypes ( "ClientOriginatedMessage" ) ;
115
+ const responseTypes = getSubmessageTypes ( "ServerOriginatedMessage" ) . filter (
116
+ ( type ) => type . includes ( "Response" ) ,
136
117
) ;
137
- const responseTypes = getSubmessageTypes (
138
- protobufBindings ,
139
- "ServerOriginatedMessage" ,
140
- ) . filter ( ( type ) => type . includes ( "Response" ) ) ;
141
118
142
119
const [ requestsWithMatchingResponses , otherRequests ] = requestTypes
143
120
. filter ( ( request ) => request !== "notificationRequest" )
144
121
. reduce (
145
122
( result , request ) => {
146
123
const [ matchingResponse , other ] = result ;
147
124
148
- const endpoint = lowercaseFirstLetter ( normalize ( request ) ) ;
125
+ const endpoint = normalize ( request ) ;
126
+
127
+ console . log ( endpoint , requestTypes ) ;
149
128
150
129
if ( responseTypes . indexOf ( `${ endpoint } Response` ) !== - 1 ) {
151
130
return [ matchingResponse . concat ( [ request ] ) , other ] ;
@@ -175,15 +154,31 @@ const sourceFile = project.createSourceFile(
175
154
const responses = requestsWithMatchingResponses . map ( ( request ) =>
176
155
request . replace ( "Request" , "Response" ) ,
177
156
) ;
178
- const imports = requestsWithMatchingResponses
179
- . concat ( responses )
180
- . concat ( otherRequests )
157
+ const requestSchemas = requestsWithMatchingResponses . map (
158
+ ( s ) => `${ s } Schema` ,
159
+ ) ;
160
+ const otherRequestSchemas = otherRequests . map ( ( s ) => `${ s } Schema` ) ;
161
+ const imports = [
162
+ requestsWithMatchingResponses ,
163
+ responses ,
164
+ otherRequests ,
165
+ requestSchemas ,
166
+ otherRequestSchemas ,
167
+ ]
168
+ . flat ( )
181
169
. sort ( )
182
170
. map ( capitalizeFirstLetter ) ;
183
171
writer . writeLine (
184
172
`import { \n${ imports . join ( ",\n" ) } \n } from "@aws/amazon-q-developer-cli-proto/fig";` ,
185
173
) ;
186
- writer . writeLine ( `import { sendMessage } from "./core.js";` ) . blankLine ( ) ;
174
+ writer
175
+ . writeLine (
176
+ [
177
+ 'import { sendMessage } from "./core.js";' ,
178
+ 'import { create } from "@bufbuild/protobuf";' ,
179
+ ] . join ( "\n" ) ,
180
+ )
181
+ . blankLine ( ) ;
187
182
188
183
requestsWithMatchingResponses . forEach ( ( request ) =>
189
184
writeGenericSendRequestWithResponseFunction ( writer , normalize ( request ) ) ,
0 commit comments