@taruvi/sdk 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/.claude/settings.local.json +16 -0
- package/DATAPROVIDER_CONTEXT.md +828 -0
- package/README.md +703 -0
- package/USAGE_EXAMPLE.md +86 -0
- package/package.json +25 -0
- package/src/client.ts +81 -0
- package/src/index.ts +20 -0
- package/src/lib/Database/DatabaseClient.ts +87 -0
- package/src/lib/Database/types.ts +29 -0
- package/src/lib/Function/FunctionsClient.ts +27 -0
- package/src/lib/Function/types.ts +17 -0
- package/src/lib/Secrets/SecretsClient.ts +44 -0
- package/src/lib/Secrets/types.ts +17 -0
- package/src/lib/Settings/SettingsClient.ts +14 -0
- package/src/lib/Settings/types.ts +4 -0
- package/src/lib/Storage/StorageClient.ts +88 -0
- package/src/lib/Storage/types.ts +40 -0
- package/src/lib/auth/AuthClient.ts +64 -0
- package/src/lib/auth/types.ts +9 -0
- package/src/lib/user/UserClient.ts +44 -0
- package/src/lib/user/types.ts +69 -0
- package/src/lib-internal/errors/ErrorClient.ts +12 -0
- package/src/lib-internal/errors/index.ts +25 -0
- package/src/lib-internal/errors/types.ts +105 -0
- package/src/lib-internal/http/HttpClient.ts +96 -0
- package/src/lib-internal/http/types.ts +10 -0
- package/src/lib-internal/routes/AuthRoutes.ts +0 -0
- package/src/lib-internal/routes/DatabaseRoutes.ts +5 -0
- package/src/lib-internal/routes/FunctionRoutes.ts +3 -0
- package/src/lib-internal/routes/RouteBuilder.ts +0 -0
- package/src/lib-internal/routes/SecretsRoutes.ts +5 -0
- package/src/lib-internal/routes/SettingsRoutes.ts +3 -0
- package/src/lib-internal/routes/StorageRoutes.ts +7 -0
- package/src/lib-internal/routes/UserRoutes.ts +9 -0
- package/src/lib-internal/routes/index.ts +0 -0
- package/src/lib-internal/token/TokenClient.ts +30 -0
- package/src/lib-internal/token/types.ts +0 -0
- package/src/types.ts +68 -0
- package/src/utils/enums.ts +12 -0
- package/src/utils/utils.ts +36 -0
- package/tests/mocks/db.json +1 -0
- package/tsconfig.json +43 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Client } from "../../client.js";
|
|
2
|
+
import type { UserCreateRequest, UserCreateResponse, UserDataResponse, UserList, UserUpdateRequest } from "./types.js";
|
|
3
|
+
import { UserRoutes } from "../../lib-internal/routes/UserRoutes.js";
|
|
4
|
+
import { buildQueryString } from "../../utils/utils.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export class User {
|
|
8
|
+
private client: Client
|
|
9
|
+
|
|
10
|
+
constructor(client: Client) {
|
|
11
|
+
this.client = client
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// - getUserProfile
|
|
15
|
+
async getUserData(): Promise<UserDataResponse> {
|
|
16
|
+
return await this.client.httpClient.get<UserDataResponse>(UserRoutes.getCurrentUser())
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// - updateUser
|
|
20
|
+
async updateUser(username: string, body: UserUpdateRequest): Promise<UserCreateResponse> {
|
|
21
|
+
return await this.client.httpClient.put(UserRoutes.updateUser(username), body)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async list(filters: UserList) {
|
|
25
|
+
const queryString = buildQueryString(filters as unknown as Record<string, unknown>)
|
|
26
|
+
return await this.client.httpClient.get(UserRoutes.listUser(queryString))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// - createUser
|
|
30
|
+
async createUser(userData: UserCreateRequest): Promise<UserCreateResponse> {
|
|
31
|
+
return await this.client.httpClient.post<UserCreateResponse, UserCreateRequest>(
|
|
32
|
+
UserRoutes.baseUrl,
|
|
33
|
+
userData
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// - deleteUser
|
|
38
|
+
async deleteUser(username: string): Promise<void> {
|
|
39
|
+
return await this.client.httpClient.delete(UserRoutes.deleteUser(username))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// TODO: Implement user management methods
|
|
43
|
+
// - token getter (access JWT token)
|
|
44
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export interface UserCreateRequest {
|
|
2
|
+
username: string,
|
|
3
|
+
email: string,
|
|
4
|
+
password: string,
|
|
5
|
+
confirm_password: string,
|
|
6
|
+
first_name: string,
|
|
7
|
+
last_name: string,
|
|
8
|
+
is_active: boolean,
|
|
9
|
+
is_staff: boolean,
|
|
10
|
+
attributes: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface UserCreateResponse {
|
|
14
|
+
username: string,
|
|
15
|
+
email: string,
|
|
16
|
+
first_name: string,
|
|
17
|
+
last_name: string,
|
|
18
|
+
is_active: boolean,
|
|
19
|
+
is_staff: boolean,
|
|
20
|
+
attributes: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface UserDataResponse {
|
|
24
|
+
id: number,
|
|
25
|
+
username: string,
|
|
26
|
+
email: string,
|
|
27
|
+
first_name: string,
|
|
28
|
+
last_name: string,
|
|
29
|
+
full_name: string,
|
|
30
|
+
is_active: boolean,
|
|
31
|
+
is_staff: boolean,
|
|
32
|
+
is_deleted: boolean,
|
|
33
|
+
date_joined: string, // ISO 8601 date-time string
|
|
34
|
+
last_login: string, // ISO 8601 date-time string
|
|
35
|
+
attributes: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface UserUpdateRequest {
|
|
39
|
+
username?: string,
|
|
40
|
+
email?: string,
|
|
41
|
+
password?: string,
|
|
42
|
+
confirm_password?: string,
|
|
43
|
+
first_name?: string,
|
|
44
|
+
last_name?: string,
|
|
45
|
+
is_active?: boolean,
|
|
46
|
+
is_staff?: boolean,
|
|
47
|
+
attributes?: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface UserUpdateResponse {
|
|
51
|
+
username: string,
|
|
52
|
+
email: string,
|
|
53
|
+
first_name: string,
|
|
54
|
+
last_name: string,
|
|
55
|
+
is_active: boolean,
|
|
56
|
+
is_staff: boolean,
|
|
57
|
+
attributes: string
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface UserList {
|
|
61
|
+
search: string
|
|
62
|
+
is_active: boolean
|
|
63
|
+
is_staff: boolean
|
|
64
|
+
is_superuser: boolean
|
|
65
|
+
is_deleted: boolean
|
|
66
|
+
ordering: string
|
|
67
|
+
page: Number
|
|
68
|
+
page_size: Number
|
|
69
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error handling module exports
|
|
3
|
+
*
|
|
4
|
+
* This module provides comprehensive error handling for the Taruvi SDK
|
|
5
|
+
* including typed error classes, error codes, and utility functions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Export error client
|
|
9
|
+
export { ErrorClient } from './ErrorClient.js';
|
|
10
|
+
|
|
11
|
+
// TODO: Export all error classes when implemented
|
|
12
|
+
// - TaruviError
|
|
13
|
+
// - AuthError
|
|
14
|
+
// - DatabaseError
|
|
15
|
+
// - StorageError
|
|
16
|
+
// - NetworkError
|
|
17
|
+
// - ValidationError
|
|
18
|
+
// - FunctionError
|
|
19
|
+
|
|
20
|
+
// TODO: Export types when implemented
|
|
21
|
+
// - ErrorCode
|
|
22
|
+
// - ErrorSeverity
|
|
23
|
+
// - ErrorResponse
|
|
24
|
+
// - HttpErrorResponse
|
|
25
|
+
// - ValidationErrorDetail
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error severity levels for categorizing errors
|
|
3
|
+
*/
|
|
4
|
+
export enum ErrorSeverity {
|
|
5
|
+
LOW = 'low',
|
|
6
|
+
MEDIUM = 'medium',
|
|
7
|
+
HIGH = 'high',
|
|
8
|
+
CRITICAL = 'critical'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Standard error codes used across the SDK
|
|
13
|
+
*/
|
|
14
|
+
export enum ErrorCode {
|
|
15
|
+
// General errors (1000-1099)
|
|
16
|
+
UNKNOWN_ERROR = 'UNKNOWN_ERROR',
|
|
17
|
+
INTERNAL_ERROR = 'INTERNAL_ERROR',
|
|
18
|
+
TIMEOUT_ERROR = 'TIMEOUT_ERROR',
|
|
19
|
+
|
|
20
|
+
// Network errors (1100-1199)
|
|
21
|
+
NETWORK_ERROR = 'NETWORK_ERROR',
|
|
22
|
+
CONNECTION_ERROR = 'CONNECTION_ERROR',
|
|
23
|
+
REQUEST_FAILED = 'REQUEST_FAILED',
|
|
24
|
+
|
|
25
|
+
// Authentication errors (1200-1299)
|
|
26
|
+
AUTH_ERROR = 'AUTH_ERROR',
|
|
27
|
+
UNAUTHORIZED = 'UNAUTHORIZED',
|
|
28
|
+
TOKEN_EXPIRED = 'TOKEN_EXPIRED',
|
|
29
|
+
TOKEN_INVALID = 'TOKEN_INVALID',
|
|
30
|
+
SESSION_EXPIRED = 'SESSION_EXPIRED',
|
|
31
|
+
INVALID_CREDENTIALS = 'INVALID_CREDENTIALS',
|
|
32
|
+
|
|
33
|
+
// Authorization errors (1300-1399)
|
|
34
|
+
FORBIDDEN = 'FORBIDDEN',
|
|
35
|
+
INSUFFICIENT_PERMISSIONS = 'INSUFFICIENT_PERMISSIONS',
|
|
36
|
+
|
|
37
|
+
// Validation errors (1400-1499)
|
|
38
|
+
VALIDATION_ERROR = 'VALIDATION_ERROR',
|
|
39
|
+
INVALID_INPUT = 'INVALID_INPUT',
|
|
40
|
+
MISSING_REQUIRED_FIELD = 'MISSING_REQUIRED_FIELD',
|
|
41
|
+
INVALID_FORMAT = 'INVALID_FORMAT',
|
|
42
|
+
|
|
43
|
+
// Database errors (1500-1599)
|
|
44
|
+
DATABASE_ERROR = 'DATABASE_ERROR',
|
|
45
|
+
QUERY_FAILED = 'QUERY_FAILED',
|
|
46
|
+
RECORD_NOT_FOUND = 'RECORD_NOT_FOUND',
|
|
47
|
+
DUPLICATE_ENTRY = 'DUPLICATE_ENTRY',
|
|
48
|
+
CONSTRAINT_VIOLATION = 'CONSTRAINT_VIOLATION',
|
|
49
|
+
|
|
50
|
+
// Storage errors (1600-1699)
|
|
51
|
+
STORAGE_ERROR = 'STORAGE_ERROR',
|
|
52
|
+
FILE_NOT_FOUND = 'FILE_NOT_FOUND',
|
|
53
|
+
FILE_TOO_LARGE = 'FILE_TOO_LARGE',
|
|
54
|
+
INVALID_FILE_TYPE = 'INVALID_FILE_TYPE',
|
|
55
|
+
UPLOAD_FAILED = 'UPLOAD_FAILED',
|
|
56
|
+
DOWNLOAD_FAILED = 'DOWNLOAD_FAILED',
|
|
57
|
+
|
|
58
|
+
// Function errors (1700-1799)
|
|
59
|
+
FUNCTION_ERROR = 'FUNCTION_ERROR',
|
|
60
|
+
FUNCTION_NOT_FOUND = 'FUNCTION_NOT_FOUND',
|
|
61
|
+
FUNCTION_EXECUTION_FAILED = 'FUNCTION_EXECUTION_FAILED',
|
|
62
|
+
FUNCTION_TIMEOUT = 'FUNCTION_TIMEOUT',
|
|
63
|
+
|
|
64
|
+
// Rate limiting errors (1800-1899)
|
|
65
|
+
RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
|
|
66
|
+
QUOTA_EXCEEDED = 'QUOTA_EXCEEDED',
|
|
67
|
+
|
|
68
|
+
// Client errors (1900-1999)
|
|
69
|
+
CONFIGURATION_ERROR = 'CONFIGURATION_ERROR',
|
|
70
|
+
INVALID_API_KEY = 'INVALID_API_KEY',
|
|
71
|
+
INVALID_CONFIG = 'INVALID_CONFIG'
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Base error response structure
|
|
76
|
+
*/
|
|
77
|
+
export interface ErrorResponse {
|
|
78
|
+
code: ErrorCode;
|
|
79
|
+
message: string;
|
|
80
|
+
severity: ErrorSeverity;
|
|
81
|
+
timestamp: string;
|
|
82
|
+
requestId?: string | undefined;
|
|
83
|
+
metadata?: Record<string, any> | undefined;
|
|
84
|
+
cause?: Error | undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* HTTP error response from the server
|
|
89
|
+
*/
|
|
90
|
+
export interface HttpErrorResponse {
|
|
91
|
+
status: number;
|
|
92
|
+
statusText: string;
|
|
93
|
+
message?: string;
|
|
94
|
+
code?: string;
|
|
95
|
+
details?: any;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Validation error details
|
|
100
|
+
*/
|
|
101
|
+
export interface ValidationErrorDetail {
|
|
102
|
+
field: string;
|
|
103
|
+
message: string;
|
|
104
|
+
value?: any;
|
|
105
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { TaruviConfig } from "../../types.js";
|
|
2
|
+
import type { TokenClient } from "../token/TokenClient.js";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* HttpClient handles all HTTP requests to the Taruvi API.
|
|
7
|
+
* Automatically adds authentication headers:
|
|
8
|
+
* - Authorization: API key for site/app identification
|
|
9
|
+
* - X-Session-Token: User session token for authenticated requests
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export class HttpClient {
|
|
14
|
+
private config: TaruviConfig
|
|
15
|
+
private tokenClient: TokenClient
|
|
16
|
+
|
|
17
|
+
constructor(config: TaruviConfig, tokenClient: TokenClient) {
|
|
18
|
+
this.config = config
|
|
19
|
+
this.tokenClient = tokenClient
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private getAuthHeaders(isFormData: boolean = false): Record<string, string> {
|
|
23
|
+
const headers: Record<string, string> = {}
|
|
24
|
+
|
|
25
|
+
// Don't set Content-Type for FormData - let axios set it with the boundary
|
|
26
|
+
if (!isFormData) {
|
|
27
|
+
headers['Content-Type'] = 'application/json'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Site/app API key (developer authentication)
|
|
31
|
+
if (this.config.apiKey) {
|
|
32
|
+
headers['Authorization'] = `Token ${this.config.apiKey}`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Tenant admin session token
|
|
36
|
+
const jwt = this.tokenClient.getToken()
|
|
37
|
+
if (jwt) {
|
|
38
|
+
headers['Authorization'] = `Bearer ${jwt}`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return headers
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async get<T>(endpoint: string) {
|
|
45
|
+
const { data } = await axios.get(`${this.config.baseUrl}/${endpoint}`, {
|
|
46
|
+
headers: this.getAuthHeaders()
|
|
47
|
+
})
|
|
48
|
+
return data
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async post<T, D = any>(endpoint: string, body: D): Promise<T> {
|
|
52
|
+
const isFormData = body instanceof FormData
|
|
53
|
+
const { data } = await axios.post<T>(
|
|
54
|
+
`${this.config.baseUrl}/${endpoint}`,
|
|
55
|
+
body,
|
|
56
|
+
{
|
|
57
|
+
headers: this.getAuthHeaders(isFormData)
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
return data
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async put<T, D = any>(endpoint: string, body: D) {
|
|
64
|
+
const isFormData = body instanceof FormData
|
|
65
|
+
const { data } = await axios.put<T>(`${this.config.baseUrl}/${endpoint}`,
|
|
66
|
+
body,
|
|
67
|
+
{
|
|
68
|
+
headers: this.getAuthHeaders(isFormData)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
return data
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async delete<T, D = any>(endpoint: string, body?: D): Promise<T> {
|
|
75
|
+
const { data } = await axios.delete<T>(
|
|
76
|
+
`${this.config.baseUrl}/${endpoint}`,
|
|
77
|
+
{
|
|
78
|
+
headers: this.getAuthHeaders(),
|
|
79
|
+
data: body
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
return data
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async patch<T, D = any>(endpoint: string, body: D): Promise<T> {
|
|
86
|
+
const isFormData = body instanceof FormData
|
|
87
|
+
const { data } = await axios.patch<T>(
|
|
88
|
+
`${this.config.baseUrl}/${endpoint}`,
|
|
89
|
+
body,
|
|
90
|
+
{
|
|
91
|
+
headers: this.getAuthHeaders(isFormData)
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
return data
|
|
95
|
+
}
|
|
96
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const StorageRoutes = {
|
|
2
|
+
baseUrl: (appslug: string, bucket: string) => `api/apps/${appslug}/storage/buckets/${bucket}/objects`,
|
|
3
|
+
path: (path: string) => "/" + path,
|
|
4
|
+
upload: () => "/batch-upload",
|
|
5
|
+
delete: () => "/batch-delete"
|
|
6
|
+
// bucket: (appslug: string, bucketslug: string) => `${StorageRoutesClone.baseUrl(appslug)}/${bucketslug}`
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UserList } from "../../lib/user/types.js";
|
|
2
|
+
|
|
3
|
+
export const UserRoutes = {
|
|
4
|
+
baseUrl: "api/users/",
|
|
5
|
+
getCurrentUser: () => `${UserRoutes.baseUrl}me/`,
|
|
6
|
+
updateUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
7
|
+
deleteUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
|
|
8
|
+
listUser: (filter: string) => `${UserRoutes.baseUrl}${filter}`
|
|
9
|
+
} as const
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getRuntimeEnvironment } from "../../utils/utils.js"
|
|
2
|
+
|
|
3
|
+
export class TokenClient {
|
|
4
|
+
// private tenantAdminToken: string | null = null
|
|
5
|
+
private runTimeEnvironment: string
|
|
6
|
+
private browserRunTime: boolean
|
|
7
|
+
// private adminSessionToken: string | null
|
|
8
|
+
|
|
9
|
+
constructor(token?: string) {
|
|
10
|
+
this.runTimeEnvironment = getRuntimeEnvironment()
|
|
11
|
+
this.browserRunTime = this.runTimeEnvironment == "Browser"
|
|
12
|
+
// this.adminSessionToken = this.getToken()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getToken(): string | null {
|
|
16
|
+
if (this.browserRunTime) {
|
|
17
|
+
// return localStorage.getItem("")
|
|
18
|
+
return localStorage.getItem("jwt")
|
|
19
|
+
}
|
|
20
|
+
return null
|
|
21
|
+
// return this.tenantAdminToken
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// TODO: Implement token management
|
|
25
|
+
// - setToken
|
|
26
|
+
// - getToken
|
|
27
|
+
// - refreshToken
|
|
28
|
+
// - clearToken
|
|
29
|
+
// - isTokenExpired
|
|
30
|
+
}
|
|
File without changes
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { MimeTypeCategory, Visibility } from './utils/enums.js'
|
|
2
|
+
|
|
3
|
+
export interface TaruviConfig {
|
|
4
|
+
apiKey: string // Identifies which site the client belongs to
|
|
5
|
+
appSlug: string // Identifies which app the client belongs to
|
|
6
|
+
baseUrl: string
|
|
7
|
+
deskUrl?: string // URL for the desk/login page
|
|
8
|
+
token?: string // Optional: Pre-existing auth token
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface StorageFilters {
|
|
12
|
+
// Pagination (DRF style)
|
|
13
|
+
page?: number
|
|
14
|
+
pageSize?: number
|
|
15
|
+
|
|
16
|
+
// Range Filters - Size (in bytes)
|
|
17
|
+
size__gte?: number
|
|
18
|
+
size__lte?: number
|
|
19
|
+
size__gt?: number
|
|
20
|
+
size__lt?: number
|
|
21
|
+
min_size?: number
|
|
22
|
+
max_size?: number
|
|
23
|
+
|
|
24
|
+
// Range Filters - Dates (ISO 8601)
|
|
25
|
+
created_at__gte?: string
|
|
26
|
+
created_at__lte?: string
|
|
27
|
+
created_after?: string
|
|
28
|
+
created_before?: string
|
|
29
|
+
updated_at__gte?: string
|
|
30
|
+
updated_at__lte?: string
|
|
31
|
+
|
|
32
|
+
// Search Filters
|
|
33
|
+
search?: string
|
|
34
|
+
filename__icontains?: string
|
|
35
|
+
prefix?: string
|
|
36
|
+
file?: string
|
|
37
|
+
file__icontains?: string
|
|
38
|
+
file__startswith?: string
|
|
39
|
+
file__istartswith?: string
|
|
40
|
+
metadata_search?: string
|
|
41
|
+
|
|
42
|
+
// MIME Type Filters
|
|
43
|
+
mimetype?: string
|
|
44
|
+
mimetype__in?: string
|
|
45
|
+
mimetype_category?: MimeTypeCategory
|
|
46
|
+
|
|
47
|
+
// Visibility & User Filters
|
|
48
|
+
visibility?: Visibility
|
|
49
|
+
created_by_me?: boolean
|
|
50
|
+
modified_by_me?: boolean
|
|
51
|
+
created_by__username?: string
|
|
52
|
+
created_by__username__icontains?: string
|
|
53
|
+
|
|
54
|
+
// Sorting
|
|
55
|
+
ordering?: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface DatabaseFilters {
|
|
59
|
+
// Pagination (DRF style)
|
|
60
|
+
page?: number
|
|
61
|
+
pageSize?: number
|
|
62
|
+
|
|
63
|
+
// Sorting (DRF style: "-field" for desc, "field" for asc)
|
|
64
|
+
ordering?: string
|
|
65
|
+
|
|
66
|
+
// Dynamic filters - allows any field with operators
|
|
67
|
+
[key: string]: string | number | boolean | undefined
|
|
68
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const _window = typeof window !== 'undefined' ? window : undefined
|
|
2
|
+
const _global = typeof global !== 'undefined' ? global : undefined
|
|
3
|
+
const _process = typeof process !== 'undefined' ? process : undefined
|
|
4
|
+
const _navigator = typeof navigator !== 'undefined' ? navigator : undefined
|
|
5
|
+
const _document = typeof document !== 'undefined' ? document : undefined
|
|
6
|
+
const _self = typeof self !== 'undefined' ? self : undefined
|
|
7
|
+
|
|
8
|
+
export const isBrowser = (): boolean => {
|
|
9
|
+
return _window !== undefined && _document !== undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const isReactNative = (): boolean => {
|
|
13
|
+
return _navigator !== undefined &&
|
|
14
|
+
// @ts-ignore - navigator.product is deprecated but still used in RN detection
|
|
15
|
+
_navigator.product === 'ReactNative'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const getRuntimeEnvironment = (): string => {
|
|
19
|
+
if (isBrowser()) return 'Browser'
|
|
20
|
+
if (isReactNative()) return 'ReactNative'
|
|
21
|
+
return 'Server'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function buildQueryString(filters: Record<string, unknown> | undefined): string {
|
|
25
|
+
if (!filters || Object.keys(filters).length === 0) {
|
|
26
|
+
return ''
|
|
27
|
+
}
|
|
28
|
+
const params = new URLSearchParams()
|
|
29
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
30
|
+
if (value !== undefined && value !== null) {
|
|
31
|
+
params.append(key, String(value))
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
const queryString = params.toString()
|
|
35
|
+
return queryString ? `?${queryString}` : ''
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Visit https://aka.ms/tsconfig to read more about this file
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
// File Layout
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
|
|
8
|
+
// Environment Settings
|
|
9
|
+
// See also https://aka.ms/tsconfig/module
|
|
10
|
+
"module": "nodenext",
|
|
11
|
+
"target": "esnext",
|
|
12
|
+
"lib": ["esnext", "dom"],
|
|
13
|
+
"types": ["node"],
|
|
14
|
+
|
|
15
|
+
// Other Outputs
|
|
16
|
+
"sourceMap": true,
|
|
17
|
+
"declaration": true,
|
|
18
|
+
"declarationMap": true,
|
|
19
|
+
|
|
20
|
+
// Stricter Typechecking Options
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
"exactOptionalPropertyTypes": true,
|
|
23
|
+
|
|
24
|
+
// Style Options
|
|
25
|
+
// "noImplicitReturns": true,
|
|
26
|
+
// "noImplicitOverride": true,
|
|
27
|
+
// "noUnusedLocals": true,
|
|
28
|
+
// "noUnusedParameters": true,
|
|
29
|
+
// "noFallthroughCasesInSwitch": true,
|
|
30
|
+
// "noPropertyAccessFromIndexSignature": true,
|
|
31
|
+
|
|
32
|
+
// Recommended Options
|
|
33
|
+
"strict": true,
|
|
34
|
+
"jsx": "react-jsx",
|
|
35
|
+
"verbatimModuleSyntax": true,
|
|
36
|
+
"isolatedModules": true,
|
|
37
|
+
"noUncheckedSideEffectImports": true,
|
|
38
|
+
"moduleDetection": "force",
|
|
39
|
+
"skipLibCheck": true,
|
|
40
|
+
},
|
|
41
|
+
"include": ["src/**/*"],
|
|
42
|
+
"exclude": ["node_modules", "dist", "taruvi-platform", "tests"]
|
|
43
|
+
}
|