Skip to content

Commit aa383f1

Browse files
committed
feat: add nodejs commonjs module support
1 parent 6c43dbf commit aa383f1

File tree

2 files changed

+157
-2
lines changed

2 files changed

+157
-2
lines changed

cjs/index.js

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
const fetchEventSource = require('@microsoft/fetch-event-source');
2+
const fetch = require('node-fetch');
3+
4+
module.exports = class Api2d {
5+
// 设置key和apiBaseUrl
6+
constructor(key = null, apiBaseUrl = null, timeout = 60000) {
7+
this.key = key;
8+
this.apiBaseUrl = apiBaseUrl || (key && key.startsWith('fk') ? 'https://stream.api2d.net' : 'https://api.openai.com');
9+
this.timeout = timeout;
10+
this.controller = new AbortController();
11+
}
12+
13+
// set key
14+
setKey(key) {
15+
this.key = key;
16+
}
17+
18+
// set apiBaseUrl
19+
setApiBaseUrl(apiBaseUrl) {
20+
this.apiBaseUrl = apiBaseUrl;
21+
}
22+
23+
setTimeout(timeout) {
24+
this.timeout = parseInt(timeout) || 60 * 1000;
25+
}
26+
27+
abort() {
28+
this.controller.abort();
29+
}
30+
31+
// Completion
32+
async completion(options) {
33+
// 拼接目标URL
34+
const url = this.apiBaseUrl + '/v1/chat/completions';
35+
// 拼接headers
36+
const headers = {
37+
'Content-Type': 'application/json',
38+
Authorization: 'Bearer ' + this.key
39+
};
40+
41+
const { onMessage, onEnd, model, ...restOptions } = options;
42+
43+
// 如果是流式返回,且有回调函数
44+
if (restOptions.stream && onMessage) {
45+
// 返回一个 Promise
46+
return new Promise(async (resolve, reject) => {
47+
try {
48+
let chars = '';
49+
console.log('in stream');
50+
// 使用 fetchEventSource 发送请求
51+
const timeout_handle = setTimeout(() => {
52+
this.controller.abort();
53+
// throw new Error( "Timeout "+ this.timeout );
54+
reject(new Error(`[408]:Timeout by ${this.timeout} ms`));
55+
}, this.timeout);
56+
const response = await fetchEventSource(url, {
57+
signal: this.controller.signal,
58+
method: 'POST',
59+
headers: { ...headers, Accept: 'text/event-stream' },
60+
body: JSON.stringify({ ...restOptions, model: model || 'gpt-3.5-turbo' }),
61+
async onopen(response) {
62+
if (response.status != 200) {
63+
throw new Error(`[${response.status}]:${response.statusText}`);
64+
}
65+
},
66+
onmessage: (e) => {
67+
if (timeout_handle) {
68+
clearTimeout(timeout_handle);
69+
}
70+
if (e.data == '[DONE]') {
71+
// console.log( 'DONE' );
72+
if (onEnd) onEnd(chars);
73+
resolve(chars);
74+
} else {
75+
// console.log( e.data );
76+
const event = JSON.parse(e.data);
77+
if (event.choices[0].delta.content) chars += event.choices[0].delta.content;
78+
if (onMessage) onMessage(chars);
79+
}
80+
},
81+
onerror: (error) => {
82+
console.log(error);
83+
throw new Error(String(error)?.match(/\[(\d+)\]/)?.[1] ? error : `[500]:${error}`);
84+
}
85+
});
86+
87+
// const ret = await response.json();
88+
} catch (error) {
89+
console.log(error);
90+
reject(error);
91+
}
92+
});
93+
} else {
94+
// 使用 fetch 发送请求
95+
const response = await fetch(url, {
96+
signal: this.controller.signal,
97+
method: 'POST',
98+
headers: headers,
99+
body: JSON.stringify({ ...restOptions, model: model || 'gpt-3.5-turbo' })
100+
});
101+
const timeout_handle = setTimeout(() => {
102+
this.controller.abort();
103+
}, this.timeout);
104+
const ret = await response.json();
105+
clearTimeout(timeout_handle);
106+
return ret;
107+
}
108+
}
109+
110+
async embeddings(options) {
111+
// 拼接目标URL
112+
const url = this.apiBaseUrl + '/v1/embeddings';
113+
// 拼接headers
114+
const headers = {
115+
'Content-Type': 'application/json',
116+
Authorization: 'Bearer ' + this.key
117+
};
118+
const { model, ...restOptions } = options;
119+
// 使用 fetch 发送请求
120+
const response = await fetch(url, {
121+
signal: this.controller.signal,
122+
method: 'POST',
123+
headers: headers,
124+
body: JSON.stringify({ ...restOptions, model: model || 'text-embedding-ada-002' })
125+
});
126+
const timeout_handle = setTimeout(() => {
127+
this.controller.abort();
128+
}, this.timeout);
129+
const ret = await response.json();
130+
clearTimeout(timeout_handle);
131+
return ret;
132+
}
133+
134+
async billing() {
135+
const url = this.apiBaseUrl + '/dashboard/billing/credit_grants';
136+
const headers = {
137+
'Content-Type': 'application/json',
138+
Authorization: 'Bearer ' + this.key
139+
};
140+
const response = await fetch(url, {
141+
signal: this.controller.signal,
142+
method: 'GET',
143+
headers: headers
144+
});
145+
const timeout_handle = setTimeout(() => {
146+
this.controller.abort();
147+
}, this.timeout);
148+
const ret = await response.json();
149+
clearTimeout(timeout_handle);
150+
return ret;
151+
}
152+
};

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
"name": "api2d",
33
"version": "0.1.11",
44
"description": "pure browser sdk for api2d and openai",
5-
"main": "index.js",
5+
"main": "cjs/index.js",
6+
"module": "index.js",
7+
"types": "index.d.ts",
68
"repository": "https://github.com/easychen/api2d-js",
79
"author": "EasyChen",
810
"license": "MIT",
911
"private": false,
1012
"dependencies": {
11-
"@microsoft/fetch-event-source": "^2.0.1"
13+
"@microsoft/fetch-event-source": "^2.0.1",
14+
"node-fetch": "^2.6.9"
1215
}
1316
}

0 commit comments

Comments
 (0)