okai 0.0.5 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.js +39 -0
- package/dist/cs-apis.js +123 -0
- package/dist/cs-ast.js +685 -0
- package/dist/cs-gen.js +123 -0
- package/dist/cs-migrations.js +102 -0
- package/dist/icons.js +84 -0
- package/dist/index.js +418 -51
- package/dist/info.js +1 -1
- package/dist/openai.js +203 -14
- package/dist/ts-ast.js +26 -0
- package/dist/ts-parser.js +170 -0
- package/dist/tsd-gen.js +109 -0
- package/dist/types.js +8 -1
- package/dist/utils.js +178 -18
- package/package.json +2 -1
package/dist/openai.js
CHANGED
@@ -18,12 +18,44 @@ IncludeTypes: OpenAiChatCompletion.*
|
|
18
18
|
// @Api(Description="The tool calls generated by the model, such as function calls.")
|
19
19
|
// @DataContract
|
20
20
|
export class ToolCall {
|
21
|
+
/** @description The ID of the tool call. */
|
22
|
+
// @DataMember(Name="id")
|
23
|
+
// @ApiMember(Description="The ID of the tool call.")
|
24
|
+
id;
|
25
|
+
/** @description The type of the tool. Currently, only `function` is supported. */
|
26
|
+
// @DataMember(Name="type")
|
27
|
+
// @ApiMember(Description="The type of the tool. Currently, only `function` is supported.")
|
28
|
+
type;
|
29
|
+
/** @description The function that the model called. */
|
30
|
+
// @DataMember(Name="function")
|
31
|
+
// @ApiMember(Description="The function that the model called.")
|
32
|
+
function;
|
21
33
|
constructor(init) { Object.assign(this, init); }
|
22
34
|
}
|
23
35
|
/** @description A list of messages comprising the conversation so far. */
|
24
36
|
// @Api(Description="A list of messages comprising the conversation so far.")
|
25
37
|
// @DataContract
|
26
38
|
export class OpenAiMessage {
|
39
|
+
/** @description The contents of the message. */
|
40
|
+
// @DataMember(Name="content")
|
41
|
+
// @ApiMember(Description="The contents of the message.")
|
42
|
+
content;
|
43
|
+
/** @description The role of the author of this message. Valid values are `system`, `user`, `assistant` and `tool`. */
|
44
|
+
// @DataMember(Name="role")
|
45
|
+
// @ApiMember(Description="The role of the author of this message. Valid values are `system`, `user`, `assistant` and `tool`.")
|
46
|
+
role;
|
47
|
+
/** @description An optional name for the participant. Provides the model information to differentiate between participants of the same role. */
|
48
|
+
// @DataMember(Name="name")
|
49
|
+
// @ApiMember(Description="An optional name for the participant. Provides the model information to differentiate between participants of the same role.")
|
50
|
+
name;
|
51
|
+
/** @description The tool calls generated by the model, such as function calls. */
|
52
|
+
// @DataMember(Name="tool_calls")
|
53
|
+
// @ApiMember(Description="The tool calls generated by the model, such as function calls.")
|
54
|
+
tool_calls;
|
55
|
+
/** @description Tool call that this message is responding to. */
|
56
|
+
// @DataMember(Name="tool_call_id")
|
57
|
+
// @ApiMember(Description="Tool call that this message is responding to.")
|
58
|
+
tool_call_id;
|
27
59
|
constructor(init) { Object.assign(this, init); }
|
28
60
|
}
|
29
61
|
export var ResponseFormat;
|
@@ -33,6 +65,10 @@ export var ResponseFormat;
|
|
33
65
|
})(ResponseFormat || (ResponseFormat = {}));
|
34
66
|
// @DataContract
|
35
67
|
export class OpenAiResponseFormat {
|
68
|
+
/** @description An object specifying the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than gpt-3.5-turbo-1106. */
|
69
|
+
// @DataMember(Name="response_format")
|
70
|
+
// @ApiMember(Description="An object specifying the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than gpt-3.5-turbo-1106.")
|
71
|
+
response_format;
|
36
72
|
constructor(init) { Object.assign(this, init); }
|
37
73
|
}
|
38
74
|
export var OpenAiToolType;
|
@@ -41,55 +77,208 @@ export var OpenAiToolType;
|
|
41
77
|
})(OpenAiToolType || (OpenAiToolType = {}));
|
42
78
|
// @DataContract
|
43
79
|
export class OpenAiTools {
|
80
|
+
/** @description The type of the tool. Currently, only function is supported. */
|
81
|
+
// @DataMember(Name="type")
|
82
|
+
// @ApiMember(Description="The type of the tool. Currently, only function is supported.")
|
83
|
+
type;
|
44
84
|
constructor(init) { Object.assign(this, init); }
|
45
85
|
}
|
46
86
|
/** @description Given a list of messages comprising a conversation, the model will return a response. */
|
47
87
|
// @Api(Description="Given a list of messages comprising a conversation, the model will return a response.")
|
48
88
|
// @DataContract
|
49
89
|
export class OpenAiChat {
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
90
|
+
/** @description A list of messages comprising the conversation so far. */
|
91
|
+
// @DataMember(Name="messages")
|
92
|
+
// @ApiMember(Description="A list of messages comprising the conversation so far.")
|
93
|
+
messages = [];
|
94
|
+
/** @description ID of the model to use. See the model endpoint compatibility table for details on which models work with the Chat API */
|
95
|
+
// @DataMember(Name="model")
|
96
|
+
// @ApiMember(Description="ID of the model to use. See the model endpoint compatibility table for details on which models work with the Chat API")
|
97
|
+
model;
|
98
|
+
/** @description Number between `-2.0` and `2.0`. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. */
|
99
|
+
// @DataMember(Name="frequency_penalty")
|
100
|
+
// @ApiMember(Description="Number between `-2.0` and `2.0`. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.")
|
101
|
+
frequency_penalty;
|
102
|
+
/** @description Modify the likelihood of specified tokens appearing in the completion. */
|
103
|
+
// @DataMember(Name="logit_bias")
|
104
|
+
// @ApiMember(Description="Modify the likelihood of specified tokens appearing in the completion.")
|
105
|
+
logit_bias;
|
106
|
+
/** @description Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the content of message. */
|
107
|
+
// @DataMember(Name="logprobs")
|
108
|
+
// @ApiMember(Description="Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the content of message.")
|
109
|
+
logprobs;
|
110
|
+
/** @description An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. logprobs must be set to true if this parameter is used. */
|
111
|
+
// @DataMember(Name="top_logprobs")
|
112
|
+
// @ApiMember(Description="An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability. logprobs must be set to true if this parameter is used.")
|
113
|
+
top_logprobs;
|
114
|
+
/** @description The maximum number of tokens that can be generated in the chat completion. */
|
115
|
+
// @DataMember(Name="max_tokens")
|
116
|
+
// @ApiMember(Description="The maximum number of tokens that can be generated in the chat completion.")
|
117
|
+
max_tokens;
|
118
|
+
/** @description How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. */
|
119
|
+
// @DataMember(Name="n")
|
120
|
+
// @ApiMember(Description="How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs.")
|
121
|
+
n;
|
122
|
+
/** @description Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. */
|
123
|
+
// @DataMember(Name="presence_penalty")
|
124
|
+
// @ApiMember(Description="Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.")
|
125
|
+
presence_penalty;
|
126
|
+
/** @description An object specifying the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than `gpt-3.5-turbo-1106`. Setting Type to ResponseFormat.JsonObject enables JSON mode, which guarantees the message the model generates is valid JSON. */
|
127
|
+
// @DataMember(Name="response_format")
|
128
|
+
// @ApiMember(Description="An object specifying the format that the model must output. Compatible with GPT-4 Turbo and all GPT-3.5 Turbo models newer than `gpt-3.5-turbo-1106`. Setting Type to ResponseFormat.JsonObject enables JSON mode, which guarantees the message the model generates is valid JSON.")
|
129
|
+
response_format;
|
130
|
+
/** @description This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same seed and parameters should return the same result. Determinism is not guaranteed, and you should refer to the system_fingerprint response parameter to monitor changes in the backend. */
|
131
|
+
// @DataMember(Name="seed")
|
132
|
+
// @ApiMember(Description="This feature is in Beta. If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same seed and parameters should return the same result. Determinism is not guaranteed, and you should refer to the system_fingerprint response parameter to monitor changes in the backend.")
|
133
|
+
seed;
|
134
|
+
/** @description Up to 4 sequences where the API will stop generating further tokens. */
|
135
|
+
// @DataMember(Name="stop")
|
136
|
+
// @ApiMember(Description="Up to 4 sequences where the API will stop generating further tokens.")
|
137
|
+
stop;
|
138
|
+
/** @description If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only server-sent events as they become available, with the stream terminated by a `data: [DONE]` message. */
|
139
|
+
// @DataMember(Name="stream")
|
140
|
+
// @ApiMember(Description="If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only server-sent events as they become available, with the stream terminated by a `data: [DONE]` message.")
|
141
|
+
stream;
|
142
|
+
/** @description What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. */
|
143
|
+
// @DataMember(Name="temperature")
|
144
|
+
// @ApiMember(Description="What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.")
|
145
|
+
temperature;
|
146
|
+
/** @description An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. */
|
147
|
+
// @DataMember(Name="top_p")
|
148
|
+
// @ApiMember(Description="An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.")
|
149
|
+
top_p;
|
150
|
+
/** @description A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. A max of 128 functions are supported. */
|
151
|
+
// @DataMember(Name="tools")
|
152
|
+
// @ApiMember(Description="A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for. A max of 128 functions are supported.")
|
153
|
+
tools;
|
154
|
+
/** @description A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. */
|
155
|
+
// @DataMember(Name="user")
|
156
|
+
// @ApiMember(Description="A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse.")
|
157
|
+
user;
|
158
|
+
constructor(init) { Object.assign(this, init); }
|
57
159
|
}
|
58
160
|
// @DataContract
|
59
161
|
export class ResponseError {
|
162
|
+
// @DataMember(Order=1)
|
163
|
+
errorCode;
|
164
|
+
// @DataMember(Order=2)
|
165
|
+
fieldName;
|
166
|
+
// @DataMember(Order=3)
|
167
|
+
message;
|
168
|
+
// @DataMember(Order=4)
|
169
|
+
meta;
|
60
170
|
constructor(init) { Object.assign(this, init); }
|
61
171
|
}
|
62
172
|
// @DataContract
|
63
173
|
export class ResponseStatus {
|
174
|
+
// @DataMember(Order=1)
|
175
|
+
errorCode;
|
176
|
+
// @DataMember(Order=2)
|
177
|
+
message;
|
178
|
+
// @DataMember(Order=3)
|
179
|
+
stackTrace;
|
180
|
+
// @DataMember(Order=4)
|
181
|
+
errors;
|
182
|
+
// @DataMember(Order=5)
|
183
|
+
meta;
|
64
184
|
constructor(init) { Object.assign(this, init); }
|
65
185
|
}
|
66
186
|
// @DataContract
|
67
187
|
export class ChoiceMessage {
|
188
|
+
/** @description The contents of the message. */
|
189
|
+
// @DataMember(Name="content")
|
190
|
+
// @ApiMember(Description="The contents of the message.")
|
191
|
+
content;
|
192
|
+
/** @description The tool calls generated by the model, such as function calls. */
|
193
|
+
// @DataMember(Name="tool_calls")
|
194
|
+
// @ApiMember(Description="The tool calls generated by the model, such as function calls.")
|
195
|
+
tool_calls;
|
196
|
+
/** @description The role of the author of this message. */
|
197
|
+
// @DataMember(Name="role")
|
198
|
+
// @ApiMember(Description="The role of the author of this message.")
|
199
|
+
role;
|
68
200
|
constructor(init) { Object.assign(this, init); }
|
69
201
|
}
|
70
202
|
export class Choice {
|
203
|
+
/** @description The reason the model stopped generating tokens. This will be stop if the model hit a natural stop point or a provided stop sequence, length if the maximum number of tokens specified in the request was reached, content_filter if content was omitted due to a flag from our content filters, tool_calls if the model called a tool */
|
204
|
+
// @DataMember(Name="finish_reason")
|
205
|
+
// @ApiMember(Description="The reason the model stopped generating tokens. This will be stop if the model hit a natural stop point or a provided stop sequence, length if the maximum number of tokens specified in the request was reached, content_filter if content was omitted due to a flag from our content filters, tool_calls if the model called a tool")
|
206
|
+
finish_reason;
|
207
|
+
/** @description The index of the choice in the list of choices. */
|
208
|
+
// @DataMember(Name="index")
|
209
|
+
// @ApiMember(Description="The index of the choice in the list of choices.")
|
210
|
+
index;
|
211
|
+
/** @description A chat completion message generated by the model. */
|
212
|
+
// @DataMember(Name="message")
|
213
|
+
// @ApiMember(Description="A chat completion message generated by the model.")
|
214
|
+
message;
|
71
215
|
constructor(init) { Object.assign(this, init); }
|
72
216
|
}
|
73
217
|
/** @description Usage statistics for the completion request. */
|
74
218
|
// @Api(Description="Usage statistics for the completion request.")
|
75
219
|
// @DataContract
|
76
220
|
export class OpenAiUsage {
|
221
|
+
/** @description Number of tokens in the generated completion. */
|
222
|
+
// @DataMember(Name="completion_tokens")
|
223
|
+
// @ApiMember(Description="Number of tokens in the generated completion.")
|
224
|
+
completion_tokens;
|
225
|
+
/** @description Number of tokens in the prompt. */
|
226
|
+
// @DataMember(Name="prompt_tokens")
|
227
|
+
// @ApiMember(Description="Number of tokens in the prompt.")
|
228
|
+
prompt_tokens;
|
229
|
+
/** @description Total number of tokens used in the request (prompt + completion). */
|
230
|
+
// @DataMember(Name="total_tokens")
|
231
|
+
// @ApiMember(Description="Total number of tokens used in the request (prompt + completion).")
|
232
|
+
total_tokens;
|
77
233
|
constructor(init) { Object.assign(this, init); }
|
78
234
|
}
|
79
235
|
// @DataContract
|
80
236
|
export class OpenAiChatResponse {
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
237
|
+
/** @description A unique identifier for the chat completion. */
|
238
|
+
// @DataMember(Name="id")
|
239
|
+
// @ApiMember(Description="A unique identifier for the chat completion.")
|
240
|
+
id;
|
241
|
+
/** @description A list of chat completion choices. Can be more than one if n is greater than 1. */
|
242
|
+
// @DataMember(Name="choices")
|
243
|
+
// @ApiMember(Description="A list of chat completion choices. Can be more than one if n is greater than 1.")
|
244
|
+
choices = [];
|
245
|
+
/** @description The Unix timestamp (in seconds) of when the chat completion was created. */
|
246
|
+
// @DataMember(Name="created")
|
247
|
+
// @ApiMember(Description="The Unix timestamp (in seconds) of when the chat completion was created.")
|
248
|
+
created;
|
249
|
+
/** @description The model used for the chat completion. */
|
250
|
+
// @DataMember(Name="model")
|
251
|
+
// @ApiMember(Description="The model used for the chat completion.")
|
252
|
+
model;
|
253
|
+
/** @description This fingerprint represents the backend configuration that the model runs with. */
|
254
|
+
// @DataMember(Name="system_fingerprint")
|
255
|
+
// @ApiMember(Description="This fingerprint represents the backend configuration that the model runs with.")
|
256
|
+
system_fingerprint;
|
257
|
+
/** @description The object type, which is always chat.completion. */
|
258
|
+
// @DataMember(Name="object")
|
259
|
+
// @ApiMember(Description="The object type, which is always chat.completion.")
|
260
|
+
object;
|
261
|
+
/** @description Usage statistics for the completion request. */
|
262
|
+
// @DataMember(Name="usage")
|
263
|
+
// @ApiMember(Description="Usage statistics for the completion request.")
|
264
|
+
usage;
|
265
|
+
// @DataMember(Name="responseStatus")
|
266
|
+
responseStatus;
|
267
|
+
constructor(init) { Object.assign(this, init); }
|
88
268
|
}
|
89
269
|
/** @description Given a list of messages comprising a conversation, the model will return a response. */
|
90
270
|
// @Route("/v1/chat/completions", "POST")
|
91
271
|
// @Api(Description="Given a list of messages comprising a conversation, the model will return a response.")
|
92
272
|
export class OpenAiChatCompletion extends OpenAiChat {
|
273
|
+
/** @description Provide a unique identifier to track requests */
|
274
|
+
// @ApiMember(Description="Provide a unique identifier to track requests")
|
275
|
+
refId;
|
276
|
+
/** @description Specify which AI Provider to use */
|
277
|
+
// @ApiMember(Description="Specify which AI Provider to use")
|
278
|
+
provider;
|
279
|
+
/** @description Categorize like requests under a common group */
|
280
|
+
// @ApiMember(Description="Categorize like requests under a common group")
|
281
|
+
tag;
|
93
282
|
constructor(init) { super(init); Object.assign(this, init); }
|
94
283
|
getTypeName() { return 'OpenAiChatCompletion'; }
|
95
284
|
getMethod() { return 'POST'; }
|
package/dist/ts-ast.js
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
import { TypeScriptParser } from "./ts-parser.js";
|
2
|
+
export function toTypeScriptSrc(msg) {
|
3
|
+
msg = msg.trim();
|
4
|
+
const startPos = msg.indexOf("```typescript");
|
5
|
+
if (startPos >= 0) {
|
6
|
+
const ts = msg.substring(msg.indexOf('\n', startPos) + 1);
|
7
|
+
const src = ts.substring(0, ts.indexOf("```"));
|
8
|
+
return src;
|
9
|
+
}
|
10
|
+
if (msg.startsWith("//") || msg.startsWith("/*") || msg.startsWith("export ")
|
11
|
+
|| msg.startsWith("interface ") || msg.startsWith("class ") || msg.startsWith("type ")) {
|
12
|
+
return msg;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
// export function toAst(typescriptSrc:string) {
|
16
|
+
// const parsed = parseTypeScriptSource(typescriptSrc)
|
17
|
+
// return parsed
|
18
|
+
// }
|
19
|
+
// export function toAst(src:string) {
|
20
|
+
// const parsed = TypeScriptMultiParser.parse(src)
|
21
|
+
// return parsed
|
22
|
+
// }
|
23
|
+
export function toAst(src) {
|
24
|
+
const parser = new TypeScriptParser();
|
25
|
+
return parser.parse(src);
|
26
|
+
}
|
@@ -0,0 +1,170 @@
|
|
1
|
+
export class TypeScriptParser {
|
2
|
+
static CLASS_PATTERN = /class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?\s*{([^}]*)}/g;
|
3
|
+
static INTERFACE_PATTERN = /interface\s+(\w+)(?:\s+extends\s+(\w+))?\s*{([^}]*)}/g;
|
4
|
+
static ENUM_PATTERN = /enum\s+(\w+)\s*{([^}]*)}/g;
|
5
|
+
static PROPERTY_PATTERN = /(?:(?<modifier>private|public|protected|readonly)\s+)*(?<name>\w+)(?<optional>\?)?\s*:\s*(?<type>[\w<>[\],\s]+)(?<union>\|\s*[\w<>[\],|,\s]+)?\s*;?/;
|
6
|
+
static ENUM_MEMBER_PATTERN = /(\w+)\s*(?:=\s*("[^"]*"|'[^']*'|\d+|[^,\n]+))?\s*/;
|
7
|
+
classes = [];
|
8
|
+
interfaces = [];
|
9
|
+
enums = [];
|
10
|
+
getLineComment(line) {
|
11
|
+
// Check for single line comment at end of line
|
12
|
+
const singleLineMatch = line.match(/.*?\/\/\s*(.+)$/);
|
13
|
+
if (singleLineMatch) {
|
14
|
+
return singleLineMatch[1].trim();
|
15
|
+
}
|
16
|
+
// Check for inline multi-line comment
|
17
|
+
const multiLineMatch = line.match(/.*?\/\*\s*(.+?)\s*\*\//);
|
18
|
+
if (multiLineMatch) {
|
19
|
+
return multiLineMatch[1].trim();
|
20
|
+
}
|
21
|
+
return undefined;
|
22
|
+
}
|
23
|
+
getPreviousLine(content, position) {
|
24
|
+
const beforePosition = content.substring(0, position);
|
25
|
+
const lineNumber = beforePosition.split('\n').length;
|
26
|
+
if (lineNumber > 1) {
|
27
|
+
const lines = content.split('\n');
|
28
|
+
return lines[lineNumber - 2]; // -2 because array is 0-based and we want previous line
|
29
|
+
}
|
30
|
+
return undefined;
|
31
|
+
}
|
32
|
+
parseClassProperties(classBody) {
|
33
|
+
const props = [];
|
34
|
+
const lines = this.cleanBody(classBody).split('\n');
|
35
|
+
lines.forEach((line, index) => {
|
36
|
+
const match = line.match(TypeScriptParser.PROPERTY_PATTERN);
|
37
|
+
if (match?.groups) {
|
38
|
+
const member = {
|
39
|
+
modifier: match.groups.modifier,
|
40
|
+
name: match.groups.name,
|
41
|
+
type: match.groups.type.trim(),
|
42
|
+
optional: match.groups.optional === '?' || undefined,
|
43
|
+
};
|
44
|
+
// empty for properties with inline objects `salaryRange: {min:number, max:number};`
|
45
|
+
if (!member.type) {
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
const union = match.groups.union
|
49
|
+
? match.groups.union.split('|').filter(x => x.trim()).map((u) => u.trim())
|
50
|
+
: undefined;
|
51
|
+
if (union) {
|
52
|
+
member.union = union;
|
53
|
+
if (union.includes('null') || union.includes('undefined')) {
|
54
|
+
member.optional = true;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
const commments = [];
|
58
|
+
let previousLine = this.getPreviousLine(classBody, classBody.indexOf(line));
|
59
|
+
while (previousLine && !previousLine.match(TypeScriptParser.PROPERTY_PATTERN)) {
|
60
|
+
const comment = this.getLineComment(previousLine);
|
61
|
+
if (comment)
|
62
|
+
commments.unshift(comment);
|
63
|
+
previousLine = this.getPreviousLine(classBody, classBody.indexOf(previousLine));
|
64
|
+
}
|
65
|
+
const lineComment = this.getLineComment(line);
|
66
|
+
if (lineComment) {
|
67
|
+
commments.push(lineComment);
|
68
|
+
}
|
69
|
+
if (commments.length) {
|
70
|
+
member.comment = commments.join('\n');
|
71
|
+
}
|
72
|
+
props.push(member);
|
73
|
+
}
|
74
|
+
});
|
75
|
+
return props;
|
76
|
+
}
|
77
|
+
parseInterfaces(content) {
|
78
|
+
let match;
|
79
|
+
while ((match = TypeScriptParser.INTERFACE_PATTERN.exec(content))) {
|
80
|
+
const previousLine = this.getPreviousLine(content, match.index);
|
81
|
+
this.interfaces.push({
|
82
|
+
name: match[1],
|
83
|
+
extends: match[2],
|
84
|
+
comment: previousLine ? this.getLineComment(previousLine) : undefined,
|
85
|
+
properties: this.parseClassProperties(match[3])
|
86
|
+
});
|
87
|
+
}
|
88
|
+
}
|
89
|
+
parseClasses(content) {
|
90
|
+
let match;
|
91
|
+
while ((match = TypeScriptParser.CLASS_PATTERN.exec(content))) {
|
92
|
+
const previousLine = this.getPreviousLine(content, match.index);
|
93
|
+
this.classes.push({
|
94
|
+
name: match[1],
|
95
|
+
extends: match[2],
|
96
|
+
implements: match[3]?.split(',').map(i => i.trim()),
|
97
|
+
comment: previousLine ? this.getLineComment(previousLine) : undefined,
|
98
|
+
properties: this.parseClassProperties(match[4]),
|
99
|
+
});
|
100
|
+
}
|
101
|
+
}
|
102
|
+
parseEnumMembers(enumBody) {
|
103
|
+
const members = [];
|
104
|
+
const lines = enumBody.split('\n')
|
105
|
+
.map(line => line.trim())
|
106
|
+
.filter(line => line && !line.match(/^\s*\/\//));
|
107
|
+
let prevIntValue = 0;
|
108
|
+
lines.forEach((line, index) => {
|
109
|
+
const match = line.match(TypeScriptParser.ENUM_MEMBER_PATTERN);
|
110
|
+
if (match) {
|
111
|
+
const [, name, value] = match;
|
112
|
+
const member = {
|
113
|
+
name: name.trim()
|
114
|
+
};
|
115
|
+
if (value) {
|
116
|
+
// Remove quotes if present
|
117
|
+
const cleanValue = value.trim().replace(/^["']|["']$/g, '');
|
118
|
+
member.value = isNaN(Number(cleanValue)) ? cleanValue : Number(cleanValue);
|
119
|
+
}
|
120
|
+
else {
|
121
|
+
member.value = prevIntValue + 1;
|
122
|
+
}
|
123
|
+
if (typeof member.value === 'number') {
|
124
|
+
prevIntValue = member.value;
|
125
|
+
}
|
126
|
+
const previousLine = this.getPreviousLine(enumBody, enumBody.indexOf(line));
|
127
|
+
if (previousLine) {
|
128
|
+
member.comment = this.getLineComment(previousLine);
|
129
|
+
}
|
130
|
+
const lineComment = this.getLineComment(line);
|
131
|
+
if (lineComment) {
|
132
|
+
member.comment = member.comment ? member.comment + `\n${lineComment}` : lineComment;
|
133
|
+
}
|
134
|
+
members.push(member);
|
135
|
+
}
|
136
|
+
});
|
137
|
+
return members;
|
138
|
+
}
|
139
|
+
parseEnums(content) {
|
140
|
+
let match;
|
141
|
+
while ((match = TypeScriptParser.ENUM_PATTERN.exec(content))) {
|
142
|
+
const previousLine = this.getPreviousLine(content, match.index);
|
143
|
+
this.enums.push({
|
144
|
+
name: match[1],
|
145
|
+
comment: previousLine ? this.getLineComment(previousLine) : undefined,
|
146
|
+
members: this.parseEnumMembers(match[2])
|
147
|
+
});
|
148
|
+
}
|
149
|
+
}
|
150
|
+
cleanBody(body) {
|
151
|
+
return body
|
152
|
+
.split('\n')
|
153
|
+
.map(line => line.trim())
|
154
|
+
.filter(line => line.length > 0)
|
155
|
+
.join('\n');
|
156
|
+
}
|
157
|
+
parse(sourceCode) {
|
158
|
+
this.classes = [];
|
159
|
+
this.interfaces = [];
|
160
|
+
this.enums = [];
|
161
|
+
this.parseInterfaces(sourceCode);
|
162
|
+
this.parseClasses(sourceCode);
|
163
|
+
this.parseEnums(sourceCode);
|
164
|
+
return {
|
165
|
+
classes: this.classes,
|
166
|
+
interfaces: this.interfaces,
|
167
|
+
enums: this.enums
|
168
|
+
};
|
169
|
+
}
|
170
|
+
}
|
package/dist/tsd-gen.js
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
import { toPascalCase, toCamelCase } from "./utils.js";
|
2
|
+
export class TsdGenerator {
|
3
|
+
interfaces = [];
|
4
|
+
enums = [];
|
5
|
+
ast = { classes: [], interfaces: [], enums: [] };
|
6
|
+
clsToInterface(ast) {
|
7
|
+
const to = {
|
8
|
+
name: ast.name,
|
9
|
+
extends: ast.extends,
|
10
|
+
comment: ast.comment,
|
11
|
+
properties: ast.properties
|
12
|
+
};
|
13
|
+
return to;
|
14
|
+
}
|
15
|
+
toInterface(ast) {
|
16
|
+
const sb = [];
|
17
|
+
if (ast.comment) {
|
18
|
+
sb.push(ast.comment.split('\n').map(x => `// ${x}`).join('\n'));
|
19
|
+
}
|
20
|
+
const extend = ast.extends ? ` extends ${ast.extends}` : '';
|
21
|
+
sb.push(`export interface ${ast.name}${extend} {`);
|
22
|
+
for (const prop of ast.properties) {
|
23
|
+
if (prop.comment) {
|
24
|
+
sb.push(prop.comment.split('\n').map(x => ` // ${x}`).join('\n'));
|
25
|
+
}
|
26
|
+
sb.push(` ${prop.name}${prop.optional ? '?' : ''}: ${prop.type}`);
|
27
|
+
}
|
28
|
+
sb.push('}');
|
29
|
+
return sb.join('\n');
|
30
|
+
}
|
31
|
+
toEnum(ast) {
|
32
|
+
const sb = [];
|
33
|
+
if (ast.comment) {
|
34
|
+
sb.push(ast.comment.split('\n').map(x => `// ${x}`).join('\n'));
|
35
|
+
}
|
36
|
+
sb.push(`export enum ${ast.name} {`);
|
37
|
+
for (let i = 0; i < ast.members.length; i++) {
|
38
|
+
const member = ast.members[i];
|
39
|
+
if (member.comment) {
|
40
|
+
sb.push(member.comment.split('\n').map(x => ` // ${x}`).join('\n'));
|
41
|
+
}
|
42
|
+
const value = typeof member.value === 'string'
|
43
|
+
? ` = '${member.value}'`
|
44
|
+
: member.value !== (i + 1) ? ` = ${member.value}` : '';
|
45
|
+
sb.push(` ${member.name}${value},`);
|
46
|
+
}
|
47
|
+
sb.push('}');
|
48
|
+
return sb.join('\n');
|
49
|
+
}
|
50
|
+
generate(ast) {
|
51
|
+
this.ast = ast;
|
52
|
+
const sb = [];
|
53
|
+
for (const cls of ast.enums ?? []) {
|
54
|
+
sb.push(this.toEnum(cls));
|
55
|
+
sb.push('');
|
56
|
+
}
|
57
|
+
for (const cls of ast.interfaces ?? []) {
|
58
|
+
sb.push(this.toInterface(cls));
|
59
|
+
sb.push('');
|
60
|
+
}
|
61
|
+
for (const cls of ast.classes ?? []) {
|
62
|
+
const iface = this.clsToInterface(cls);
|
63
|
+
sb.push(this.toInterface(iface));
|
64
|
+
sb.push('');
|
65
|
+
}
|
66
|
+
const tsd = sb.join('\n');
|
67
|
+
return tsd;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
export class TsdDataModelGenerator extends TsdGenerator {
|
71
|
+
generate(ast) {
|
72
|
+
function convertProps(properties) {
|
73
|
+
properties?.forEach(prop => {
|
74
|
+
prop.name = toCamelCase(prop.name);
|
75
|
+
if (prop.type === 'User') {
|
76
|
+
prop.name = 'userId';
|
77
|
+
prop.type = 'string';
|
78
|
+
}
|
79
|
+
if (prop.type === 'User[]') {
|
80
|
+
if (prop.name.endsWith('s')) {
|
81
|
+
prop.name = prop.name.slice(0, -1) + 'Ids';
|
82
|
+
}
|
83
|
+
prop.type = 'string[]';
|
84
|
+
}
|
85
|
+
});
|
86
|
+
}
|
87
|
+
ast.classes?.forEach(cls => {
|
88
|
+
cls.name = toPascalCase(cls.name);
|
89
|
+
convertProps(cls.properties);
|
90
|
+
});
|
91
|
+
ast.interfaces?.forEach(cls => {
|
92
|
+
cls.name = toPascalCase(cls.name);
|
93
|
+
convertProps(cls.properties);
|
94
|
+
});
|
95
|
+
ast.enums?.forEach(e => {
|
96
|
+
e.name = toPascalCase(e.name);
|
97
|
+
e.members?.forEach(m => {
|
98
|
+
m.name = toPascalCase(m.name);
|
99
|
+
});
|
100
|
+
});
|
101
|
+
if (ast.classes) {
|
102
|
+
ast.classes = ast.classes.filter(x => x.name !== 'User');
|
103
|
+
}
|
104
|
+
if (ast.interfaces) {
|
105
|
+
ast.interfaces = ast.interfaces.filter(x => x.name !== 'User');
|
106
|
+
}
|
107
|
+
return super.generate(ast);
|
108
|
+
}
|
109
|
+
}
|