@taruvi/sdk 1.3.7 → 1.3.8-beta.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/.github/workflows/publish.yml +57 -0
- package/package.json +1 -1
- package/src/lib/auth/types.ts +22 -10
- package/src/lib/database/DatabaseClient.ts +28 -0
- package/src/lib/database/types.ts +28 -8
- package/src/lib/functions/types.ts +2 -0
- package/src/lib/settings/SettingsClient.ts +8 -0
- package/src/lib/storage/types.ts +2 -2
- package/src/lib/users/UserClient.ts +2 -2
- package/src/lib-internal/routes/GraphRoutes.ts +1 -1
- package/src/lib-internal/routes/SettingsRoutes.ts +2 -1
- package/src/lib-internal/routes/UserRoutes.ts +1 -1
- package/src/lib-internal/token/TokenClient.ts +16 -0
- package/src/types.ts +8 -0
- package/tests/unit/database/DatabaseClient.test.ts +5 -5
- package/tests/unit/edge-cases/robustness.test.ts +2 -2
- package/tests/unit/graphs/GraphClient.test.ts +19 -19
- package/tests/unit/storage/StorageClient.test.ts +1 -1
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Publish to NPM
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, beta]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
with:
|
|
13
|
+
fetch-depth: 0
|
|
14
|
+
|
|
15
|
+
- uses: actions/setup-node@v4
|
|
16
|
+
with:
|
|
17
|
+
node-version: '20'
|
|
18
|
+
registry-url: 'https://registry.npmjs.org'
|
|
19
|
+
|
|
20
|
+
- name: Get secrets from Infisical
|
|
21
|
+
uses: Infisical/secrets-action@v1.0.7
|
|
22
|
+
with:
|
|
23
|
+
client-id: ${{ secrets.INFISICAL_CLIENT_ID }}
|
|
24
|
+
client-secret: ${{ secrets.INFISICAL_CLIENT_SECRET }}
|
|
25
|
+
env-slug: taruvi-test
|
|
26
|
+
project-slug: taruvi-qmc-d
|
|
27
|
+
domain: "https://environment.eoxvantage.com"
|
|
28
|
+
|
|
29
|
+
- run: npm install
|
|
30
|
+
|
|
31
|
+
- run: npm test
|
|
32
|
+
|
|
33
|
+
- name: Check if version changed
|
|
34
|
+
id: version_check
|
|
35
|
+
run: |
|
|
36
|
+
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
37
|
+
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
|
38
|
+
|
|
39
|
+
if git tag | grep -q "^v${CURRENT_VERSION}$"; then
|
|
40
|
+
echo "changed=false" >> $GITHUB_OUTPUT
|
|
41
|
+
else
|
|
42
|
+
echo "changed=true" >> $GITHUB_OUTPUT
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
- name: Tag release
|
|
46
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
47
|
+
run: |
|
|
48
|
+
git config user.name "github-actions[bot]"
|
|
49
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
50
|
+
git tag "v${{ steps.version_check.outputs.current_version }}"
|
|
51
|
+
git push origin "v${{ steps.version_check.outputs.current_version }}"
|
|
52
|
+
|
|
53
|
+
- name: Publish (beta)
|
|
54
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
55
|
+
run: npm publish --access public --tag beta
|
|
56
|
+
env:
|
|
57
|
+
NODE_AUTH_TOKEN: ${{ env.NPM_TOKEN }}
|
package/package.json
CHANGED
package/src/lib/auth/types.ts
CHANGED
|
@@ -13,17 +13,23 @@ export interface UserCreateRequest {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface UserCreateResponse {
|
|
16
|
-
id:
|
|
17
|
-
uuid: string
|
|
16
|
+
id: string
|
|
18
17
|
username: string
|
|
19
18
|
email: string
|
|
20
19
|
first_name: string
|
|
21
20
|
last_name: string
|
|
21
|
+
full_name: string
|
|
22
22
|
is_active: boolean
|
|
23
|
-
is_staff: boolean
|
|
24
23
|
is_superuser: boolean
|
|
25
24
|
is_deleted: boolean
|
|
26
25
|
date_joined: string
|
|
26
|
+
last_login: string
|
|
27
|
+
groups: UserGroup[]
|
|
28
|
+
user_permissions: UserPermission[]
|
|
29
|
+
attributes: Record<string, unknown>
|
|
30
|
+
missing_attributes: string[]
|
|
31
|
+
roles: UserRole[]
|
|
32
|
+
icon_url: string | null
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
export interface UserGroup {
|
|
@@ -47,23 +53,23 @@ export interface UserRole {
|
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
export interface UserDataResponse {
|
|
50
|
-
id:
|
|
56
|
+
id: string
|
|
51
57
|
username: string
|
|
52
58
|
email: string
|
|
53
59
|
first_name: string
|
|
54
60
|
last_name: string
|
|
55
61
|
full_name: string
|
|
56
62
|
is_active: boolean
|
|
57
|
-
is_staff: boolean
|
|
58
63
|
is_superuser: boolean
|
|
59
64
|
is_deleted: boolean
|
|
60
|
-
date_joined: string
|
|
61
|
-
last_login: string
|
|
65
|
+
date_joined: string
|
|
66
|
+
last_login: string
|
|
62
67
|
groups: UserGroup[]
|
|
63
68
|
user_permissions: UserPermission[]
|
|
64
69
|
attributes: Record<string, unknown>
|
|
65
70
|
missing_attributes: string[]
|
|
66
71
|
roles: UserRole[]
|
|
72
|
+
icon_url: string | null
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
export interface UserUpdateRequest {
|
|
@@ -76,17 +82,23 @@ export interface UserUpdateRequest {
|
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
export interface UserUpdateResponse {
|
|
79
|
-
id:
|
|
80
|
-
uuid: string
|
|
85
|
+
id: string
|
|
81
86
|
username: string
|
|
82
87
|
email: string
|
|
83
88
|
first_name: string
|
|
84
89
|
last_name: string
|
|
90
|
+
full_name: string
|
|
85
91
|
is_active: boolean
|
|
86
|
-
is_staff: boolean
|
|
87
92
|
is_superuser: boolean
|
|
88
93
|
is_deleted: boolean
|
|
89
94
|
date_joined: string
|
|
95
|
+
last_login: string
|
|
96
|
+
groups: UserGroup[]
|
|
97
|
+
user_permissions: UserPermission[]
|
|
98
|
+
attributes: Record<string, unknown>
|
|
99
|
+
missing_attributes: string[]
|
|
100
|
+
roles: UserRole[]
|
|
101
|
+
icon_url: string | null
|
|
90
102
|
}
|
|
91
103
|
|
|
92
104
|
export interface UserList {
|
|
@@ -66,6 +66,34 @@ export class Database<T = Record<string, unknown>> {
|
|
|
66
66
|
})
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
search(query: string): Database<T> {
|
|
70
|
+
return new Database<T>(this.client, { ...this.urlParams }, undefined, undefined, {
|
|
71
|
+
...this.queryParams,
|
|
72
|
+
search: query
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
aggregate(...expressions: string[]): Database<T> {
|
|
77
|
+
return new Database<T>(this.client, { ...this.urlParams }, undefined, undefined, {
|
|
78
|
+
...this.queryParams,
|
|
79
|
+
_aggregate: expressions.join(',')
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
groupBy(...fields: string[]): Database<T> {
|
|
84
|
+
return new Database<T>(this.client, { ...this.urlParams }, undefined, undefined, {
|
|
85
|
+
...this.queryParams,
|
|
86
|
+
_group_by: fields.join(',')
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
having(condition: string): Database<T> {
|
|
91
|
+
return new Database<T>(this.client, { ...this.urlParams }, undefined, undefined, {
|
|
92
|
+
...this.queryParams,
|
|
93
|
+
_having: condition
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
|
|
69
97
|
get(recordId: string): Database<T> {
|
|
70
98
|
return new Database<T>(this.client, { ...this.urlParams, recordId }, HttpMethod.GET)
|
|
71
99
|
}
|
|
@@ -4,23 +4,43 @@ import type { TaruviResponse } from "../../types.js"
|
|
|
4
4
|
|
|
5
5
|
export type DatabaseOperation = HttpMethod
|
|
6
6
|
|
|
7
|
-
// Filter operators matching
|
|
7
|
+
// Filter operators matching backend FilterParams.OPERATORS (32 operators)
|
|
8
8
|
export type FilterOperator =
|
|
9
|
+
// Comparison
|
|
9
10
|
| 'eq' // Equal
|
|
10
11
|
| 'ne' // Not equal
|
|
11
12
|
| 'gt' // Greater than
|
|
12
13
|
| 'gte' // Greater than or equal
|
|
13
14
|
| 'lt' // Less than
|
|
14
15
|
| 'lte' // Less than or equal
|
|
16
|
+
// IN operators
|
|
15
17
|
| 'in' // In array
|
|
16
18
|
| 'nin' // Not in array
|
|
17
|
-
| '
|
|
18
|
-
| '
|
|
19
|
-
|
|
20
|
-
| '
|
|
21
|
-
| '
|
|
22
|
-
| '
|
|
23
|
-
| '
|
|
19
|
+
| 'ina' // In array (case-insensitive)
|
|
20
|
+
| 'nina' // Not in array (case-insensitive)
|
|
21
|
+
// String contains
|
|
22
|
+
| 'contains' // Contains (case-sensitive)
|
|
23
|
+
| 'ncontains' // Not contains (case-sensitive)
|
|
24
|
+
| 'containss' // Contains (case-sensitive, strict)
|
|
25
|
+
| 'ncontainss' // Not contains (case-sensitive, strict)
|
|
26
|
+
| 'icontains' // Contains (case-insensitive)
|
|
27
|
+
| 'nicontains' // Not contains (case-insensitive)
|
|
28
|
+
// Starts with
|
|
29
|
+
| 'startswith' // Starts with (case-sensitive)
|
|
30
|
+
| 'nstartswith' // Not starts with (case-sensitive)
|
|
31
|
+
| 'startswiths' // Starts with (case-sensitive, strict)
|
|
32
|
+
| 'nstartswiths' // Not starts with (case-sensitive, strict)
|
|
33
|
+
// Ends with
|
|
34
|
+
| 'endswith' // Ends with (case-sensitive)
|
|
35
|
+
| 'nendswith' // Not ends with (case-sensitive)
|
|
36
|
+
| 'endswiths' // Ends with (case-sensitive, strict)
|
|
37
|
+
| 'nendswiths' // Not ends with (case-sensitive, strict)
|
|
38
|
+
// Range
|
|
39
|
+
| 'between' // Between two values
|
|
40
|
+
| 'nbetween' // Not between two values
|
|
41
|
+
// Null checks
|
|
42
|
+
| 'null' // Is null
|
|
43
|
+
| 'nnull' // Is not null
|
|
24
44
|
|
|
25
45
|
export type SortOrder = 'asc' | 'desc'
|
|
26
46
|
|
|
@@ -11,4 +11,12 @@ export class Settings {
|
|
|
11
11
|
async get<T = unknown>(): Promise<T> {
|
|
12
12
|
return await this.client.httpClient.get<T>(SettingsRoutes.metadata)
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
async getUserAttributes<T = unknown>(): Promise<T> {
|
|
16
|
+
return await this.client.httpClient.get<T>(SettingsRoutes.userAttributes)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async updateUserAttributes<T = unknown>(schema: Record<string, unknown>): Promise<T> {
|
|
20
|
+
return await this.client.httpClient.post<T>(SettingsRoutes.userAttributes, schema)
|
|
21
|
+
}
|
|
14
22
|
}
|
package/src/lib/storage/types.ts
CHANGED
|
@@ -54,10 +54,10 @@ export class User {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
async getPreferences(): Promise<UserPreferencesResponse> {
|
|
57
|
-
return await this.client.httpClient.get<UserPreferencesResponse>(UserRoutes.
|
|
57
|
+
return await this.client.httpClient.get<UserPreferencesResponse>(UserRoutes.preferences())
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async updatePreferences(body: UserPreferencesUpdate): Promise<UserPreferencesResponse> {
|
|
61
|
-
return await this.client.httpClient.put<UserPreferencesResponse>(UserRoutes.
|
|
61
|
+
return await this.client.httpClient.put<UserPreferencesResponse>(UserRoutes.preferences(), body)
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -6,7 +6,7 @@ export const GraphRoutes = {
|
|
|
6
6
|
|
|
7
7
|
export const GraphEdgeRoutes = {
|
|
8
8
|
baseUrl: (appSlug: string) => `api/apps/${appSlug}`,
|
|
9
|
-
edges: (tableName: string): string => `/datatables/${tableName}/
|
|
9
|
+
edges: (tableName: string): string => `/datatables/${tableName}_edges/data`,
|
|
10
10
|
edgeId: (edgeId: string): string => `/${edgeId}`
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export const UserRoutes = {
|
|
2
2
|
baseUrl: "api/users/",
|
|
3
3
|
getCurrentUser: () => `${UserRoutes.baseUrl}me/`,
|
|
4
|
+
preferences: () => `${UserRoutes.baseUrl}me/preferences/`,
|
|
4
5
|
getUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
5
6
|
updateUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
6
7
|
deleteUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
7
8
|
listUser: (filter: string) => `${UserRoutes.baseUrl}${filter}`,
|
|
8
9
|
getUserApps: (username: string) => `${UserRoutes.baseUrl}${username}/apps/`,
|
|
9
|
-
getPreferences: () => `${UserRoutes.baseUrl}me/preferences/`,
|
|
10
10
|
assignRoles: () => `api/assign/roles/`,
|
|
11
11
|
revokeRoles: () => `api/revoke/roles/`
|
|
12
12
|
} as const
|
|
@@ -194,6 +194,22 @@ export class TokenClient {
|
|
|
194
194
|
return parseInt(expiresAt) < Date.now()
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Set access token directly (e.g., from external storage)
|
|
199
|
+
*/
|
|
200
|
+
setAccessToken(token: string): void {
|
|
201
|
+
if (this.browserRunTime) {
|
|
202
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') return
|
|
203
|
+
try {
|
|
204
|
+
localStorage.setItem(TokenClient.ACCESS_TOKEN_KEY, token)
|
|
205
|
+
} catch (err) {
|
|
206
|
+
console.error('Failed to set access token:', err)
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
this.serverToken = token
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
197
213
|
/**
|
|
198
214
|
* Update access token after refresh
|
|
199
215
|
* ⚠️ IMPORTANT: Taruvi uses refresh token rotation
|
package/src/types.ts
CHANGED
|
@@ -85,6 +85,14 @@ export interface DatabaseFilters {
|
|
|
85
85
|
// Populate relations
|
|
86
86
|
populate?: string
|
|
87
87
|
|
|
88
|
+
// Search (translates to search_vector__search on backend)
|
|
89
|
+
search?: string
|
|
90
|
+
|
|
91
|
+
// Aggregates
|
|
92
|
+
_aggregate?: string
|
|
93
|
+
_group_by?: string
|
|
94
|
+
_having?: string
|
|
95
|
+
|
|
88
96
|
// Dynamic filters - allows any field with operators
|
|
89
97
|
[key: string]: string | number | boolean | undefined
|
|
90
98
|
}
|
|
@@ -182,19 +182,19 @@ describe('Database', () => {
|
|
|
182
182
|
|
|
183
183
|
describe('first()', () => {
|
|
184
184
|
it('returns first item from array', async () => {
|
|
185
|
-
mockHttpClient.get.mockResolvedValue([{ id: '1' }, { id: '2' }])
|
|
185
|
+
mockHttpClient.get.mockResolvedValue({ data: [{ id: '1' }, { id: '2' }] })
|
|
186
186
|
const result = await new Database(mockClient).from('accounts').first()
|
|
187
187
|
expect(result).toEqual({ id: '1' })
|
|
188
188
|
})
|
|
189
189
|
|
|
190
190
|
it('returns null for empty array', async () => {
|
|
191
|
-
mockHttpClient.get.mockResolvedValue([])
|
|
191
|
+
mockHttpClient.get.mockResolvedValue({ data: [] })
|
|
192
192
|
const result = await new Database(mockClient).from('accounts').first()
|
|
193
193
|
expect(result).toBeNull()
|
|
194
194
|
})
|
|
195
195
|
|
|
196
196
|
it('returns single item if not array', async () => {
|
|
197
|
-
mockHttpClient.get.mockResolvedValue({ id: '1' })
|
|
197
|
+
mockHttpClient.get.mockResolvedValue({ data: { id: '1' } })
|
|
198
198
|
const result = await new Database(mockClient).from('accounts').get('1').first()
|
|
199
199
|
expect(result).toEqual({ id: '1' })
|
|
200
200
|
})
|
|
@@ -202,13 +202,13 @@ describe('Database', () => {
|
|
|
202
202
|
|
|
203
203
|
describe('count()', () => {
|
|
204
204
|
it('returns array length', async () => {
|
|
205
|
-
mockHttpClient.get.mockResolvedValue([{ id: '1' }, { id: '2' }, { id: '3' }])
|
|
205
|
+
mockHttpClient.get.mockResolvedValue({ data: [{ id: '1' }, { id: '2' }, { id: '3' }] })
|
|
206
206
|
const result = await new Database(mockClient).from('accounts').count()
|
|
207
207
|
expect(result).toBe(3)
|
|
208
208
|
})
|
|
209
209
|
|
|
210
210
|
it('returns 0 for non-array', async () => {
|
|
211
|
-
mockHttpClient.get.mockResolvedValue({ id: '1' })
|
|
211
|
+
mockHttpClient.get.mockResolvedValue({ data: { id: '1' } })
|
|
212
212
|
const result = await new Database(mockClient).from('accounts').get('1').count()
|
|
213
213
|
expect(result).toBe(0)
|
|
214
214
|
})
|
|
@@ -248,12 +248,12 @@ describe('Builder immutability', () => {
|
|
|
248
248
|
mockHttpClient.post.mockResolvedValue({})
|
|
249
249
|
const base = new Graph(mockClient).from('employees')
|
|
250
250
|
const traversal = base.get('1').include('descendants')
|
|
251
|
-
const edge = base.
|
|
251
|
+
const edge = base.create([{ from: 1, to: 2, type: 'manager' }])
|
|
252
252
|
|
|
253
253
|
await traversal.execute()
|
|
254
254
|
await edge.execute()
|
|
255
255
|
|
|
256
256
|
expect(mockHttpClient.get.mock.calls[0][0]).toContain('/data/1/')
|
|
257
|
-
expect(mockHttpClient.post.mock.calls[0][0]).toContain('/
|
|
257
|
+
expect(mockHttpClient.post.mock.calls[0][0]).toContain('_edges/data/')
|
|
258
258
|
})
|
|
259
259
|
})
|
|
@@ -123,50 +123,50 @@ describe('Graph', () => {
|
|
|
123
123
|
})
|
|
124
124
|
|
|
125
125
|
describe('edge CRUD', () => {
|
|
126
|
-
it('
|
|
126
|
+
it('list() calls GET on edges route', async () => {
|
|
127
127
|
mockHttpClient.get.mockResolvedValue({ edges: [], total: 0 })
|
|
128
|
-
await new Graph(mockClient).from('employees').
|
|
129
|
-
expect(mockHttpClient.get).toHaveBeenCalledWith('api/apps/test-app/datatables/
|
|
128
|
+
await new Graph(mockClient).from('employees').list().execute()
|
|
129
|
+
expect(mockHttpClient.get).toHaveBeenCalledWith('api/apps/test-app/datatables/employees_edges/data/')
|
|
130
130
|
})
|
|
131
131
|
|
|
132
|
-
it('
|
|
132
|
+
it('create() calls POST with array of edges', async () => {
|
|
133
133
|
const edges = [
|
|
134
134
|
{ from: 5, to: 2, type: 'manager' },
|
|
135
135
|
{ from: 5, to: 3, type: 'dotted_line', metadata: { project: 'AI' } }
|
|
136
136
|
]
|
|
137
137
|
mockHttpClient.post.mockResolvedValue({ status: 'success', data: edges, total: 2 })
|
|
138
|
-
await new Graph(mockClient).from('employees').
|
|
138
|
+
await new Graph(mockClient).from('employees').create(edges).execute()
|
|
139
139
|
expect(mockHttpClient.post).toHaveBeenCalledWith(
|
|
140
|
-
'api/apps/test-app/datatables/
|
|
140
|
+
'api/apps/test-app/datatables/employees_edges/data/',
|
|
141
141
|
edges
|
|
142
142
|
)
|
|
143
143
|
})
|
|
144
144
|
|
|
145
|
-
it('
|
|
145
|
+
it('create() with metadata', async () => {
|
|
146
146
|
const edges = [{ from: 5, to: 3, type: 'dotted_line', metadata: { percentage: 30 } }]
|
|
147
147
|
mockHttpClient.post.mockResolvedValue({ status: 'success', data: edges, total: 1 })
|
|
148
|
-
await new Graph(mockClient).from('employees').
|
|
148
|
+
await new Graph(mockClient).from('employees').create(edges).execute()
|
|
149
149
|
expect(mockHttpClient.post).toHaveBeenCalledWith(
|
|
150
|
-
'api/apps/test-app/datatables/
|
|
150
|
+
'api/apps/test-app/datatables/employees_edges/data/',
|
|
151
151
|
edges
|
|
152
152
|
)
|
|
153
153
|
})
|
|
154
154
|
|
|
155
|
-
it('
|
|
155
|
+
it('update() calls PATCH with edge ID in URL', async () => {
|
|
156
156
|
const edge = { from: 5, to: 3, type: 'dotted_line' }
|
|
157
157
|
mockHttpClient.patch.mockResolvedValue({ id: 9, ...edge })
|
|
158
|
-
await new Graph(mockClient).from('employees').
|
|
158
|
+
await new Graph(mockClient).from('employees').update('9', edge).execute()
|
|
159
159
|
expect(mockHttpClient.patch).toHaveBeenCalledWith(
|
|
160
|
-
'api/apps/test-app/datatables/
|
|
160
|
+
'api/apps/test-app/datatables/employees_edges/data/9/',
|
|
161
161
|
edge
|
|
162
162
|
)
|
|
163
163
|
})
|
|
164
164
|
|
|
165
|
-
it('
|
|
165
|
+
it('delete() calls DELETE with edge_ids object', async () => {
|
|
166
166
|
mockHttpClient.delete.mockResolvedValue({ deleted: 2 })
|
|
167
|
-
await new Graph(mockClient).from('employees').
|
|
167
|
+
await new Graph(mockClient).from('employees').delete([9, 10]).execute()
|
|
168
168
|
expect(mockHttpClient.delete).toHaveBeenCalledWith(
|
|
169
|
-
'api/apps/test-app/datatables/
|
|
169
|
+
'api/apps/test-app/datatables/employees_edges/data/',
|
|
170
170
|
{ edge_ids: [9, 10] }
|
|
171
171
|
)
|
|
172
172
|
})
|
|
@@ -290,7 +290,7 @@ describe('Graph', () => {
|
|
|
290
290
|
total: 2
|
|
291
291
|
}
|
|
292
292
|
mockHttpClient.get.mockResolvedValue(mockResponse)
|
|
293
|
-
const result = await new Graph(mockClient).from('employees').
|
|
293
|
+
const result = await new Graph(mockClient).from('employees').list().execute()
|
|
294
294
|
expect((result as any).edges).toHaveLength(2)
|
|
295
295
|
expect((result as any).edges[0].type).toBe('manager')
|
|
296
296
|
expect((result as any).total).toBe(2)
|
|
@@ -306,7 +306,7 @@ describe('Graph', () => {
|
|
|
306
306
|
total: 1
|
|
307
307
|
}
|
|
308
308
|
mockHttpClient.post.mockResolvedValue(mockResponse)
|
|
309
|
-
const result = await new Graph(mockClient).from('employees').
|
|
309
|
+
const result = await new Graph(mockClient).from('employees').create([{ from: 5, to: 2, type: 'manager' }]).execute() as TaruviResponse<EdgeResponse[]>
|
|
310
310
|
expect(result.data).toHaveLength(1)
|
|
311
311
|
expect(result.data[0].id).toBe(10)
|
|
312
312
|
})
|
|
@@ -314,7 +314,7 @@ describe('Graph', () => {
|
|
|
314
314
|
it('returns updated edge matching EdgeResponse type', async () => {
|
|
315
315
|
const mockResponse: EdgeResponse = { id: 9, from: 5, to: 3, type: 'dotted_line', metadata: {} }
|
|
316
316
|
mockHttpClient.patch.mockResolvedValue(mockResponse)
|
|
317
|
-
const result = await new Graph(mockClient).from('employees').
|
|
317
|
+
const result = await new Graph(mockClient).from('employees').update('9', { from: 5, to: 3, type: 'dotted_line' }).execute() as EdgeResponse
|
|
318
318
|
expect(result.id).toBe(9)
|
|
319
319
|
expect(result.type).toBe('dotted_line')
|
|
320
320
|
})
|
|
@@ -322,7 +322,7 @@ describe('Graph', () => {
|
|
|
322
322
|
it('returns delete count response', async () => {
|
|
323
323
|
const mockResponse = { deleted: 3 }
|
|
324
324
|
mockHttpClient.delete.mockResolvedValue(mockResponse)
|
|
325
|
-
const result = await new Graph(mockClient).from('employees').
|
|
325
|
+
const result = await new Graph(mockClient).from('employees').delete([1, 2, 3]).execute()
|
|
326
326
|
expect((result as any).deleted).toBe(3)
|
|
327
327
|
})
|
|
328
328
|
})
|
|
@@ -148,7 +148,7 @@ describe('Storage', () => {
|
|
|
148
148
|
mockHttpClient.get.mockResolvedValue(new Blob())
|
|
149
149
|
await new Storage(mockClient).from('documents').download('folder/file name.pdf').execute()
|
|
150
150
|
expect(mockHttpClient.get).toHaveBeenCalledWith(
|
|
151
|
-
'api/apps/test-app/storage/buckets/documents/objects/folder%2Ffile%20name.pdf
|
|
151
|
+
'api/apps/test-app/storage/buckets/documents/objects/folder%2Ffile%20name.pdf/?metadata=true'
|
|
152
152
|
)
|
|
153
153
|
})
|
|
154
154
|
|