@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/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
+ }
@@ -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,6 @@
1
+ import { createClient, CreateClientOptions } from "./client";
2
+
3
+ export {
4
+ createClient,
5
+ type CreateClientOptions
6
+ };
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ export interface ListOptions {
2
+ limit?: number;
3
+ startAfter?: string;
4
+ }
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
+ }