@brostark/solutions-client 1.0.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/.eslintrc.json +3 -0
- package/README.md +3 -0
- package/dist/index.js +5 -0
- package/package-lock.json +4983 -0
- package/package.json +31 -0
- package/src/api/v1/video.ts +65 -0
- package/src/client.ts +31 -0
- package/src/constant.ts +21 -0
- package/src/helper.ts +10 -0
- package/src/index.ts +6 -0
- package/src/lib/httpRequest.ts +124 -0
- package/src/lib/types.ts +4 -0
- package/tsconfig.json +23 -0
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brostark/solutions-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"watch": "tsc --watch",
|
|
9
|
+
"prepublishOnly": "npm run build",
|
|
10
|
+
"publish": "npm publish",
|
|
11
|
+
"publish:patch": "npm version patch && npm publish",
|
|
12
|
+
"publish:minor": "npm version minor && npm publish",
|
|
13
|
+
"publish:major": "npm version major && npm publish"
|
|
14
|
+
},
|
|
15
|
+
"author": "Brostark Solutions",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"description": "Brostark Solutions Client",
|
|
18
|
+
"keywords": ["brostark", "solutions", "client", "api"],
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"eslint": "^8.57.1",
|
|
21
|
+
"eslint-config-incredibilis": "^1.1.30",
|
|
22
|
+
"typescript": "~5.8.3"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public",
|
|
26
|
+
"registry": "https://registry.npmjs.org/"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"jwt-decode": "^4.0.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jwtDecode } from "jwt-decode";
|
|
2
|
+
import { ListOptions } from "../../lib/types"
|
|
3
|
+
import { httpListRequest, httpGetRequest, httpDeleteRequest, httpUploadRequest } from "../../lib/httpRequest"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates an API to manage videos
|
|
7
|
+
* @param apiUrl - The base URL of the API
|
|
8
|
+
* @param apiKey - The API key for authentication
|
|
9
|
+
* @returns An object containing methods to interact with the video API
|
|
10
|
+
*/
|
|
11
|
+
export const generateVideoAPI = (apiUrl: string, apiKey: string) => {
|
|
12
|
+
const { accountId } = jwtDecode(apiKey) as { accountId: string };
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
/**
|
|
16
|
+
* Lists videos with pagination
|
|
17
|
+
* @param options - Pagination options (limit and startAfter)
|
|
18
|
+
* @returns A promise with the list of videos
|
|
19
|
+
*/
|
|
20
|
+
list: async (options: ListOptions = {}) => {
|
|
21
|
+
const response = await httpListRequest(`${apiUrl}/videos`, apiKey, options);
|
|
22
|
+
return response.data;
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Uploads a new video
|
|
27
|
+
* @param file - The video file to upload
|
|
28
|
+
* @returns A promise with information about the uploaded video (URL and path)
|
|
29
|
+
*/
|
|
30
|
+
upload: async (file: File) => {
|
|
31
|
+
const response = await httpUploadRequest(`${apiUrl}/upload/video`, apiKey, file);
|
|
32
|
+
return response.data;
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Retrieves information about a specific video
|
|
37
|
+
* @param id - The video identifier
|
|
38
|
+
* @returns A promise with the video information
|
|
39
|
+
*/
|
|
40
|
+
get: async (id: string) => {
|
|
41
|
+
const response = await httpGetRequest(`${apiUrl}/videos/${id}`, apiKey);
|
|
42
|
+
return response.data;
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Retrieves the video URL
|
|
47
|
+
* @param id - The video identifier
|
|
48
|
+
* @returns A promise with the video URL
|
|
49
|
+
*/
|
|
50
|
+
stream: async (filename: string): Promise<string> => {
|
|
51
|
+
const response = await httpGetRequest(`${apiUrl}/stream/${accountId}/${filename.split("/").pop()?.split(".")[0]}`, apiKey);
|
|
52
|
+
return response.data;
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Deletes a video
|
|
57
|
+
* @param id - The identifier of the video to delete
|
|
58
|
+
* @returns A promise with deletion confirmation
|
|
59
|
+
*/
|
|
60
|
+
remove: async (id: string) => {
|
|
61
|
+
const response = await httpDeleteRequest(`${apiUrl}/videos/${id}`, apiKey);
|
|
62
|
+
return response.data;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { generateVideoAPI } from "./api/v1/video";
|
|
2
|
+
import { ApiVersion, DEFAULT_API_HOST, DEFAULT_API_VERSION } from "./constant";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Options for creating the client
|
|
6
|
+
*/
|
|
7
|
+
export interface CreateClientOptions {
|
|
8
|
+
/** The API host (default: DEFAULT_API_HOST) */
|
|
9
|
+
host?: string;
|
|
10
|
+
/** The API version (default: DEFAULT_API_VERSION) */
|
|
11
|
+
version?: ApiVersion;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates an instance of the API client
|
|
16
|
+
* @param apiKey - The API key for authentication
|
|
17
|
+
* @param options - The configuration options for the client
|
|
18
|
+
* @returns An object containing the different APIs available
|
|
19
|
+
*/
|
|
20
|
+
export function createClient(apiKey: string, options: CreateClientOptions = {}) {
|
|
21
|
+
const {
|
|
22
|
+
host = DEFAULT_API_HOST,
|
|
23
|
+
version = DEFAULT_API_VERSION,
|
|
24
|
+
} = options;
|
|
25
|
+
|
|
26
|
+
const apiUrl = `${host}/${version}`;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
video: generateVideoAPI(apiUrl, apiKey),
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/constant.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Available API versions
|
|
3
|
+
*/
|
|
4
|
+
export enum ApiVersion {
|
|
5
|
+
V1 = "v1",
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Default API host
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_API_HOST = "https://api-solutions.brostark.com";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default API version
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_API_VERSION = ApiVersion.V1;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Maximum limit for list requests
|
|
20
|
+
*/
|
|
21
|
+
export const MAX_LIMIT = 100;
|
package/src/helper.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sets a limit between a minimum and maximum value
|
|
3
|
+
* @param limit - The desired limit
|
|
4
|
+
* @param min - The minimum allowed value
|
|
5
|
+
* @param max - The maximum allowed value
|
|
6
|
+
* @returns The adjusted limit
|
|
7
|
+
*/
|
|
8
|
+
export const setLimit = (limit: number, min: number, max: number) => {
|
|
9
|
+
return Math.min(Math.max(limit, min), max);
|
|
10
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { ListOptions } from "./types";
|
|
2
|
+
import { setLimit } from "../helper";
|
|
3
|
+
import { MAX_LIMIT } from "../constant";
|
|
4
|
+
|
|
5
|
+
type RequestOptions = Omit<RequestInit, "body"> & {
|
|
6
|
+
params?: Record<string, unknown>;
|
|
7
|
+
data?: unknown;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Base function to make an HTTP request
|
|
12
|
+
* @param apiUrl - The API URL
|
|
13
|
+
* @param apiKey - The API key for authentication
|
|
14
|
+
* @param options - The request configuration options
|
|
15
|
+
* @returns A promise with the request response
|
|
16
|
+
*/
|
|
17
|
+
export const httpRequest = async (apiUrl: string, apiKey: string, options: RequestOptions) => {
|
|
18
|
+
const { headers, params, data, ...rest } = options;
|
|
19
|
+
|
|
20
|
+
const url = new URL(apiUrl);
|
|
21
|
+
if (params) {
|
|
22
|
+
for (const [key, value] of Object.entries(params)) {
|
|
23
|
+
if (value !== undefined && value !== null) {
|
|
24
|
+
url.searchParams.set(key, String(value));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const config: RequestInit = {
|
|
30
|
+
mode: "no-cors",
|
|
31
|
+
method: "GET",
|
|
32
|
+
...rest,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const finalHeaders: Record<string, string> = {
|
|
36
|
+
"x-api-key": apiKey,
|
|
37
|
+
...(headers as Record<string, string>),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (data) {
|
|
41
|
+
if (data instanceof File) {
|
|
42
|
+
config.body = data;
|
|
43
|
+
if (!headers || !(headers as Record<string, string>)["Content-Type"]) {
|
|
44
|
+
finalHeaders["Content-Type"] = data.type;
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
config.body = JSON.stringify(data);
|
|
48
|
+
finalHeaders["Content-Type"] = "application/json";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
config.headers = finalHeaders;
|
|
53
|
+
|
|
54
|
+
const response = await fetch(url.toString(), config);
|
|
55
|
+
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
const errorData = await response.json().catch(() => ({ message: response.statusText }));
|
|
58
|
+
throw new Error(errorData.message || "HTTP request failed");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const responseText = await response.text();
|
|
62
|
+
try {
|
|
63
|
+
return JSON.parse(responseText);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
return responseText;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Makes an HTTP request to list resources with pagination
|
|
71
|
+
* @param apiUrl - The API URL
|
|
72
|
+
* @param apiKey - The API key for authentication
|
|
73
|
+
* @param options - The pagination options (limit and startAfter)
|
|
74
|
+
* @returns A promise with the list of resources
|
|
75
|
+
*/
|
|
76
|
+
export const httpListRequest = (apiUrl: string, apiKey: string, options: ListOptions) => {
|
|
77
|
+
return httpRequest(apiUrl, apiKey, {
|
|
78
|
+
params: {
|
|
79
|
+
limit: setLimit(options.limit ?? 10, 1, MAX_LIMIT),
|
|
80
|
+
startAfter: options.startAfter,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Makes an HTTP GET request
|
|
87
|
+
* @param apiUrl - The API URL
|
|
88
|
+
* @param apiKey - The API key for authentication
|
|
89
|
+
* @returns A promise with the resource data
|
|
90
|
+
*/
|
|
91
|
+
export const httpGetRequest = (apiUrl: string, apiKey: string) => {
|
|
92
|
+
return httpRequest(apiUrl, apiKey, {
|
|
93
|
+
method: "GET",
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Makes an HTTP DELETE request
|
|
99
|
+
* @param apiUrl - The API URL
|
|
100
|
+
* @param apiKey - The API key for authentication
|
|
101
|
+
* @returns A promise with the deletion confirmation
|
|
102
|
+
*/
|
|
103
|
+
export const httpDeleteRequest = (apiUrl: string, apiKey: string) => {
|
|
104
|
+
return httpRequest(apiUrl, apiKey, {
|
|
105
|
+
method: "DELETE",
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Makes an HTTP request to upload a file
|
|
111
|
+
* @param apiUrl - The API URL
|
|
112
|
+
* @param apiKey - The API key for authentication
|
|
113
|
+
* @param file - The file to upload
|
|
114
|
+
* @returns A promise with information about the uploaded file
|
|
115
|
+
*/
|
|
116
|
+
export const httpUploadRequest = (apiUrl: string, apiKey: string, file: File) => {
|
|
117
|
+
return httpRequest(apiUrl, apiKey, {
|
|
118
|
+
method: "POST",
|
|
119
|
+
data: file,
|
|
120
|
+
headers: {
|
|
121
|
+
"Content-Type": file.type,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
package/src/lib/types.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationMap": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"strict": true,
|
|
13
|
+
"strictPropertyInitialization": false,
|
|
14
|
+
"downlevelIteration": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"noFallthroughCasesInSwitch": true,
|
|
17
|
+
"resolveJsonModule": true,
|
|
18
|
+
"isolatedModules": true
|
|
19
|
+
},
|
|
20
|
+
"include": [
|
|
21
|
+
"src"
|
|
22
|
+
]
|
|
23
|
+
}
|