@taruvi/sdk 1.3.3 → 1.3.4-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/.claude/settings.local.json +19 -0
- package/.kiro/settings/lsp.json +198 -0
- package/MODULE_NAMING_CHANGES.md +81 -0
- package/PARAMETER_NAMING_CHANGES.md +106 -0
- package/README.md +4 -4
- package/USAGE_EXAMPLE.md +86 -0
- package/package.json +10 -9
- package/{dist/client.js → src/client.ts} +59 -39
- package/src/index.ts +54 -0
- package/src/lib/analytics/AnalyticsClient.ts +24 -0
- package/src/lib/analytics/types.ts +8 -0
- package/src/lib/app/AppClient.ts +54 -0
- package/src/lib/app/types.ts +50 -0
- package/{dist/lib/auth/AuthClient.js → src/lib/auth/AuthClient.ts} +106 -70
- package/src/lib/auth/types.ts +111 -0
- package/src/lib/database/DatabaseClient.ts +148 -0
- package/src/lib/database/types.ts +46 -0
- package/src/lib/functions/FunctionsClient.ts +27 -0
- package/src/lib/functions/types.ts +25 -0
- package/src/lib/graphs/GraphClient.ts +106 -0
- package/src/lib/graphs/types.ts +33 -0
- package/src/lib/policy/PolicyClient.ts +79 -0
- package/src/lib/policy/types.ts +40 -0
- package/src/lib/secrets/SecretsClient.ts +75 -0
- package/src/lib/secrets/types.ts +59 -0
- package/src/lib/settings/SettingsClient.ts +14 -0
- package/src/lib/settings/types.ts +9 -0
- package/src/lib/storage/StorageClient.ts +123 -0
- package/src/lib/storage/types.ts +86 -0
- package/src/lib/users/UserClient.ts +55 -0
- package/src/lib/users/types.ts +104 -0
- package/src/lib-internal/errors/ErrorClient.ts +102 -0
- package/src/lib-internal/errors/index.ts +3 -0
- package/src/lib-internal/errors/types.ts +28 -0
- package/src/lib-internal/http/HttpClient.ts +129 -0
- package/{dist/lib-internal/http/types.js → src/lib-internal/http/types.ts} +3 -2
- package/src/lib-internal/routes/AnalyticsRoutes.ts +3 -0
- package/src/lib-internal/routes/AppRoutes.ts +9 -0
- package/src/lib-internal/routes/AuthRoutes.ts +0 -0
- package/src/lib-internal/routes/DatabaseRoutes.ts +9 -0
- package/src/lib-internal/routes/FunctionRoutes.ts +3 -0
- package/src/lib-internal/routes/GraphRoutes.ts +14 -0
- package/src/lib-internal/routes/PolicyRoutes.ts +4 -0
- package/src/lib-internal/routes/SecretsRoutes.ts +5 -0
- package/{dist/lib-internal/routes/SettingsRoutes.js → src/lib-internal/routes/SettingsRoutes.ts} +1 -2
- package/src/lib-internal/routes/StorageRoutes.ts +15 -0
- package/src/lib-internal/routes/UserRoutes.ts +11 -0
- package/src/lib-internal/routes/index.ts +0 -0
- package/{dist/lib-internal/token/TokenClient.js → src/lib-internal/token/TokenClient.ts} +144 -99
- package/src/lib-internal/token/types.ts +0 -0
- package/src/types.ts +90 -0
- package/{dist/utils/enums.js → src/utils/enums.ts} +10 -4
- package/src/utils/utils.ts +37 -0
- package/tests/fixtures/mockClient.ts +19 -0
- package/tests/mocks/db.json +1 -0
- package/tests/unit/analytics/AnalyticsClient.test.ts +84 -0
- package/tests/unit/app/AppClient.test.ts +114 -0
- package/tests/unit/auth/AuthClient.test.ts +131 -0
- package/tests/unit/client/Client.test.ts +70 -0
- package/tests/unit/database/DatabaseClient.test.ts +304 -0
- package/tests/unit/edge-cases/robustness.test.ts +259 -0
- package/tests/unit/errors/errors.test.ts +209 -0
- package/tests/unit/functions/FunctionsClient.test.ts +99 -0
- package/tests/unit/graphs/GraphClient.test.ts +329 -0
- package/tests/unit/policy/PolicyClient.test.ts +184 -0
- package/tests/unit/secrets/SecretsClient.test.ts +146 -0
- package/tests/unit/settings/SettingsClient.test.ts +50 -0
- package/tests/unit/storage/StorageClient.test.ts +251 -0
- package/tests/unit/users/UserClient.test.ts +150 -0
- package/tsconfig.json +43 -0
- package/vitest.config.ts +7 -0
- package/dist/client.d.ts +0 -29
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/index.d.ts +0 -25
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -15
- package/dist/index.js.map +0 -1
- package/dist/lib/Analytics/AnalyticsClient.d.ts +0 -9
- package/dist/lib/Analytics/AnalyticsClient.d.ts.map +0 -1
- package/dist/lib/Analytics/AnalyticsClient.js +0 -17
- package/dist/lib/Analytics/AnalyticsClient.js.map +0 -1
- package/dist/lib/Analytics/types.d.ts +0 -7
- package/dist/lib/Analytics/types.d.ts.map +0 -1
- package/dist/lib/Analytics/types.js +0 -2
- package/dist/lib/Analytics/types.js.map +0 -1
- package/dist/lib/App/AppClient.d.ts +0 -15
- package/dist/lib/App/AppClient.d.ts.map +0 -1
- package/dist/lib/App/AppClient.js +0 -41
- package/dist/lib/App/AppClient.js.map +0 -1
- package/dist/lib/App/types.d.ts +0 -36
- package/dist/lib/App/types.d.ts.map +0 -1
- package/dist/lib/App/types.js +0 -2
- package/dist/lib/App/types.js.map +0 -1
- package/dist/lib/Database/DatabaseClient.d.ts +0 -28
- package/dist/lib/Database/DatabaseClient.d.ts.map +0 -1
- package/dist/lib/Database/DatabaseClient.js +0 -116
- package/dist/lib/Database/DatabaseClient.js.map +0 -1
- package/dist/lib/Database/types.d.ts +0 -24
- package/dist/lib/Database/types.d.ts.map +0 -1
- package/dist/lib/Database/types.js +0 -2
- package/dist/lib/Database/types.js.map +0 -1
- package/dist/lib/Function/FunctionsClient.d.ts +0 -9
- package/dist/lib/Function/FunctionsClient.d.ts.map +0 -1
- package/dist/lib/Function/FunctionsClient.js +0 -20
- package/dist/lib/Function/FunctionsClient.js.map +0 -1
- package/dist/lib/Function/types.d.ts +0 -16
- package/dist/lib/Function/types.d.ts.map +0 -1
- package/dist/lib/Function/types.js +0 -2
- package/dist/lib/Function/types.js.map +0 -1
- package/dist/lib/Graphs/GraphClient.d.ts +0 -26
- package/dist/lib/Graphs/GraphClient.d.ts.map +0 -1
- package/dist/lib/Graphs/GraphClient.js +0 -86
- package/dist/lib/Graphs/GraphClient.js.map +0 -1
- package/dist/lib/Graphs/types.d.ts +0 -23
- package/dist/lib/Graphs/types.d.ts.map +0 -1
- package/dist/lib/Graphs/types.js +0 -2
- package/dist/lib/Graphs/types.js.map +0 -1
- package/dist/lib/Policy/PolicyClient.d.ts +0 -9
- package/dist/lib/Policy/PolicyClient.d.ts.map +0 -1
- package/dist/lib/Policy/PolicyClient.js +0 -24
- package/dist/lib/Policy/PolicyClient.js.map +0 -1
- package/dist/lib/Policy/types.d.ts +0 -22
- package/dist/lib/Policy/types.d.ts.map +0 -1
- package/dist/lib/Policy/types.js +0 -2
- package/dist/lib/Policy/types.js.map +0 -1
- package/dist/lib/Secrets/SecretsClient.d.ts +0 -14
- package/dist/lib/Secrets/SecretsClient.d.ts.map +0 -1
- package/dist/lib/Secrets/SecretsClient.js +0 -32
- package/dist/lib/Secrets/SecretsClient.js.map +0 -1
- package/dist/lib/Secrets/types.d.ts +0 -13
- package/dist/lib/Secrets/types.d.ts.map +0 -1
- package/dist/lib/Secrets/types.js +0 -2
- package/dist/lib/Secrets/types.js.map +0 -1
- package/dist/lib/Settings/SettingsClient.d.ts +0 -7
- package/dist/lib/Settings/SettingsClient.d.ts.map +0 -1
- package/dist/lib/Settings/SettingsClient.js +0 -11
- package/dist/lib/Settings/SettingsClient.js.map +0 -1
- package/dist/lib/Settings/types.d.ts +0 -4
- package/dist/lib/Settings/types.d.ts.map +0 -1
- package/dist/lib/Settings/types.js +0 -2
- package/dist/lib/Settings/types.js.map +0 -1
- package/dist/lib/Storage/StorageClient.d.ts +0 -26
- package/dist/lib/Storage/StorageClient.d.ts.map +0 -1
- package/dist/lib/Storage/StorageClient.js +0 -78
- package/dist/lib/Storage/StorageClient.js.map +0 -1
- package/dist/lib/Storage/types.d.ts +0 -35
- package/dist/lib/Storage/types.d.ts.map +0 -1
- package/dist/lib/Storage/types.js +0 -2
- package/dist/lib/Storage/types.js.map +0 -1
- package/dist/lib/auth/AuthClient.d.ts +0 -66
- package/dist/lib/auth/AuthClient.d.ts.map +0 -1
- package/dist/lib/auth/AuthClient.js.map +0 -1
- package/dist/lib/auth/types.d.ts +0 -9
- package/dist/lib/auth/types.d.ts.map +0 -1
- package/dist/lib/auth/types.js +0 -2
- package/dist/lib/auth/types.js.map +0 -1
- package/dist/lib/user/UserClient.d.ts +0 -16
- package/dist/lib/user/UserClient.d.ts.map +0 -1
- package/dist/lib/user/UserClient.js +0 -41
- package/dist/lib/user/UserClient.js.map +0 -1
- package/dist/lib/user/types.d.ts +0 -100
- package/dist/lib/user/types.d.ts.map +0 -1
- package/dist/lib/user/types.js +0 -2
- package/dist/lib/user/types.js.map +0 -1
- package/dist/lib-internal/errors/ErrorClient.d.ts +0 -4
- package/dist/lib-internal/errors/ErrorClient.d.ts.map +0 -1
- package/dist/lib-internal/errors/ErrorClient.js +0 -6
- package/dist/lib-internal/errors/ErrorClient.js.map +0 -1
- package/dist/lib-internal/errors/index.d.ts +0 -8
- package/dist/lib-internal/errors/index.d.ts.map +0 -1
- package/dist/lib-internal/errors/index.js +0 -23
- package/dist/lib-internal/errors/index.js.map +0 -1
- package/dist/lib-internal/errors/types.d.ts +0 -83
- package/dist/lib-internal/errors/types.d.ts.map +0 -1
- package/dist/lib-internal/errors/types.js +0 -65
- package/dist/lib-internal/errors/types.js.map +0 -1
- package/dist/lib-internal/http/HttpClient.d.ts +0 -22
- package/dist/lib-internal/http/HttpClient.d.ts.map +0 -1
- package/dist/lib-internal/http/HttpClient.js +0 -65
- package/dist/lib-internal/http/HttpClient.js.map +0 -1
- package/dist/lib-internal/http/types.d.ts +0 -12
- package/dist/lib-internal/http/types.d.ts.map +0 -1
- package/dist/lib-internal/http/types.js.map +0 -1
- package/dist/lib-internal/routes/AnalyticsRoutes.d.ts +0 -4
- package/dist/lib-internal/routes/AnalyticsRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/AnalyticsRoutes.js +0 -4
- package/dist/lib-internal/routes/AnalyticsRoutes.js.map +0 -1
- package/dist/lib-internal/routes/AppRoutes.d.ts +0 -10
- package/dist/lib-internal/routes/AppRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/AppRoutes.js +0 -6
- package/dist/lib-internal/routes/AppRoutes.js.map +0 -1
- package/dist/lib-internal/routes/AuthRoutes.d.ts +0 -2
- package/dist/lib-internal/routes/AuthRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/AuthRoutes.js +0 -2
- package/dist/lib-internal/routes/AuthRoutes.js.map +0 -1
- package/dist/lib-internal/routes/DatabaseRoutes.d.ts +0 -10
- package/dist/lib-internal/routes/DatabaseRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/DatabaseRoutes.js +0 -6
- package/dist/lib-internal/routes/DatabaseRoutes.js.map +0 -1
- package/dist/lib-internal/routes/FunctionRoutes.d.ts +0 -4
- package/dist/lib-internal/routes/FunctionRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/FunctionRoutes.js +0 -4
- package/dist/lib-internal/routes/FunctionRoutes.js.map +0 -1
- package/dist/lib-internal/routes/GraphRoutes.d.ts +0 -14
- package/dist/lib-internal/routes/GraphRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/GraphRoutes.js +0 -11
- package/dist/lib-internal/routes/GraphRoutes.js.map +0 -1
- package/dist/lib-internal/routes/PolicyRoutes.d.ts +0 -5
- package/dist/lib-internal/routes/PolicyRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/PolicyRoutes.js +0 -5
- package/dist/lib-internal/routes/PolicyRoutes.js.map +0 -1
- package/dist/lib-internal/routes/SecretsRoutes.d.ts +0 -6
- package/dist/lib-internal/routes/SecretsRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/SecretsRoutes.js +0 -6
- package/dist/lib-internal/routes/SecretsRoutes.js.map +0 -1
- package/dist/lib-internal/routes/SettingsRoutes.d.ts +0 -4
- package/dist/lib-internal/routes/SettingsRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/SettingsRoutes.js.map +0 -1
- package/dist/lib-internal/routes/StorageRoutes.d.ts +0 -11
- package/dist/lib-internal/routes/StorageRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/StorageRoutes.js +0 -8
- package/dist/lib-internal/routes/StorageRoutes.js.map +0 -1
- package/dist/lib-internal/routes/UserRoutes.d.ts +0 -11
- package/dist/lib-internal/routes/UserRoutes.d.ts.map +0 -1
- package/dist/lib-internal/routes/UserRoutes.js +0 -11
- package/dist/lib-internal/routes/UserRoutes.js.map +0 -1
- package/dist/lib-internal/routes/index.d.ts +0 -2
- package/dist/lib-internal/routes/index.d.ts.map +0 -1
- package/dist/lib-internal/routes/index.js +0 -2
- package/dist/lib-internal/routes/index.js.map +0 -1
- package/dist/lib-internal/token/TokenClient.d.ts +0 -71
- package/dist/lib-internal/token/TokenClient.d.ts.map +0 -1
- package/dist/lib-internal/token/TokenClient.js.map +0 -1
- package/dist/lib-internal/token/types.d.ts +0 -2
- package/dist/lib-internal/token/types.d.ts.map +0 -1
- package/dist/lib-internal/token/types.js +0 -2
- package/dist/lib-internal/token/types.js.map +0 -1
- package/dist/types.d.ts +0 -49
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/enums.d.ts +0 -20
- package/dist/utils/enums.d.ts.map +0 -1
- package/dist/utils/enums.js.map +0 -1
- package/dist/utils/utils.d.ts +0 -5
- package/dist/utils/utils.d.ts.map +0 -1
- package/dist/utils/utils.js +0 -32
- package/dist/utils/utils.js.map +0 -1
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { TaruviConfig } from "../../types.js";
|
|
2
|
+
import type { TokenClient } from "../token/TokenClient.js";
|
|
3
|
+
import axios, { AxiosError } from "axios";
|
|
4
|
+
import { createErrorFromResponse, NetworkError, TaruviError } from "../errors/index.js";
|
|
5
|
+
import type { ErrorResponseBody } from "../errors/index.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* HttpClient handles all HTTP requests to the Taruvi API.
|
|
9
|
+
* Automatically adds authentication headers and converts
|
|
10
|
+
* error responses to typed SDK errors.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export class HttpClient {
|
|
15
|
+
private config: TaruviConfig
|
|
16
|
+
private tokenClient: TokenClient
|
|
17
|
+
|
|
18
|
+
constructor(config: TaruviConfig, tokenClient: TokenClient) {
|
|
19
|
+
this.config = config
|
|
20
|
+
this.tokenClient = tokenClient
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private getAuthHeaders(isFormData: boolean = false): Record<string, string> {
|
|
24
|
+
const headers: Record<string, string> = {}
|
|
25
|
+
|
|
26
|
+
// Don't set Content-Type for FormData - let axios set it with the boundary
|
|
27
|
+
if (!isFormData) {
|
|
28
|
+
headers['Content-Type'] = 'application/json'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Tenant admin session token
|
|
32
|
+
const jwt = this.tokenClient.getToken()
|
|
33
|
+
if (jwt) {
|
|
34
|
+
headers['Authorization'] = `Bearer ${jwt}`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return headers
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private handleError(error: unknown): never {
|
|
41
|
+
if (error instanceof TaruviError) {
|
|
42
|
+
throw error
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (error instanceof AxiosError) {
|
|
46
|
+
if (error.response) {
|
|
47
|
+
const body = error.response.data as ErrorResponseBody | undefined
|
|
48
|
+
throw createErrorFromResponse(error.response.status, body)
|
|
49
|
+
}
|
|
50
|
+
// No response — network error
|
|
51
|
+
throw new NetworkError(error.message)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Unknown error
|
|
55
|
+
throw error
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async get<T>(endpoint: string): Promise<T> {
|
|
59
|
+
try {
|
|
60
|
+
const { data } = await axios.get<T>(`${this.config.apiUrl}/${endpoint}`, {
|
|
61
|
+
headers: this.getAuthHeaders()
|
|
62
|
+
})
|
|
63
|
+
return data
|
|
64
|
+
} catch (error) {
|
|
65
|
+
this.handleError(error)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async post<T, D = unknown>(endpoint: string, body: D): Promise<T> {
|
|
70
|
+
try {
|
|
71
|
+
const isFormData = body instanceof FormData
|
|
72
|
+
const { data } = await axios.post<T>(
|
|
73
|
+
`${this.config.apiUrl}/${endpoint}`,
|
|
74
|
+
body,
|
|
75
|
+
{
|
|
76
|
+
headers: this.getAuthHeaders(isFormData)
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
return data
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.handleError(error)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async put<T, D = unknown>(endpoint: string, body: D): Promise<T> {
|
|
86
|
+
try {
|
|
87
|
+
const isFormData = body instanceof FormData
|
|
88
|
+
const { data } = await axios.put<T>(`${this.config.apiUrl}/${endpoint}`,
|
|
89
|
+
body,
|
|
90
|
+
{
|
|
91
|
+
headers: this.getAuthHeaders(isFormData)
|
|
92
|
+
})
|
|
93
|
+
return data
|
|
94
|
+
} catch (error) {
|
|
95
|
+
this.handleError(error)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async delete<T, D = unknown>(endpoint: string, body?: D): Promise<T> {
|
|
100
|
+
try {
|
|
101
|
+
const { data } = await axios.delete<T>(
|
|
102
|
+
`${this.config.apiUrl}/${endpoint}`,
|
|
103
|
+
{
|
|
104
|
+
headers: this.getAuthHeaders(),
|
|
105
|
+
data: body
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
return data
|
|
109
|
+
} catch (error) {
|
|
110
|
+
this.handleError(error)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async patch<T, D = unknown>(endpoint: string, body: D): Promise<T> {
|
|
115
|
+
try {
|
|
116
|
+
const isFormData = body instanceof FormData
|
|
117
|
+
const { data } = await axios.patch<T>(
|
|
118
|
+
`${this.config.apiUrl}/${endpoint}`,
|
|
119
|
+
body,
|
|
120
|
+
{
|
|
121
|
+
headers: this.getAuthHeaders(isFormData)
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
return data
|
|
125
|
+
} catch (error) {
|
|
126
|
+
this.handleError(error)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const AppRoutes = {
|
|
2
|
+
baseUrl: (appSlug: string) => `api/apps/${appSlug}`,
|
|
3
|
+
roles: (): string => `/roles`,
|
|
4
|
+
settings: (): string => "/settings/"
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type AllRouteKeys = keyof typeof AppRoutes
|
|
8
|
+
export type AppRouteKey = Exclude<AllRouteKeys, 'baseUrl'>
|
|
9
|
+
export type AppUrlParams = Partial<Record<AppRouteKey, string>>
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DatabaseRoutes = {
|
|
2
|
+
baseUrl: (appSlug: string) => `api/apps/${appSlug}`,
|
|
3
|
+
dataTables: (tableName: string): string => `/datatables/${tableName}/data`,
|
|
4
|
+
recordId: (recordId: string): string => `/${recordId}`
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type AllRouteKeys = keyof typeof DatabaseRoutes
|
|
8
|
+
export type DatabaseRouteKey = Exclude<AllRouteKeys, 'baseUrl'>
|
|
9
|
+
export type DatabaseUrlParams = Partial<Record<DatabaseRouteKey, string>>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const GraphRoutes = {
|
|
2
|
+
baseUrl: (appSlug: string) => `api/apps/${appSlug}`,
|
|
3
|
+
dataTables: (tableName: string): string => `/datatables/${tableName}/data`,
|
|
4
|
+
recordId: (recordId: string): string => `/${recordId}`
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const GraphEdgeRoutes = {
|
|
8
|
+
baseUrl: (appSlug: string) => `api/apps/${appSlug}`,
|
|
9
|
+
edges: (tableName: string): string => `/datatables/${tableName}/edges`,
|
|
10
|
+
edgeId: (edgeId: string): string => `/${edgeId}`
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type AllRouteKeys = keyof typeof GraphRoutes
|
|
14
|
+
export type GraphRouteKey = Exclude<AllRouteKeys, 'baseUrl'>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const StorageRoutes = {
|
|
2
|
+
baseUrl: (appslug: string, bucket: string) => `api/apps/${appslug}/storage/buckets/${bucket}/objects`,
|
|
3
|
+
path: (path: string) => "/" + encodeURIComponent(path),
|
|
4
|
+
upload: () => "/batch-upload",
|
|
5
|
+
delete: () => "/batch-delete"
|
|
6
|
+
// bucket: (appslug: string, bucketslug: string) => `${StorageRoutesClone.baseUrl(appslug)}/${bucketslug}`
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type StoragePathKey = 'path'
|
|
10
|
+
export type StorageFlagKey = 'upload' | 'delete'
|
|
11
|
+
export type StorageRouteKey = StoragePathKey | StorageFlagKey
|
|
12
|
+
|
|
13
|
+
export type BucketUrlParams = Partial<
|
|
14
|
+
Record<StorageRouteKey, string | true>
|
|
15
|
+
>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const UserRoutes = {
|
|
2
|
+
baseUrl: "api/users/",
|
|
3
|
+
getCurrentUser: () => `${UserRoutes.baseUrl}me/`,
|
|
4
|
+
getUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
5
|
+
updateUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
6
|
+
deleteUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
7
|
+
listUser: (filter: string) => `${UserRoutes.baseUrl}${filter}`,
|
|
8
|
+
getUserApps: (username: string) => `${UserRoutes.baseUrl}${username}/apps/`,
|
|
9
|
+
assignRoles: () => `api/assign/roles/`,
|
|
10
|
+
revokeRoles: () => `api/revoke/roles/`
|
|
11
|
+
} as const
|
|
File without changes
|
|
@@ -1,221 +1,266 @@
|
|
|
1
|
-
import { getRuntimeEnvironment } from "../../utils/utils.js"
|
|
1
|
+
import { getRuntimeEnvironment } from "../../utils/utils.js"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Token management interface for Web UI Flow authentication
|
|
5
|
+
*/
|
|
6
|
+
export interface AuthTokens {
|
|
7
|
+
sessionToken?: string | undefined;
|
|
8
|
+
accessToken: string;
|
|
9
|
+
refreshToken: string;
|
|
10
|
+
expiresIn?: number | undefined;
|
|
11
|
+
expiresAt?: number | undefined;
|
|
12
|
+
tokenType?: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
2
15
|
/**
|
|
3
16
|
* TokenClient - Manages authentication tokens for both browser and server environments
|
|
4
17
|
* Implements Web UI Flow token handling as described in Taruvi documentation
|
|
5
18
|
*/
|
|
6
19
|
export class TokenClient {
|
|
7
|
-
static ACCESS_TOKEN_KEY = 'jwt';
|
|
8
|
-
static REFRESH_TOKEN_KEY = 'refresh_token';
|
|
9
|
-
static SESSION_TOKEN_KEY = 'session_token';
|
|
10
|
-
static EXPIRES_AT_KEY = 'token_expires_at';
|
|
11
|
-
static TOKEN_TYPE_KEY = 'token_type';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
private static readonly ACCESS_TOKEN_KEY = 'jwt';
|
|
21
|
+
private static readonly REFRESH_TOKEN_KEY = 'refresh_token';
|
|
22
|
+
private static readonly SESSION_TOKEN_KEY = 'session_token';
|
|
23
|
+
private static readonly EXPIRES_AT_KEY = 'token_expires_at';
|
|
24
|
+
private static readonly TOKEN_TYPE_KEY = 'token_type';
|
|
25
|
+
|
|
26
|
+
private runTimeEnvironment: string
|
|
27
|
+
private browserRunTime: boolean
|
|
28
|
+
private serverToken: string | null = null
|
|
29
|
+
|
|
30
|
+
constructor(token?: string) {
|
|
31
|
+
this.runTimeEnvironment = getRuntimeEnvironment()
|
|
32
|
+
this.browserRunTime = this.runTimeEnvironment == "Browser"
|
|
33
|
+
|
|
18
34
|
// For server-side usage, store the token
|
|
19
35
|
if (!this.browserRunTime && token) {
|
|
20
|
-
this.serverToken = token
|
|
36
|
+
this.serverToken = token
|
|
21
37
|
}
|
|
22
38
|
}
|
|
39
|
+
|
|
23
40
|
/**
|
|
24
41
|
* Get access token (supports both browser and server)
|
|
25
42
|
*/
|
|
26
|
-
getToken() {
|
|
43
|
+
getToken(): string | null {
|
|
27
44
|
if (this.browserRunTime) {
|
|
28
45
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
29
|
-
return null
|
|
46
|
+
return null
|
|
30
47
|
}
|
|
31
|
-
return localStorage.getItem(TokenClient.ACCESS_TOKEN_KEY)
|
|
48
|
+
return localStorage.getItem(TokenClient.ACCESS_TOKEN_KEY)
|
|
32
49
|
}
|
|
33
|
-
return this.serverToken
|
|
50
|
+
return this.serverToken
|
|
34
51
|
}
|
|
52
|
+
|
|
35
53
|
/**
|
|
36
54
|
* Set all authentication tokens from Web UI Flow callback
|
|
37
55
|
*/
|
|
38
|
-
setTokens(tokens) {
|
|
56
|
+
setTokens(tokens: AuthTokens): void {
|
|
39
57
|
if (!this.browserRunTime) {
|
|
40
|
-
console.warn('Token storage is only available in browser environment')
|
|
41
|
-
return
|
|
58
|
+
console.warn('Token storage is only available in browser environment')
|
|
59
|
+
return
|
|
42
60
|
}
|
|
61
|
+
|
|
43
62
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
44
|
-
return
|
|
63
|
+
return
|
|
45
64
|
}
|
|
65
|
+
|
|
46
66
|
try {
|
|
47
67
|
// Store access token
|
|
48
|
-
localStorage.setItem(TokenClient.ACCESS_TOKEN_KEY, tokens.accessToken)
|
|
68
|
+
localStorage.setItem(TokenClient.ACCESS_TOKEN_KEY, tokens.accessToken)
|
|
69
|
+
|
|
49
70
|
// Store refresh token
|
|
50
|
-
localStorage.setItem(TokenClient.REFRESH_TOKEN_KEY, tokens.refreshToken)
|
|
71
|
+
localStorage.setItem(TokenClient.REFRESH_TOKEN_KEY, tokens.refreshToken)
|
|
72
|
+
|
|
51
73
|
// Store session token if provided
|
|
52
74
|
if (tokens.sessionToken) {
|
|
53
|
-
localStorage.setItem(TokenClient.SESSION_TOKEN_KEY, tokens.sessionToken)
|
|
75
|
+
localStorage.setItem(TokenClient.SESSION_TOKEN_KEY, tokens.sessionToken)
|
|
54
76
|
}
|
|
77
|
+
|
|
55
78
|
// Calculate and store expiration time
|
|
56
79
|
if (tokens.expiresIn) {
|
|
57
|
-
const expiresAt = Date.now() + (tokens.expiresIn * 1000)
|
|
58
|
-
localStorage.setItem(TokenClient.EXPIRES_AT_KEY, expiresAt.toString())
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
localStorage.setItem(TokenClient.EXPIRES_AT_KEY, tokens.expiresAt.toString());
|
|
80
|
+
const expiresAt = Date.now() + (tokens.expiresIn * 1000)
|
|
81
|
+
localStorage.setItem(TokenClient.EXPIRES_AT_KEY, expiresAt.toString())
|
|
82
|
+
} else if (tokens.expiresAt) {
|
|
83
|
+
localStorage.setItem(TokenClient.EXPIRES_AT_KEY, tokens.expiresAt.toString())
|
|
62
84
|
}
|
|
85
|
+
|
|
63
86
|
// Store token type
|
|
64
87
|
if (tokens.tokenType) {
|
|
65
|
-
localStorage.setItem(TokenClient.TOKEN_TYPE_KEY, tokens.tokenType)
|
|
88
|
+
localStorage.setItem(TokenClient.TOKEN_TYPE_KEY, tokens.tokenType)
|
|
66
89
|
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
console.error('Failed to store authentication tokens:', err);
|
|
90
|
+
} catch (err) {
|
|
91
|
+
console.error('Failed to store authentication tokens:', err)
|
|
70
92
|
}
|
|
71
93
|
}
|
|
94
|
+
|
|
72
95
|
/**
|
|
73
96
|
* Get all stored tokens
|
|
74
97
|
*/
|
|
75
|
-
getTokens() {
|
|
98
|
+
getTokens(): AuthTokens | null {
|
|
76
99
|
if (!this.browserRunTime) {
|
|
77
|
-
return null
|
|
100
|
+
return null
|
|
78
101
|
}
|
|
102
|
+
|
|
79
103
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
80
|
-
return null
|
|
104
|
+
return null
|
|
81
105
|
}
|
|
106
|
+
|
|
82
107
|
try {
|
|
83
|
-
const accessToken = localStorage.getItem(TokenClient.ACCESS_TOKEN_KEY)
|
|
84
|
-
const refreshToken = localStorage.getItem(TokenClient.REFRESH_TOKEN_KEY)
|
|
85
|
-
const sessionToken = localStorage.getItem(TokenClient.SESSION_TOKEN_KEY)
|
|
86
|
-
const expiresAt = localStorage.getItem(TokenClient.EXPIRES_AT_KEY)
|
|
87
|
-
const tokenType = localStorage.getItem(TokenClient.TOKEN_TYPE_KEY)
|
|
108
|
+
const accessToken = localStorage.getItem(TokenClient.ACCESS_TOKEN_KEY)
|
|
109
|
+
const refreshToken = localStorage.getItem(TokenClient.REFRESH_TOKEN_KEY)
|
|
110
|
+
const sessionToken = localStorage.getItem(TokenClient.SESSION_TOKEN_KEY)
|
|
111
|
+
const expiresAt = localStorage.getItem(TokenClient.EXPIRES_AT_KEY)
|
|
112
|
+
const tokenType = localStorage.getItem(TokenClient.TOKEN_TYPE_KEY)
|
|
113
|
+
|
|
88
114
|
if (!accessToken || !refreshToken) {
|
|
89
|
-
return null
|
|
115
|
+
return null
|
|
90
116
|
}
|
|
91
|
-
|
|
117
|
+
|
|
118
|
+
const tokens: AuthTokens = {
|
|
92
119
|
accessToken,
|
|
93
120
|
refreshToken,
|
|
94
121
|
tokenType: tokenType || 'Bearer',
|
|
95
|
-
}
|
|
122
|
+
}
|
|
123
|
+
|
|
96
124
|
if (sessionToken) {
|
|
97
|
-
tokens.sessionToken = sessionToken
|
|
125
|
+
tokens.sessionToken = sessionToken
|
|
98
126
|
}
|
|
127
|
+
|
|
99
128
|
if (expiresAt) {
|
|
100
|
-
tokens.expiresIn = Math.floor((parseInt(expiresAt) - Date.now()) / 1000)
|
|
101
|
-
tokens.expiresAt = parseInt(expiresAt)
|
|
129
|
+
tokens.expiresIn = Math.floor((parseInt(expiresAt) - Date.now()) / 1000)
|
|
130
|
+
tokens.expiresAt = parseInt(expiresAt)
|
|
102
131
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
catch (err) {
|
|
106
|
-
console.error('Failed to retrieve authentication tokens:', err)
|
|
107
|
-
return null
|
|
132
|
+
|
|
133
|
+
return tokens
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error('Failed to retrieve authentication tokens:', err)
|
|
136
|
+
return null
|
|
108
137
|
}
|
|
109
138
|
}
|
|
139
|
+
|
|
110
140
|
/**
|
|
111
141
|
* Get refresh token
|
|
112
142
|
*/
|
|
113
|
-
getRefreshToken() {
|
|
143
|
+
getRefreshToken(): string | null {
|
|
114
144
|
if (!this.browserRunTime) {
|
|
115
|
-
return null
|
|
145
|
+
return null
|
|
116
146
|
}
|
|
147
|
+
|
|
117
148
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
118
|
-
return null
|
|
149
|
+
return null
|
|
119
150
|
}
|
|
120
|
-
|
|
151
|
+
|
|
152
|
+
return localStorage.getItem(TokenClient.REFRESH_TOKEN_KEY)
|
|
121
153
|
}
|
|
154
|
+
|
|
122
155
|
/**
|
|
123
156
|
* Get session token
|
|
124
157
|
*/
|
|
125
|
-
getSessionToken() {
|
|
158
|
+
getSessionToken(): string | null {
|
|
126
159
|
if (!this.browserRunTime) {
|
|
127
|
-
return null
|
|
160
|
+
return null
|
|
128
161
|
}
|
|
162
|
+
|
|
129
163
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
130
|
-
return null
|
|
164
|
+
return null
|
|
131
165
|
}
|
|
132
|
-
|
|
166
|
+
|
|
167
|
+
return localStorage.getItem(TokenClient.SESSION_TOKEN_KEY)
|
|
133
168
|
}
|
|
169
|
+
|
|
134
170
|
/**
|
|
135
171
|
* Check if user is authenticated (has valid access token)
|
|
136
172
|
*/
|
|
137
|
-
isAuthenticated() {
|
|
138
|
-
return !!this.getToken()
|
|
173
|
+
isAuthenticated(): boolean {
|
|
174
|
+
return !!this.getToken()
|
|
139
175
|
}
|
|
176
|
+
|
|
140
177
|
/**
|
|
141
178
|
* Check if access token is expired
|
|
142
179
|
*/
|
|
143
|
-
isTokenExpired() {
|
|
180
|
+
isTokenExpired(): boolean {
|
|
144
181
|
if (!this.browserRunTime) {
|
|
145
|
-
return true
|
|
182
|
+
return true
|
|
146
183
|
}
|
|
184
|
+
|
|
147
185
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
148
|
-
return true
|
|
186
|
+
return true
|
|
149
187
|
}
|
|
150
|
-
|
|
188
|
+
|
|
189
|
+
const expiresAt = localStorage.getItem(TokenClient.EXPIRES_AT_KEY)
|
|
151
190
|
if (!expiresAt) {
|
|
152
|
-
return true
|
|
191
|
+
return true
|
|
153
192
|
}
|
|
154
|
-
|
|
193
|
+
|
|
194
|
+
return parseInt(expiresAt) < Date.now()
|
|
155
195
|
}
|
|
196
|
+
|
|
156
197
|
/**
|
|
157
198
|
* Update access token after refresh
|
|
158
199
|
* ⚠️ IMPORTANT: Taruvi uses refresh token rotation
|
|
159
200
|
* When you refresh, you get BOTH a new access token AND a new refresh token
|
|
160
201
|
*/
|
|
161
|
-
updateAccessToken(accessToken, expiresIn) {
|
|
202
|
+
updateAccessToken(accessToken: string, expiresIn: number): void {
|
|
162
203
|
if (!this.browserRunTime) {
|
|
163
|
-
console.warn('Token update is only available in browser environment')
|
|
164
|
-
return
|
|
204
|
+
console.warn('Token update is only available in browser environment')
|
|
205
|
+
return
|
|
165
206
|
}
|
|
207
|
+
|
|
166
208
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
167
|
-
return
|
|
209
|
+
return
|
|
168
210
|
}
|
|
211
|
+
|
|
169
212
|
try {
|
|
170
|
-
localStorage.setItem(TokenClient.ACCESS_TOKEN_KEY, accessToken)
|
|
171
|
-
const expiresAt = Date.now() + (expiresIn * 1000)
|
|
172
|
-
localStorage.setItem(TokenClient.EXPIRES_AT_KEY, expiresAt.toString())
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
console.error('Failed to update access token:', err);
|
|
213
|
+
localStorage.setItem(TokenClient.ACCESS_TOKEN_KEY, accessToken)
|
|
214
|
+
const expiresAt = Date.now() + (expiresIn * 1000)
|
|
215
|
+
localStorage.setItem(TokenClient.EXPIRES_AT_KEY, expiresAt.toString())
|
|
216
|
+
} catch (err) {
|
|
217
|
+
console.error('Failed to update access token:', err)
|
|
176
218
|
}
|
|
177
219
|
}
|
|
220
|
+
|
|
178
221
|
/**
|
|
179
222
|
* Update refresh token after rotation
|
|
180
223
|
* ⚠️ IMPORTANT: Taruvi rotates refresh tokens
|
|
181
224
|
* Always update the refresh token when you receive a new one
|
|
182
225
|
*/
|
|
183
|
-
updateRefreshToken(refreshToken) {
|
|
226
|
+
updateRefreshToken(refreshToken: string): void {
|
|
184
227
|
if (!this.browserRunTime) {
|
|
185
|
-
console.warn('Token update is only available in browser environment')
|
|
186
|
-
return
|
|
228
|
+
console.warn('Token update is only available in browser environment')
|
|
229
|
+
return
|
|
187
230
|
}
|
|
231
|
+
|
|
188
232
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
189
|
-
return
|
|
233
|
+
return
|
|
190
234
|
}
|
|
235
|
+
|
|
191
236
|
try {
|
|
192
|
-
localStorage.setItem(TokenClient.REFRESH_TOKEN_KEY, refreshToken)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
console.error('Failed to update refresh token:', err);
|
|
237
|
+
localStorage.setItem(TokenClient.REFRESH_TOKEN_KEY, refreshToken)
|
|
238
|
+
} catch (err) {
|
|
239
|
+
console.error('Failed to update refresh token:', err)
|
|
196
240
|
}
|
|
197
241
|
}
|
|
242
|
+
|
|
198
243
|
/**
|
|
199
244
|
* Clear all tokens (logout)
|
|
200
245
|
*/
|
|
201
|
-
clearTokens() {
|
|
246
|
+
clearTokens(): void {
|
|
202
247
|
if (!this.browserRunTime) {
|
|
203
|
-
this.serverToken = null
|
|
204
|
-
return
|
|
248
|
+
this.serverToken = null
|
|
249
|
+
return
|
|
205
250
|
}
|
|
251
|
+
|
|
206
252
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
207
|
-
return
|
|
253
|
+
return
|
|
208
254
|
}
|
|
255
|
+
|
|
209
256
|
try {
|
|
210
|
-
localStorage.removeItem(TokenClient.ACCESS_TOKEN_KEY)
|
|
211
|
-
localStorage.removeItem(TokenClient.REFRESH_TOKEN_KEY)
|
|
212
|
-
localStorage.removeItem(TokenClient.SESSION_TOKEN_KEY)
|
|
213
|
-
localStorage.removeItem(TokenClient.EXPIRES_AT_KEY)
|
|
214
|
-
localStorage.removeItem(TokenClient.TOKEN_TYPE_KEY)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
console.error('Failed to clear tokens:', err);
|
|
257
|
+
localStorage.removeItem(TokenClient.ACCESS_TOKEN_KEY)
|
|
258
|
+
localStorage.removeItem(TokenClient.REFRESH_TOKEN_KEY)
|
|
259
|
+
localStorage.removeItem(TokenClient.SESSION_TOKEN_KEY)
|
|
260
|
+
localStorage.removeItem(TokenClient.EXPIRES_AT_KEY)
|
|
261
|
+
localStorage.removeItem(TokenClient.TOKEN_TYPE_KEY)
|
|
262
|
+
} catch (err) {
|
|
263
|
+
console.error('Failed to clear tokens:', err)
|
|
218
264
|
}
|
|
219
265
|
}
|
|
220
266
|
}
|
|
221
|
-
//# sourceMappingURL=TokenClient.js.map
|
|
File without changes
|