@prisme.ai/sdk 0.0.2
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/Readme.md +26 -0
- package/dist/_virtual/_tslib.js +107 -0
- package/dist/index.d.ts +7 -0
- package/dist/lib/ApiError.d.ts +8 -0
- package/dist/lib/ApiError.test.d.ts +1 -0
- package/dist/lib/HTTPError.d.ts +6 -0
- package/dist/lib/HTTPError.test.d.ts +1 -0
- package/dist/lib/api.d.ts +59 -0
- package/dist/lib/api.test.d.ts +1 -0
- package/dist/lib/events.d.ts +14 -0
- package/dist/lib/events.test.d.ts +1 -0
- package/dist/lib/fetcher.d.ts +11 -0
- package/dist/lib/fetcher.test.d.ts +1 -0
- package/dist/lib/types.d.ts +13 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.test.d.ts +1 -0
- package/dist/sdk/index.js +19 -0
- package/dist/sdk/lib/ApiError.js +24 -0
- package/dist/sdk/lib/HTTPError.js +21 -0
- package/dist/sdk/lib/api.js +553 -0
- package/dist/sdk/lib/events.js +65 -0
- package/dist/sdk/lib/fetcher.js +121 -0
- package/dist/sdk/lib/utils.js +18 -0
- package/index.ts +7 -0
- package/lib/ApiError.test.ts +13 -0
- package/lib/ApiError.ts +21 -0
- package/lib/HTTPError.test.ts +8 -0
- package/lib/HTTPError.ts +13 -0
- package/lib/api.test.ts +231 -0
- package/lib/api.ts +439 -0
- package/lib/events.test.ts +57 -0
- package/lib/events.ts +69 -0
- package/lib/fetcher.test.ts +200 -0
- package/lib/fetcher.ts +97 -0
- package/lib/types.ts +17 -0
- package/lib/utils.test.ts +38 -0
- package/lib/utils.ts +12 -0
- package/package.json +16 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import ApiError from './ApiError';
|
|
2
|
+
import Fetcher from './fetcher';
|
|
3
|
+
import HTTPError from './HTTPError';
|
|
4
|
+
|
|
5
|
+
it('should fetch', async () => {
|
|
6
|
+
const fetcher = new Fetcher('http/');
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
global.fetch = jest.fn(() => ({
|
|
9
|
+
ok: true,
|
|
10
|
+
headers: [['foo', 'bar']],
|
|
11
|
+
json() {
|
|
12
|
+
return undefined;
|
|
13
|
+
},
|
|
14
|
+
clone() {
|
|
15
|
+
return { ...this };
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
const o = await fetcher.get('url');
|
|
19
|
+
expect(o.headers).toEqual({ foo: 'bar' });
|
|
20
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
21
|
+
headers: expect.any(Headers),
|
|
22
|
+
method: 'GET',
|
|
23
|
+
});
|
|
24
|
+
const headers = (global.fetch as jest.Mock).mock.calls[0][1].headers;
|
|
25
|
+
expect(headers.get('Access-Control-Allow-Origin')).toBe('*');
|
|
26
|
+
expect(headers.get('Content-Type')).toBe('application/json');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should fetch with auth', async () => {
|
|
30
|
+
const fetcher = new Fetcher('http/');
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
global.fetch = jest.fn(() => ({
|
|
33
|
+
ok: true,
|
|
34
|
+
headers: {},
|
|
35
|
+
json() {
|
|
36
|
+
return {};
|
|
37
|
+
},
|
|
38
|
+
clone() {
|
|
39
|
+
return { ...this };
|
|
40
|
+
},
|
|
41
|
+
}));
|
|
42
|
+
fetcher.token = 'token';
|
|
43
|
+
await fetcher.get('url');
|
|
44
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
45
|
+
headers: expect.any(Headers),
|
|
46
|
+
method: 'GET',
|
|
47
|
+
});
|
|
48
|
+
const headers = (global.fetch as jest.Mock).mock.calls[0][1].headers;
|
|
49
|
+
expect(headers.get('Access-Control-Allow-Origin')).toBe('*');
|
|
50
|
+
expect(headers.get('x-prismeai-session-token')).toBe('token');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should fail to fetch', async () => {
|
|
54
|
+
const fetcher = new Fetcher('http/');
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
global.fetch = jest.fn(() => ({
|
|
57
|
+
ok: false,
|
|
58
|
+
json: () => ({
|
|
59
|
+
error: 'error',
|
|
60
|
+
message: 'message',
|
|
61
|
+
}),
|
|
62
|
+
status: 400,
|
|
63
|
+
}));
|
|
64
|
+
try {
|
|
65
|
+
await fetcher.get('url');
|
|
66
|
+
} catch (e) {
|
|
67
|
+
expect(e).toBeInstanceOf(ApiError);
|
|
68
|
+
if (e instanceof ApiError) {
|
|
69
|
+
expect(e.error).toBe('error');
|
|
70
|
+
expect(e.message).toBe('message');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
74
|
+
headers: expect.any(Headers),
|
|
75
|
+
method: 'GET',
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should fail to fetch with unformatted error', async () => {
|
|
80
|
+
const fetcher = new Fetcher('http/');
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
global.fetch = jest.fn(() => ({
|
|
83
|
+
ok: false,
|
|
84
|
+
statusText: 'error',
|
|
85
|
+
status: 400,
|
|
86
|
+
}));
|
|
87
|
+
try {
|
|
88
|
+
await fetcher.get('url');
|
|
89
|
+
} catch (e) {
|
|
90
|
+
expect(e).toBeInstanceOf(HTTPError);
|
|
91
|
+
if (e instanceof ApiError) {
|
|
92
|
+
expect(e.message).toBe('error');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
96
|
+
headers: expect.any(Headers),
|
|
97
|
+
method: 'GET',
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should post', async () => {
|
|
102
|
+
const fetcher = new Fetcher('http/');
|
|
103
|
+
// @ts-ignore
|
|
104
|
+
global.fetch = jest.fn(() => ({
|
|
105
|
+
ok: true,
|
|
106
|
+
headers: {},
|
|
107
|
+
json() {
|
|
108
|
+
return {};
|
|
109
|
+
},
|
|
110
|
+
clone() {
|
|
111
|
+
return { ...this };
|
|
112
|
+
},
|
|
113
|
+
}));
|
|
114
|
+
await fetcher.post('url');
|
|
115
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
116
|
+
headers: expect.any(Headers),
|
|
117
|
+
method: 'POST',
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should post with body', async () => {
|
|
122
|
+
const fetcher = new Fetcher('http/');
|
|
123
|
+
// @ts-ignore
|
|
124
|
+
global.fetch = jest.fn(() => ({
|
|
125
|
+
ok: true,
|
|
126
|
+
headers: {},
|
|
127
|
+
json() {
|
|
128
|
+
return {};
|
|
129
|
+
},
|
|
130
|
+
clone() {
|
|
131
|
+
return { ...this };
|
|
132
|
+
},
|
|
133
|
+
}));
|
|
134
|
+
await fetcher.post('url', {});
|
|
135
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
136
|
+
headers: expect.any(Headers),
|
|
137
|
+
method: 'POST',
|
|
138
|
+
body: '{}',
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should patch', async () => {
|
|
143
|
+
const fetcher = new Fetcher('http/');
|
|
144
|
+
// @ts-ignore
|
|
145
|
+
global.fetch = jest.fn(() => ({
|
|
146
|
+
ok: true,
|
|
147
|
+
headers: {},
|
|
148
|
+
json() {
|
|
149
|
+
return {};
|
|
150
|
+
},
|
|
151
|
+
clone() {
|
|
152
|
+
return { ...this };
|
|
153
|
+
},
|
|
154
|
+
}));
|
|
155
|
+
await fetcher.patch('url', {});
|
|
156
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
157
|
+
headers: expect.any(Headers),
|
|
158
|
+
method: 'PATCH',
|
|
159
|
+
body: '{}',
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should delete', async () => {
|
|
164
|
+
const fetcher = new Fetcher('http/');
|
|
165
|
+
// @ts-ignore
|
|
166
|
+
global.fetch = jest.fn(() => ({
|
|
167
|
+
ok: true,
|
|
168
|
+
headers: {},
|
|
169
|
+
json() {
|
|
170
|
+
return {};
|
|
171
|
+
},
|
|
172
|
+
clone() {
|
|
173
|
+
return { ...this };
|
|
174
|
+
},
|
|
175
|
+
}));
|
|
176
|
+
await fetcher.delete('url');
|
|
177
|
+
expect(global.fetch).toHaveBeenCalledWith('http/url', {
|
|
178
|
+
headers: expect.any(Headers),
|
|
179
|
+
method: 'DELETE',
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('should use formData', async () => {
|
|
184
|
+
const fetcher = new Fetcher('http/');
|
|
185
|
+
// @ts-ignore
|
|
186
|
+
global.fetch = jest.fn(() => ({
|
|
187
|
+
ok: true,
|
|
188
|
+
headers: {},
|
|
189
|
+
json() {
|
|
190
|
+
return {};
|
|
191
|
+
},
|
|
192
|
+
clone() {
|
|
193
|
+
return { ...this };
|
|
194
|
+
},
|
|
195
|
+
}));
|
|
196
|
+
const formData = new FormData();
|
|
197
|
+
await fetcher.post('url', formData);
|
|
198
|
+
const headers = (global.fetch as jest.Mock).mock.calls[0][1].headers;
|
|
199
|
+
expect(headers.has('Content-Type')).toBe(false);
|
|
200
|
+
});
|
package/lib/fetcher.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import ApiError from './ApiError';
|
|
2
|
+
import HTTPError from './HTTPError';
|
|
3
|
+
|
|
4
|
+
const headersAsObject = (headers: Headers) =>
|
|
5
|
+
Array.from(headers).reduce(
|
|
6
|
+
(prev, [k, v]) => ({
|
|
7
|
+
...prev,
|
|
8
|
+
[k]: v,
|
|
9
|
+
}),
|
|
10
|
+
{}
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export class Fetcher {
|
|
14
|
+
public host: string;
|
|
15
|
+
public token: string | null = null;
|
|
16
|
+
|
|
17
|
+
constructor(host: string) {
|
|
18
|
+
this.host = host;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
protected async _fetch<T>(
|
|
22
|
+
url: string,
|
|
23
|
+
options: RequestInit = {}
|
|
24
|
+
): Promise<T> {
|
|
25
|
+
const headers = new Headers(options.headers || {});
|
|
26
|
+
|
|
27
|
+
if (this.token && !headers.has('x-prismeai-session-token')) {
|
|
28
|
+
headers.append('x-prismeai-session-token', this.token);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (
|
|
32
|
+
(!options.body || !(options.body instanceof FormData)) &&
|
|
33
|
+
!headers.has('Content-Type')
|
|
34
|
+
) {
|
|
35
|
+
headers.append('Content-Type', 'application/json');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
headers.append('Access-Control-Allow-Origin', '*');
|
|
39
|
+
|
|
40
|
+
const res = await global.fetch(`${this.host}${url}`, {
|
|
41
|
+
...options,
|
|
42
|
+
headers,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!res.ok) {
|
|
46
|
+
let error;
|
|
47
|
+
try {
|
|
48
|
+
error = new ApiError(await res.json(), res.status);
|
|
49
|
+
} catch (e) {
|
|
50
|
+
error = new HTTPError(res.statusText, res.status);
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const clone = res.clone();
|
|
56
|
+
try {
|
|
57
|
+
const response = (await res.json()) || {};
|
|
58
|
+
Object.defineProperty(response, 'headers', {
|
|
59
|
+
value: headersAsObject(res.headers),
|
|
60
|
+
configurable: false,
|
|
61
|
+
enumerable: false,
|
|
62
|
+
writable: false,
|
|
63
|
+
});
|
|
64
|
+
return response;
|
|
65
|
+
} catch (e) {
|
|
66
|
+
return ((await clone.text()) as unknown) as T;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async get<T = any>(url: string) {
|
|
71
|
+
return this._fetch<T>(url, {
|
|
72
|
+
method: 'GET',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async post<T>(url: string, body?: Record<string, any>) {
|
|
77
|
+
return this._fetch<T>(url, {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
body: body && !(body instanceof FormData) ? JSON.stringify(body) : body,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async patch<T>(url: string, body: Record<string, any>) {
|
|
84
|
+
return this._fetch<T>(url, {
|
|
85
|
+
method: 'PATCH',
|
|
86
|
+
body: JSON.stringify(body),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async delete<T>(url: string) {
|
|
91
|
+
return this._fetch<T>(url, {
|
|
92
|
+
method: 'DELETE',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export default Fetcher;
|
package/lib/types.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import '@prisme.ai/types';
|
|
2
|
+
|
|
3
|
+
export interface Workspace extends Prismeai.Workspace {
|
|
4
|
+
id: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface Event<DateType extends Date | string>
|
|
8
|
+
extends Omit<Prismeai.PrismeEvent, 'createdAt'> {
|
|
9
|
+
createdAt: DateType;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type EventsFilters = {
|
|
13
|
+
afterDate?: PrismeaiAPI.EventsLongpolling.Parameters.AfterDate;
|
|
14
|
+
beforeDate?: PrismeaiAPI.EventsLongpolling.Parameters.BeforeDate;
|
|
15
|
+
text?: PrismeaiAPI.EventsLongpolling.Parameters.Text;
|
|
16
|
+
query?: PrismeaiAPI.EventsLongpolling.Parameters.Query;
|
|
17
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { removedUndefinedProperties } from './utils';
|
|
2
|
+
|
|
3
|
+
it('should remove undefined keys', () => {
|
|
4
|
+
const myObject = {
|
|
5
|
+
first: 'one',
|
|
6
|
+
second: 'second',
|
|
7
|
+
third: '',
|
|
8
|
+
fourth: undefined,
|
|
9
|
+
fifth: 5,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const newObject = removedUndefinedProperties(myObject);
|
|
13
|
+
|
|
14
|
+
expect(newObject).toStrictEqual({
|
|
15
|
+
first: 'one',
|
|
16
|
+
second: 'second',
|
|
17
|
+
third: '',
|
|
18
|
+
fifth: 5,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should remove empty strings if specified', () => {
|
|
23
|
+
const myObject = {
|
|
24
|
+
first: 'one',
|
|
25
|
+
second: 'second',
|
|
26
|
+
third: '',
|
|
27
|
+
fourth: undefined,
|
|
28
|
+
fifth: 5,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const newObject = removedUndefinedProperties(myObject, true);
|
|
32
|
+
|
|
33
|
+
expect(newObject).toStrictEqual({
|
|
34
|
+
first: 'one',
|
|
35
|
+
second: 'second',
|
|
36
|
+
fifth: 5,
|
|
37
|
+
});
|
|
38
|
+
});
|
package/lib/utils.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const removedUndefinedProperties = (
|
|
2
|
+
obj: any,
|
|
3
|
+
removeEmptyStrings: boolean = false
|
|
4
|
+
) =>
|
|
5
|
+
Object.entries(obj).reduce((newObject: any, [key, value]) => {
|
|
6
|
+
if (value !== undefined) {
|
|
7
|
+
if (!(removeEmptyStrings && value === '')) {
|
|
8
|
+
newObject[key] = value;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return newObject;
|
|
12
|
+
}, {});
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prisme.ai/sdk",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Communicate with Prisme.ai API",
|
|
5
|
+
"main": "dist/sdk/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"author": "",
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@prisme.ai/types": "^1.0.9",
|
|
13
|
+
"qs": "^6.10.3",
|
|
14
|
+
"socket.io-client": "^4.4.1"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es5",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"allowSyntheticDefaultImports": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"noFallthroughCasesInSwitch": true,
|
|
12
|
+
"module": "ESNext",
|
|
13
|
+
"moduleResolution": "node",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": false,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"declaration": true
|
|
18
|
+
},
|
|
19
|
+
"include": ["./index.ts", "lib/**/*", "openapi/*"],
|
|
20
|
+
"exclude": ["node_modules", "dist"]
|
|
21
|
+
}
|