@effect-ak/tg-bot-client 1.2.0 → 1.3.0

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/index.cjs CHANGED
@@ -24,9 +24,7 @@ __export(index_exports, {
24
24
  TG_BOT_API_URL: () => TG_BOT_API_URL,
25
25
  TgBotClientError: () => TgBotClientError,
26
26
  executeTgBotMethod: () => executeTgBotMethod,
27
- getBaseUrl: () => getBaseUrl,
28
27
  getFile: () => getFile,
29
- getFileBytes: () => getFileBytes,
30
28
  isFileContent: () => isFileContent,
31
29
  isMessageEffect: () => isMessageEffect,
32
30
  isTgBotApiResponse: () => isTgBotApiResponse,
@@ -52,28 +50,6 @@ var TgBotClientError = class extends Error {
52
50
  var isFileContent = (input) => typeof input == "object" && input != null && "file_content" in input && input.file_content instanceof Uint8Array && "file_name" in input && typeof input.file_name == "string";
53
51
  var isTgBotApiResponse = (input) => typeof input == "object" && input != null && "ok" in input && typeof input.ok == "boolean";
54
52
 
55
- // src/const.ts
56
- var TG_BOT_API_URL = "https://api.telegram.org";
57
- var MESSAGE_EFFECTS = {
58
- "\u{1F525}": "5104841245755180586",
59
- "\u{1F44D}": "5107584321108051014",
60
- "\u{1F44E}": "5104858069142078462",
61
- "\u2764\uFE0F": "5159385139981059251",
62
- "\u{1F389}": "5046509860389126442",
63
- "\u{1F4A9}": "5046589136895476101"
64
- };
65
- var messageEffectIdCodes = Object.keys(
66
- MESSAGE_EFFECTS
67
- );
68
- var isMessageEffect = (input) => {
69
- return typeof input === "string" && input in MESSAGE_EFFECTS;
70
- };
71
-
72
- // src/config.ts
73
- var getBaseUrl = (config) => {
74
- return config?.baseUrl ?? TG_BOT_API_URL;
75
- };
76
-
77
53
  // src/utils.ts
78
54
  var snakeToCamel = (str) => {
79
55
  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
@@ -82,12 +58,10 @@ var snakeToCamel = (str) => {
82
58
  // src/execute.ts
83
59
  async function executeTgBotMethod(params) {
84
60
  const { config, method, input } = params;
85
- const baseUrl = getBaseUrl(config);
86
- const botToken = config.botToken;
87
61
  let httpResponse;
88
62
  try {
89
63
  httpResponse = await fetch(
90
- `${baseUrl}/bot${botToken}/${snakeToCamel(method)}`,
64
+ `${config.base_url}/bot${config.bot_token}/${snakeToCamel(method)}`,
91
65
  {
92
66
  body: makePayload(input) ?? null,
93
67
  method: "POST"
@@ -140,8 +114,8 @@ var makePayload = (body) => {
140
114
  };
141
115
 
142
116
  // src/client-file.ts
143
- var getFileBytes = async (fileId, context) => {
144
- const { config, execute } = context;
117
+ var getFile = async (params) => {
118
+ const { fileId, config, execute } = params;
145
119
  const response = await execute("get_file", { file_id: fileId });
146
120
  const file_path = response.file_path;
147
121
  if (!file_path || file_path.length === 0) {
@@ -153,9 +127,7 @@ var getFileBytes = async (fileId, context) => {
153
127
  });
154
128
  }
155
129
  const file_name = file_path.replaceAll("/", "-");
156
- const baseUrl = getBaseUrl(config);
157
- const botToken = config.botToken;
158
- const url = `${baseUrl}/file/bot${botToken}/${file_path}`;
130
+ const url = `${config.base_url}/file/bot${config.bot_token}/${file_path}`;
159
131
  let content;
160
132
  try {
161
133
  content = await fetch(url).then((_) => _.arrayBuffer());
@@ -165,29 +137,49 @@ var getFileBytes = async (fileId, context) => {
165
137
  });
166
138
  }
167
139
  const base64String = () => Buffer.from(content).toString("base64");
140
+ const file = () => new File([content], file_name, {
141
+ ...params.type ? { type: params.type } : {}
142
+ });
168
143
  return {
169
144
  content,
170
145
  file_name,
171
- base64String
146
+ base64String,
147
+ file
172
148
  };
173
149
  };
174
- var getFile = async (input, context) => {
175
- const { content, file_name } = await getFileBytes(input.fileId, context);
176
- return new File([content], file_name, {
177
- ...input.type ? { type: input.type } : {}
178
- });
150
+
151
+ // src/const.ts
152
+ var TG_BOT_API_URL = "https://api.telegram.org";
153
+ var MESSAGE_EFFECTS = {
154
+ "\u{1F525}": "5104841245755180586",
155
+ "\u{1F44D}": "5107584321108051014",
156
+ "\u{1F44E}": "5104858069142078462",
157
+ "\u2764\uFE0F": "5159385139981059251",
158
+ "\u{1F389}": "5046509860389126442",
159
+ "\u{1F4A9}": "5046589136895476101"
160
+ };
161
+ var messageEffectIdCodes = Object.keys(
162
+ MESSAGE_EFFECTS
163
+ );
164
+ var isMessageEffect = (input) => {
165
+ return typeof input === "string" && input in MESSAGE_EFFECTS;
179
166
  };
180
167
 
181
168
  // src/client.ts
182
169
  function makeTgBotClient(config) {
183
170
  const tgConfig = {
184
- botToken: config.bot_token,
185
- ...config.base_url ? { baseUrl: config.base_url } : {}
171
+ bot_token: config.bot_token,
172
+ base_url: config.base_url ?? TG_BOT_API_URL
186
173
  };
187
- const execute = (method, input) => executeTgBotMethod({ config: tgConfig, method, input });
174
+ const execute = (method, input) => executeTgBotMethod({
175
+ config: tgConfig,
176
+ method,
177
+ input
178
+ });
188
179
  return {
180
+ config: tgConfig,
189
181
  execute,
190
- getFile: (input) => getFile(input, { config: tgConfig, execute })
182
+ getFile: (input) => getFile({ ...input, config: tgConfig, execute })
191
183
  };
192
184
  }
193
185
  // Annotate the CommonJS export names for ESM import in node:
@@ -196,9 +188,7 @@ function makeTgBotClient(config) {
196
188
  TG_BOT_API_URL,
197
189
  TgBotClientError,
198
190
  executeTgBotMethod,
199
- getBaseUrl,
200
191
  getFile,
201
- getFileBytes,
202
192
  isFileContent,
203
193
  isMessageEffect,
204
194
  isTgBotApiResponse,
package/dist/index.d.cts CHANGED
@@ -1,43 +1,42 @@
1
1
  import { Api } from '@effect-ak/tg-bot-api';
2
2
 
3
- interface TgBotConfig {
4
- botToken: string;
5
- baseUrl?: string;
3
+ interface TgFile {
4
+ readonly content: ArrayBuffer;
5
+ readonly file_name: string;
6
+ readonly base64String: () => string;
7
+ readonly file: () => File;
6
8
  }
7
- declare const getBaseUrl: (config?: Pick<TgBotConfig, "baseUrl">) => string;
8
-
9
- declare function executeTgBotMethod<M extends keyof Api>(params: {
10
- config: TgBotConfig;
11
- method: M;
12
- input: Parameters<Api[M]>[0];
13
- }): Promise<ReturnType<Api[M]>>;
14
- declare const makePayload: (body: object) => FormData | undefined;
15
-
16
- interface GetFile {
9
+ declare const getFile: (params: {
17
10
  fileId: string;
11
+ config: {
12
+ bot_token: string;
13
+ base_url: string;
14
+ };
18
15
  type?: string;
19
- }
20
- interface FileBytes {
21
- content: ArrayBuffer;
22
- file_name: string;
23
- base64String: () => string;
24
- }
25
- interface FileContext {
26
- config: TgBotConfig;
27
- execute: <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
28
- }
29
- declare const getFileBytes: (fileId: string, context: FileContext) => Promise<FileBytes>;
30
- declare const getFile: (input: GetFile, context: FileContext) => Promise<File>;
16
+ execute: ExecuteMethod;
17
+ }) => Promise<TgFile>;
31
18
 
32
19
  interface TgBotClient {
33
- readonly execute: <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
34
- readonly getFile: (input: GetFile) => Promise<File>;
20
+ readonly config: Required<TgClientConfig>;
21
+ readonly execute: ExecuteMethod;
22
+ readonly getFile: (input: {
23
+ fileId: string;
24
+ type?: string;
25
+ }) => Promise<TgFile>;
35
26
  }
36
- interface MakeTgClient {
27
+ interface TgClientConfig {
37
28
  bot_token: string;
38
29
  base_url?: string;
39
30
  }
40
- declare function makeTgBotClient(config: MakeTgClient): TgBotClient;
31
+ declare function makeTgBotClient(config: TgClientConfig): TgBotClient;
32
+
33
+ type ExecuteMethod = <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
34
+ declare function executeTgBotMethod<M extends keyof Api>(params: {
35
+ config: Required<TgClientConfig>;
36
+ method: M;
37
+ input: Parameters<Api[M]>[0];
38
+ }): Promise<ReturnType<Api[M]>>;
39
+ declare const makePayload: (body: object) => FormData | undefined;
41
40
 
42
41
  type ErrorReason = {
43
42
  _tag: "NotOkResponse";
@@ -95,4 +94,4 @@ declare const isMessageEffect: (input: unknown) => input is MessageEffect;
95
94
 
96
95
  declare const snakeToCamel: (str: string) => string;
97
96
 
98
- export { type FileBytes, type FileContent, type GetFile, MESSAGE_EFFECTS, type MakeTgClient, type MessageEffect, TG_BOT_API_URL, type TgBotApiResponseSchema, type TgBotClient, TgBotClientError, type TgBotConfig, executeTgBotMethod, getBaseUrl, getFile, getFileBytes, isFileContent, isMessageEffect, isTgBotApiResponse, makePayload, makeTgBotClient, messageEffectIdCodes, snakeToCamel };
97
+ export { type ExecuteMethod, type FileContent, MESSAGE_EFFECTS, type MessageEffect, TG_BOT_API_URL, type TgBotApiResponseSchema, type TgBotClient, TgBotClientError, type TgClientConfig, type TgFile, executeTgBotMethod, getFile, isFileContent, isMessageEffect, isTgBotApiResponse, makePayload, makeTgBotClient, messageEffectIdCodes, snakeToCamel };
package/dist/index.d.ts CHANGED
@@ -1,43 +1,42 @@
1
1
  import { Api } from '@effect-ak/tg-bot-api';
2
2
 
3
- interface TgBotConfig {
4
- botToken: string;
5
- baseUrl?: string;
3
+ interface TgFile {
4
+ readonly content: ArrayBuffer;
5
+ readonly file_name: string;
6
+ readonly base64String: () => string;
7
+ readonly file: () => File;
6
8
  }
7
- declare const getBaseUrl: (config?: Pick<TgBotConfig, "baseUrl">) => string;
8
-
9
- declare function executeTgBotMethod<M extends keyof Api>(params: {
10
- config: TgBotConfig;
11
- method: M;
12
- input: Parameters<Api[M]>[0];
13
- }): Promise<ReturnType<Api[M]>>;
14
- declare const makePayload: (body: object) => FormData | undefined;
15
-
16
- interface GetFile {
9
+ declare const getFile: (params: {
17
10
  fileId: string;
11
+ config: {
12
+ bot_token: string;
13
+ base_url: string;
14
+ };
18
15
  type?: string;
19
- }
20
- interface FileBytes {
21
- content: ArrayBuffer;
22
- file_name: string;
23
- base64String: () => string;
24
- }
25
- interface FileContext {
26
- config: TgBotConfig;
27
- execute: <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
28
- }
29
- declare const getFileBytes: (fileId: string, context: FileContext) => Promise<FileBytes>;
30
- declare const getFile: (input: GetFile, context: FileContext) => Promise<File>;
16
+ execute: ExecuteMethod;
17
+ }) => Promise<TgFile>;
31
18
 
32
19
  interface TgBotClient {
33
- readonly execute: <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
34
- readonly getFile: (input: GetFile) => Promise<File>;
20
+ readonly config: Required<TgClientConfig>;
21
+ readonly execute: ExecuteMethod;
22
+ readonly getFile: (input: {
23
+ fileId: string;
24
+ type?: string;
25
+ }) => Promise<TgFile>;
35
26
  }
36
- interface MakeTgClient {
27
+ interface TgClientConfig {
37
28
  bot_token: string;
38
29
  base_url?: string;
39
30
  }
40
- declare function makeTgBotClient(config: MakeTgClient): TgBotClient;
31
+ declare function makeTgBotClient(config: TgClientConfig): TgBotClient;
32
+
33
+ type ExecuteMethod = <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
34
+ declare function executeTgBotMethod<M extends keyof Api>(params: {
35
+ config: Required<TgClientConfig>;
36
+ method: M;
37
+ input: Parameters<Api[M]>[0];
38
+ }): Promise<ReturnType<Api[M]>>;
39
+ declare const makePayload: (body: object) => FormData | undefined;
41
40
 
42
41
  type ErrorReason = {
43
42
  _tag: "NotOkResponse";
@@ -95,4 +94,4 @@ declare const isMessageEffect: (input: unknown) => input is MessageEffect;
95
94
 
96
95
  declare const snakeToCamel: (str: string) => string;
97
96
 
98
- export { type FileBytes, type FileContent, type GetFile, MESSAGE_EFFECTS, type MakeTgClient, type MessageEffect, TG_BOT_API_URL, type TgBotApiResponseSchema, type TgBotClient, TgBotClientError, type TgBotConfig, executeTgBotMethod, getBaseUrl, getFile, getFileBytes, isFileContent, isMessageEffect, isTgBotApiResponse, makePayload, makeTgBotClient, messageEffectIdCodes, snakeToCamel };
97
+ export { type ExecuteMethod, type FileContent, MESSAGE_EFFECTS, type MessageEffect, TG_BOT_API_URL, type TgBotApiResponseSchema, type TgBotClient, TgBotClientError, type TgClientConfig, type TgFile, executeTgBotMethod, getFile, isFileContent, isMessageEffect, isTgBotApiResponse, makePayload, makeTgBotClient, messageEffectIdCodes, snakeToCamel };
package/dist/index.js CHANGED
@@ -13,28 +13,6 @@ var TgBotClientError = class extends Error {
13
13
  var isFileContent = (input) => typeof input == "object" && input != null && "file_content" in input && input.file_content instanceof Uint8Array && "file_name" in input && typeof input.file_name == "string";
14
14
  var isTgBotApiResponse = (input) => typeof input == "object" && input != null && "ok" in input && typeof input.ok == "boolean";
15
15
 
16
- // src/const.ts
17
- var TG_BOT_API_URL = "https://api.telegram.org";
18
- var MESSAGE_EFFECTS = {
19
- "\u{1F525}": "5104841245755180586",
20
- "\u{1F44D}": "5107584321108051014",
21
- "\u{1F44E}": "5104858069142078462",
22
- "\u2764\uFE0F": "5159385139981059251",
23
- "\u{1F389}": "5046509860389126442",
24
- "\u{1F4A9}": "5046589136895476101"
25
- };
26
- var messageEffectIdCodes = Object.keys(
27
- MESSAGE_EFFECTS
28
- );
29
- var isMessageEffect = (input) => {
30
- return typeof input === "string" && input in MESSAGE_EFFECTS;
31
- };
32
-
33
- // src/config.ts
34
- var getBaseUrl = (config) => {
35
- return config?.baseUrl ?? TG_BOT_API_URL;
36
- };
37
-
38
16
  // src/utils.ts
39
17
  var snakeToCamel = (str) => {
40
18
  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
@@ -43,12 +21,10 @@ var snakeToCamel = (str) => {
43
21
  // src/execute.ts
44
22
  async function executeTgBotMethod(params) {
45
23
  const { config, method, input } = params;
46
- const baseUrl = getBaseUrl(config);
47
- const botToken = config.botToken;
48
24
  let httpResponse;
49
25
  try {
50
26
  httpResponse = await fetch(
51
- `${baseUrl}/bot${botToken}/${snakeToCamel(method)}`,
27
+ `${config.base_url}/bot${config.bot_token}/${snakeToCamel(method)}`,
52
28
  {
53
29
  body: makePayload(input) ?? null,
54
30
  method: "POST"
@@ -101,8 +77,8 @@ var makePayload = (body) => {
101
77
  };
102
78
 
103
79
  // src/client-file.ts
104
- var getFileBytes = async (fileId, context) => {
105
- const { config, execute } = context;
80
+ var getFile = async (params) => {
81
+ const { fileId, config, execute } = params;
106
82
  const response = await execute("get_file", { file_id: fileId });
107
83
  const file_path = response.file_path;
108
84
  if (!file_path || file_path.length === 0) {
@@ -114,9 +90,7 @@ var getFileBytes = async (fileId, context) => {
114
90
  });
115
91
  }
116
92
  const file_name = file_path.replaceAll("/", "-");
117
- const baseUrl = getBaseUrl(config);
118
- const botToken = config.botToken;
119
- const url = `${baseUrl}/file/bot${botToken}/${file_path}`;
93
+ const url = `${config.base_url}/file/bot${config.bot_token}/${file_path}`;
120
94
  let content;
121
95
  try {
122
96
  content = await fetch(url).then((_) => _.arrayBuffer());
@@ -126,29 +100,49 @@ var getFileBytes = async (fileId, context) => {
126
100
  });
127
101
  }
128
102
  const base64String = () => Buffer.from(content).toString("base64");
103
+ const file = () => new File([content], file_name, {
104
+ ...params.type ? { type: params.type } : {}
105
+ });
129
106
  return {
130
107
  content,
131
108
  file_name,
132
- base64String
109
+ base64String,
110
+ file
133
111
  };
134
112
  };
135
- var getFile = async (input, context) => {
136
- const { content, file_name } = await getFileBytes(input.fileId, context);
137
- return new File([content], file_name, {
138
- ...input.type ? { type: input.type } : {}
139
- });
113
+
114
+ // src/const.ts
115
+ var TG_BOT_API_URL = "https://api.telegram.org";
116
+ var MESSAGE_EFFECTS = {
117
+ "\u{1F525}": "5104841245755180586",
118
+ "\u{1F44D}": "5107584321108051014",
119
+ "\u{1F44E}": "5104858069142078462",
120
+ "\u2764\uFE0F": "5159385139981059251",
121
+ "\u{1F389}": "5046509860389126442",
122
+ "\u{1F4A9}": "5046589136895476101"
123
+ };
124
+ var messageEffectIdCodes = Object.keys(
125
+ MESSAGE_EFFECTS
126
+ );
127
+ var isMessageEffect = (input) => {
128
+ return typeof input === "string" && input in MESSAGE_EFFECTS;
140
129
  };
141
130
 
142
131
  // src/client.ts
143
132
  function makeTgBotClient(config) {
144
133
  const tgConfig = {
145
- botToken: config.bot_token,
146
- ...config.base_url ? { baseUrl: config.base_url } : {}
134
+ bot_token: config.bot_token,
135
+ base_url: config.base_url ?? TG_BOT_API_URL
147
136
  };
148
- const execute = (method, input) => executeTgBotMethod({ config: tgConfig, method, input });
137
+ const execute = (method, input) => executeTgBotMethod({
138
+ config: tgConfig,
139
+ method,
140
+ input
141
+ });
149
142
  return {
143
+ config: tgConfig,
150
144
  execute,
151
- getFile: (input) => getFile(input, { config: tgConfig, execute })
145
+ getFile: (input) => getFile({ ...input, config: tgConfig, execute })
152
146
  };
153
147
  }
154
148
  export {
@@ -156,9 +150,7 @@ export {
156
150
  TG_BOT_API_URL,
157
151
  TgBotClientError,
158
152
  executeTgBotMethod,
159
- getBaseUrl,
160
153
  getFile,
161
- getFileBytes,
162
154
  isFileContent,
163
155
  isMessageEffect,
164
156
  isTgBotApiResponse,
package/package.json CHANGED
@@ -2,8 +2,11 @@
2
2
  "name": "@effect-ak/tg-bot-client",
3
3
  "type": "module",
4
4
  "description": "Type-safe HTTP client for Telegram Bot API",
5
- "version": "1.2.0",
5
+ "version": "1.3.0",
6
6
  "license": "MIT",
7
+ "scripts": {
8
+ "build": "tsup"
9
+ },
7
10
  "author": {
8
11
  "name": "Aleksandr Kondaurov",
9
12
  "email": "kondaurov.dev@gmail.com"
@@ -31,8 +34,5 @@
31
34
  },
32
35
  "dependencies": {
33
36
  "@effect-ak/tg-bot-api": "0.9.2"
34
- },
35
- "scripts": {
36
- "build": "tsup"
37
37
  }
38
- }
38
+ }
@@ -1,32 +1,23 @@
1
- import type { Api } from "@effect-ak/tg-bot-api"
2
1
  import { TgBotClientError } from "./errors"
3
- import type { TgBotConfig } from "./config"
4
- import { getBaseUrl } from "./config"
2
+ import type { ExecuteMethod } from "./execute"
5
3
 
6
- export interface GetFile {
7
- fileId: string
8
- type?: string
9
- }
10
-
11
- export interface FileBytes {
12
- content: ArrayBuffer
13
- file_name: string
14
- base64String: () => string
15
- }
16
-
17
- interface FileContext {
18
- config: TgBotConfig
19
- execute: <M extends keyof Api>(
20
- method: M,
21
- input: Parameters<Api[M]>[0]
22
- ) => Promise<ReturnType<Api[M]>>
4
+ export interface TgFile {
5
+ readonly content: ArrayBuffer
6
+ readonly file_name: string
7
+ readonly base64String: () => string
8
+ readonly file: () => File
23
9
  }
24
10
 
25
- export const getFileBytes = async (
26
- fileId: string,
27
- context: FileContext
28
- ): Promise<FileBytes> => {
29
- const { config, execute } = context
11
+ export const getFile = async (params: {
12
+ fileId: string
13
+ config: {
14
+ bot_token: string
15
+ base_url: string
16
+ }
17
+ type?: string
18
+ execute: ExecuteMethod
19
+ }): Promise<TgFile> => {
20
+ const { fileId, config, execute } = params
30
21
  const response = await execute("get_file", { file_id: fileId })
31
22
  const file_path = response.file_path
32
23
 
@@ -40,9 +31,7 @@ export const getFileBytes = async (
40
31
  }
41
32
 
42
33
  const file_name = file_path.replaceAll("/", "-")
43
- const baseUrl = getBaseUrl(config)
44
- const botToken = config.botToken
45
- const url = `${baseUrl}/file/bot${botToken}/${file_path}`
34
+ const url = `${config.base_url}/file/bot${config.bot_token}/${file_path}`
46
35
 
47
36
  let content: ArrayBuffer
48
37
  try {
@@ -54,20 +43,15 @@ export const getFileBytes = async (
54
43
  }
55
44
 
56
45
  const base64String = () => Buffer.from(content).toString("base64")
46
+ const file = () =>
47
+ new File([content], file_name, {
48
+ ...(params.type ? { type: params.type } : {})
49
+ })
57
50
 
58
51
  return {
59
52
  content,
60
53
  file_name,
61
- base64String
54
+ base64String,
55
+ file
62
56
  }
63
57
  }
64
-
65
- export const getFile = async (
66
- input: GetFile,
67
- context: FileContext
68
- ): Promise<File> => {
69
- const { content, file_name } = await getFileBytes(input.fileId, context)
70
- return new File([content], file_name, {
71
- ...(input.type ? { type: input.type } : {})
72
- })
73
- }
package/src/client.ts CHANGED
@@ -1,34 +1,35 @@
1
1
  import type { Api } from "@effect-ak/tg-bot-api"
2
- import { executeTgBotMethod } from "./execute"
3
- import type { TgBotConfig } from "./config"
4
- import { getFile as getFileImpl, type GetFile } from "./client-file"
2
+ import { executeTgBotMethod, type ExecuteMethod } from "./execute"
3
+ import { getFile as getFileImpl, type TgFile } from "./client-file"
4
+ import { TG_BOT_API_URL } from "./const"
5
5
 
6
6
  export interface TgBotClient {
7
- readonly execute: <M extends keyof Api>(
8
- method: M,
9
- input: Parameters<Api[M]>[0]
10
- ) => Promise<ReturnType<Api[M]>>
11
- readonly getFile: (input: GetFile) => Promise<File>
7
+ readonly config: Required<TgClientConfig>
8
+ readonly execute: ExecuteMethod
9
+ readonly getFile: (input: { fileId: string; type?: string }) => Promise<TgFile>
12
10
  }
13
11
 
14
- export interface MakeTgClient {
12
+ export interface TgClientConfig {
15
13
  bot_token: string
16
14
  base_url?: string
17
15
  }
18
16
 
19
- export function makeTgBotClient(config: MakeTgClient): TgBotClient {
20
- const tgConfig: TgBotConfig = {
21
- botToken: config.bot_token,
22
- ...(config.base_url ? { baseUrl: config.base_url } : {})
17
+ export function makeTgBotClient(config: TgClientConfig): TgBotClient {
18
+ const tgConfig = {
19
+ bot_token: config.bot_token,
20
+ base_url: config.base_url ?? TG_BOT_API_URL
23
21
  }
24
22
 
25
23
  const execute = <M extends keyof Api>(
26
24
  method: M,
27
25
  input: Parameters<Api[M]>[0]
28
- ) => executeTgBotMethod({ config: tgConfig, method, input })
26
+ ) => executeTgBotMethod({
27
+ config: tgConfig, method, input
28
+ })
29
29
 
30
30
  return {
31
+ config: tgConfig,
31
32
  execute,
32
- getFile: (input: GetFile) => getFileImpl(input, { config: tgConfig, execute })
33
+ getFile: (input) => getFileImpl({ ...input, config: tgConfig, execute })
33
34
  }
34
35
  }
package/src/execute.ts CHANGED
@@ -2,23 +2,27 @@ import type { Api } from "@effect-ak/tg-bot-api"
2
2
 
3
3
  import { TgBotClientError } from "./errors"
4
4
  import { isFileContent, isTgBotApiResponse } from "./guards"
5
- import type { TgBotConfig } from "./config"
6
- import { getBaseUrl } from "./config"
7
5
  import { snakeToCamel } from "./utils"
6
+ import type { TgClientConfig } from "./client"
8
7
 
9
- export async function executeTgBotMethod<M extends keyof Api>(params: {
10
- config: TgBotConfig
11
- method: M
8
+ export type ExecuteMethod = <M extends keyof Api>(
9
+ method: M,
12
10
  input: Parameters<Api[M]>[0]
13
- }): Promise<ReturnType<Api[M]>> {
11
+ ) => Promise<ReturnType<Api[M]>>
12
+
13
+ export async function executeTgBotMethod<M extends keyof Api>(
14
+ params: {
15
+ config: Required<TgClientConfig>
16
+ method: M
17
+ input: Parameters<Api[M]>[0]
18
+ }
19
+ ): Promise<ReturnType<Api[M]>> {
14
20
  const { config, method, input } = params
15
- const baseUrl = getBaseUrl(config)
16
- const botToken = config.botToken
17
21
 
18
22
  let httpResponse: Response
19
23
  try {
20
24
  httpResponse = await fetch(
21
- `${baseUrl}/bot${botToken}/${snakeToCamel(method)}`,
25
+ `${config.base_url}/bot${config.bot_token}/${snakeToCamel(method)}`,
22
26
  {
23
27
  body: makePayload(input) ?? null,
24
28
  method: "POST"
package/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export * from "./execute"
2
2
  export * from "./client-file"
3
3
  export * from "./client"
4
- export * from "./config"
5
4
  export * from "./errors"
6
5
  export * from "./guards"
7
6
  export * from "./const"
@@ -1,32 +1,27 @@
1
- import { describe, expect, assert, vi } from "vitest"
1
+ import { describe, expect, vi } from "vitest"
2
2
 
3
3
  import { fixture } from "./fixture"
4
- import { MESSAGE_EFFECTS } from "../src/const"
5
- import { Micro } from "effect"
6
- import { executeTgBotMethod } from "../src/execute"
4
+ import { MESSAGE_EFFECTS } from "~/const"
5
+ import { executeTgBotMethod } from "~/execute"
7
6
 
8
7
  const fetchSpy = vi.spyOn(global, "fetch")
9
8
 
10
9
  describe("telegram bot client, execute method", () => {
11
- fixture("send dice", async ({ chat_id, context }) => {
10
+ fixture("send dice", async ({ chat_id, client }) => {
12
11
  // skip();
13
12
 
14
- const response = await executeTgBotMethod("send_dice", {
13
+ const response = await client.execute("send_dice", {
15
14
  chat_id,
16
15
  emoji: "🎲",
17
16
  message_effect_id: MESSAGE_EFFECTS["🔥"]
18
- }).pipe(Micro.provideContext(context), Micro.runPromiseExit)
19
-
20
- assert(response._tag == "Success")
17
+ })
21
18
 
22
19
  const url = fetchSpy.mock.calls[0][0] as string
23
20
  const lastPath = url.split("/").pop()
24
21
 
25
22
  expect(lastPath).toEqual("sendDice")
26
23
 
27
- assert(response != null)
28
-
29
- expect(response.value.chat.id).toBeDefined()
24
+ expect(response.chat.id).toBeDefined()
30
25
  })
31
26
 
32
27
  fixture("send message", async ({ chat_id, client, skip }) => {
package/test/fixture.ts CHANGED
@@ -1,18 +1,16 @@
1
1
  import { test } from "vitest"
2
- import { Context } from "effect"
3
2
 
4
- import { makeTgBotClient, TgBotClient } from "../src/client"
5
- import { TgBotApiToken } from "../src/config"
3
+ import { makeTgBotClient, TgBotClient, TgClientConfig } from "~/client"
6
4
 
7
5
  interface Fixture {
8
6
  readonly token: string
9
7
  readonly client: TgBotClient
10
8
  readonly chat_id: string
11
- readonly context: Context.Context<TgBotApiToken>
9
+ readonly config: Required<TgClientConfig>
12
10
  }
13
11
 
14
12
  export const fixture = test.extend<Fixture>({
15
- token: async (_, use) => {
13
+ token: async ({}, use) => {
16
14
  const token = process.env["bot_token"]
17
15
  if (!token) throw Error("bot_token not defined in config.json")
18
16
  use(token)
@@ -24,12 +22,12 @@ export const fixture = test.extend<Fixture>({
24
22
  })
25
23
  use(client)
26
24
  },
27
- chat_id: async (_, use) => {
25
+ chat_id: async ({}, use) => {
28
26
  const chatId = process.env["chat_id"]
29
27
  if (!chatId) throw Error("chat_id not defined in config.json")
30
28
  use(chatId)
31
29
  },
32
- context: async ({ token }, use) => {
33
- use(Context.make(TgBotApiToken, token))
30
+ config: async ({ client }, use) => {
31
+ use(client.config)
34
32
  }
35
33
  })
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'vitest/config'
2
+ import tsconfigPaths from "vite-tsconfig-paths"
3
+
4
+ export default defineConfig({
5
+ plugins: [
6
+ tsconfigPaths()
7
+ ],
8
+ test: {
9
+ testTimeout: 30000
10
+ },
11
+ })
package/src/config.ts DELETED
@@ -1,10 +0,0 @@
1
- import { TG_BOT_API_URL } from "./const"
2
-
3
- export interface TgBotConfig {
4
- botToken: string
5
- baseUrl?: string
6
- }
7
-
8
- export const getBaseUrl = (config?: Pick<TgBotConfig, "baseUrl">): string => {
9
- return config?.baseUrl ?? TG_BOT_API_URL
10
- }
File without changes