Access & Utils
Authentication management and utility functions for the De. SDK.
Access & Utils Overview
Access provides workspace authentication and API request management.
Utils offers helper functions for common operations.
Together they provide the foundation for all SDK operations.
Access - Authentication
The Access class handles workspace authentication and HTTP requests to De. APIs.
Initialization
1
Basic Setup
Initialize with workspace credentials
typescript
import De from '@de./sdk'
const access = new De.Access({
workspace: 'your-workspace-id',
accessToken: 'your-access-token',
env: 'prod' // 'dev', 'staging', or 'prod'
})Configuration Options:
typescript
{
workspace: string // Workspace ID (required)
accessToken?: string // Access token (optional for public endpoints)
env?: 'dev' | 'staging' | 'prod' // Environment
apiUrl?: string // Custom API URL
timeout?: number // Request timeout (ms)
retries?: number // Auto-retry count
headers?: Record<string, string> // Custom headers
}Making Requests
1
GET Request
Fetch data from API
typescript
// Get user profile
const user = await access.request({
url: '/user',
method: 'GET'
})
console.log('User:', user.data)
// Get with query parameters
const orders = await access.request({
url: '/orders',
method: 'GET',
query: {
status: 'in_transit',
limit: 20
}
})
console.log('Orders:', orders.data)2
POST Request
Create or submit data
typescript
// Create order
const order = await access.request({
url: '/orders',
method: 'POST',
body: {
type: 'delivery',
customer: {
name: 'John Doe',
phone: '+1234567890'
},
pickup: {
address: '123 Main St',
coordinates: { lng: -74.0060, lat: 40.7128 }
},
delivery: {
address: '456 Oak Ave',
coordinates: { lng: -73.9855, lat: 40.7580 }
}
}
})
console.log('Order created:', order.data.id)3
PATCH Request
Update existing data
typescript
// Update order
const updated = await access.request({
url: `/orders/${orderId}`,
method: 'PATCH',
body: {
status: 'in_transit',
metadata: {
priority: 'urgent'
}
}
})
console.log('Order updated:', updated.data)4
DELETE Request
Remove data
typescript
// Cancel order
const result = await access.request({
url: `/orders/${orderId}`,
method: 'DELETE'
})
console.log('Order cancelled:', result.success)Request Options
typescript
interface RequestOptions {
url: string // API endpoint
method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'
query?: Record<string, any> // Query parameters
body?: any // Request body
headers?: Record<string, string> // Custom headers
timeout?: number // Request timeout
retries?: number // Retry attempts
validateStatus?: (status: number) => boolean // Custom validation
}Response Format
typescript
interface APIResponse<T = any> {
success: boolean
data?: T
error?: {
code: string
message: string
details?: any
}
meta?: {
timestamp: string
requestId: string
}
}Token Management
Refreshing Tokens
1
Token Refresh
Refresh expired access token
typescript
// Store refresh token
const refreshToken = localStorage.getItem('refresh_token')
// Refresh access token
const result = await access.request({
url: '/auth/refresh',
method: 'POST',
body: { refreshToken }
})
// Update access token
access.setAccessToken(result.data.token)
localStorage.setItem('access_token', result.data.token)Auto Token Refresh
2
Automatic Refresh
Auto-refresh before expiration
typescript
class TokenManager {
private access: any
private refreshInterval: any
constructor(access: any) {
this.access = access
}
startAutoRefresh(tokenExpiresIn: number) {
// Refresh 5 minutes before expiration
const refreshTime = (tokenExpiresIn - 300) * 1000
this.refreshInterval = setInterval(async () => {
try {
await this.refreshToken()
} catch (error) {
console.error('Token refresh failed:', error)
this.handleRefreshFailure()
}
}, refreshTime)
}
async refreshToken() {
const refreshToken = localStorage.getItem('refresh_token')
const result = await this.access.request({
url: '/auth/refresh',
method: 'POST',
body: { refreshToken }
})
this.access.setAccessToken(result.data.token)
localStorage.setItem('access_token', result.data.token)
}
stopAutoRefresh() {
clearInterval(this.refreshInterval)
}
private handleRefreshFailure() {
// Redirect to login
window.location.href = '/login'
}
}
// Usage
const tokenManager = new TokenManager(access)
tokenManager.startAutoRefresh(3600) // Token expires in 1 hourError Handling
Handling Errors
typescript
try {
const result = await access.request({
url: '/orders',
method: 'POST',
body: orderData
})
} catch (error: any) {
switch (error.code) {
case 'UNAUTHORIZED':
// Token expired or invalid
redirectToLogin()
break
case 'VALIDATION_ERROR':
// Invalid request data
showValidationErrors(error.details)
break
case 'RATE_LIMIT':
// Too many requests
const retryAfter = error.retryAfter || 60
showRetryMessage(`Please wait ${retryAfter} seconds`)
break
case 'SERVER_ERROR':
// Server issue
showErrorMessage('Server error. Please try again later.')
break
case 'NETWORK_ERROR':
// No internet connection
showErrorMessage('No internet connection')
break
default:
showErrorMessage(error.message)
}
}Retry Logic
typescript
async function requestWithRetry<T>(
access: any,
options: any,
maxRetries = 3
): Promise<T> {
let lastError: any
for (let i = 0; i < maxRetries; i++) {
try {
return await access.request(options)
} catch (error: any) {
lastError = error
// Don't retry client errors (4xx)
if (error.status >= 400 && error.status < 500) {
throw error
}
// Wait before retry (exponential backoff)
if (i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000
await new Promise(resolve => setTimeout(resolve, delay))
}
}
}
throw lastError
}
// Usage
const order = await requestWithRetry(access, {
url: '/orders',
method: 'POST',
body: orderData
})Utils - Helper Functions
Utility functions for common operations.
Distance Calculations
1
Calculate Distance
Distance between two coordinates
typescript
import { utils } from '@de./sdk'
const point1 = { lng: -74.0060, lat: 40.7128 }
const point2 = { lng: -73.9855, lat: 40.7580 }
// Calculate distance in meters
const distance = utils.calculateDistance(point1, point2)
console.log('Distance:', distance, 'meters')
// Calculate distance in kilometers
const distanceKm = utils.calculateDistance(point1, point2, 'km')
console.log('Distance:', distanceKm, 'km')
// Calculate distance in miles
const distanceMi = utils.calculateDistance(point1, point2, 'mi')
console.log('Distance:', distanceMi, 'miles')Coordinate Formatting
2
Format Coordinates
Convert coordinate formats
typescript
// Decimal to DMS (Degrees, Minutes, Seconds)
const dms = utils.formatCoordinates({ lng: -74.0060, lat: 40.7128 }, 'dms')
console.log('DMS:', dms)
// "40°42'46.1"N 74°00'21.6"W"
// Decimal to human-readable
const readable = utils.formatCoordinates({ lng: -74.0060, lat: 40.7128 })
console.log('Readable:', readable)
// "40.7128, -74.0060"
// Parse from string
const coords = utils.parseCoordinates('40.7128, -74.0060')
console.log('Parsed:', coords)
// { lng: -74.0060, lat: 40.7128 }Bounds Calculations
3
Calculate Bounds
Get bounding box for coordinates
typescript
const points = [
{ lng: -74.0060, lat: 40.7128 },
{ lng: -73.9855, lat: 40.7580 },
{ lng: -73.9951, lat: 40.7489 }
]
const bounds = utils.calculateBounds(points)
console.log('Bounds:', bounds)
// {
// southwest: { lng: -74.0060, lat: 40.7128 },
// northeast: { lng: -73.9855, lat: 40.7580 }
// }
// With padding
const paddedBounds = utils.calculateBounds(points, 0.01)Distance Formatting
typescript
// Format distance
const formatted = utils.formatDistance(5420)
console.log(formatted)
// "5.42 km"
// With units
const metric = utils.formatDistance(5420, 'metric')
console.log(metric)
// "5.42 km"
const imperial = utils.formatDistance(5420, 'imperial')
console.log(imperial)
// "3.37 mi"
// Custom precision
const precise = utils.formatDistance(5420, 'metric', 1)
console.log(precise)
// "5.4 km"Duration Formatting
typescript
// Format duration in seconds
const duration = utils.formatDuration(3665)
console.log(duration)
// "1h 1m 5s"
// Short format
const short = utils.formatDuration(3665, 'short')
console.log(short)
// "1:01:05"
// Human readable
const readable = utils.formatDuration(3665, 'readable')
console.log(readable)
// "1 hour, 1 minute"Coordinate Validation
typescript
// Validate coordinates
const valid = utils.validateCoordinates({ lng: -74.0060, lat: 40.7128 })
console.log('Valid:', valid)
// true
const invalid = utils.validateCoordinates({ lng: 200, lat: 100 })
console.log('Valid:', invalid)
// false
// Validate bounds
const validBounds = utils.validateBounds({
southwest: { lng: -74.1, lat: 40.6 },
northeast: { lng: -73.9, lat: 40.8 }
})Geocoding Utilities
typescript
// Extract coordinates from various formats
const coords1 = utils.extractCoordinates('40.7128, -74.0060')
const coords2 = utils.extractCoordinates('40.7128,-74.0060')
const coords3 = utils.extractCoordinates({ lat: 40.7128, lng: -74.0060 })
// All return: { lng: -74.0060, lat: 40.7128 }
// Format address
const formatted = utils.formatAddress({
street: '123 Main St',
city: 'New York',
state: 'NY',
postalCode: '10001',
country: 'USA'
})
console.log(formatted)
// "123 Main St, New York, NY 10001, USA"Array Utilities
typescript
// Chunk array
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9]
const chunks = utils.chunk(items, 3)
console.log(chunks)
// [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// Unique values
const unique = utils.unique([1, 2, 2, 3, 3, 3, 4])
console.log(unique)
// [1, 2, 3, 4]
// Group by property
const orders = [
{ id: 1, status: 'pending' },
{ id: 2, status: 'delivered' },
{ id: 3, status: 'pending' }
]
const grouped = utils.groupBy(orders, 'status')
console.log(grouped)
// {
// pending: [{ id: 1, ... }, { id: 3, ... }],
// delivered: [{ id: 2, ... }]
// }Date Utilities
typescript
// Format timestamp
const formatted = utils.formatTimestamp(Date.now())
console.log(formatted)
// "2024-03-15 14:30:45"
// Relative time
const relative = utils.relativeTime(Date.now() - 3600000)
console.log(relative)
// "1 hour ago"
// Parse ISO date
const date = utils.parseDate('2024-03-15T14:30:00Z')
console.log(date)
// Date object
// Time difference
const diff = utils.timeDifference(start, end)
console.log(diff)
// { hours: 2, minutes: 30, seconds: 45 }Complete Examples
Authenticated API Client
typescript
class APIClient {
private access: any
constructor(workspace: string, token: string) {
this.access = new De.Access({
workspace,
accessToken: token,
env: 'prod',
timeout: 30000,
retries: 3
})
}
async getOrders(filters?: any) {
return this.access.request({
url: '/orders',
method: 'GET',
query: filters
})
}
async createOrder(data: any) {
return this.access.request({
url: '/orders',
method: 'POST',
body: data
})
}
async updateOrder(id: string, updates: any) {
return this.access.request({
url: `/orders/${id}`,
method: 'PATCH',
body: updates
})
}
async cancelOrder(id: string, reason?: string) {
return this.access.request({
url: `/orders/${id}/cancel`,
method: 'POST',
body: { reason }
})
}
}
// Usage
const api = new APIClient(workspaceId, accessToken)
const orders = await api.getOrders({ status: 'in_transit' })
const newOrder = await api.createOrder(orderData)Distance Calculator
typescript
class DistanceCalculator {
calculateRouteDistance(waypoints: Location[]): number {
let totalDistance = 0
for (let i = 0; i < waypoints.length - 1; i++) {
const distance = utils.calculateDistance(
waypoints[i],
waypoints[i + 1]
)
totalDistance += distance
}
return totalDistance
}
findNearestLocation(
origin: Location,
locations: Location[]
): Location & { distance: number } {
return locations
.map(loc => ({
...loc,
distance: utils.calculateDistance(origin, loc)
}))
.sort((a, b) => a.distance - b.distance)[0]
}
isWithinRadius(
center: Location,
point: Location,
radius: number
): boolean {
const distance = utils.calculateDistance(center, point)
return distance <= radius
}
formatDistanceForDisplay(meters: number, unit: 'metric' | 'imperial' = 'metric'): string {
if (unit === 'imperial') {
const miles = meters * 0.000621371
return miles < 0.1
? `${Math.round(meters * 3.28084)} ft`
: `${miles.toFixed(2)} mi`
}
return meters < 1000
? `${Math.round(meters)} m`
: `${(meters / 1000).toFixed(2)} km`
}
}
// Usage
const calculator = new DistanceCalculator()
const routeDistance = calculator.calculateRouteDistance(waypoints)
const nearest = calculator.findNearestLocation(userLocation, warehouses)
const isNear = calculator.isWithinRadius(warehouse, delivery, 5000)Type Definitions
typescript
interface AccessConfig {
workspace: string
accessToken?: string
env?: 'dev' | 'staging' | 'prod'
apiUrl?: string
timeout?: number
retries?: number
headers?: Record<string, string>
}
interface Location {
lng: number
lat: number
}
interface Bounds {
southwest: Location
northeast: Location
}
interface Utils {
calculateDistance(p1: Location, p2: Location, unit?: 'm' | 'km' | 'mi'): number
formatCoordinates(coords: Location, format?: 'decimal' | 'dms'): string
parseCoordinates(str: string): Location
calculateBounds(points: Location[], padding?: number): Bounds
validateCoordinates(coords: Location): boolean
formatDistance(meters: number, unit?: 'metric' | 'imperial', precision?: number): string
formatDuration(seconds: number, format?: 'long' | 'short' | 'readable'): string
}Best Practices
Do
- Store tokens securely (never in code)
- Implement token refresh logic
- Handle all error cases
- Use appropriate timeout values
- Validate data before requests
- Cache frequently used data
- Use utils for calculations
Avoid
- Hardcoding credentials
- Ignoring error responses
- Making excessive API calls
- Storing tokens in localStorage in production
- Skipping input validation
- Reinventing utility functions
- Exposing tokens in client code
Environment Configuration
typescript
// config.ts
const config = {
development: {
workspace: process.env.DEV_WORKSPACE_ID,
accessToken: process.env.DEV_ACCESS_TOKEN,
apiUrl: 'https://dev-api.dedot.io'
},
staging: {
workspace: process.env.STAGING_WORKSPACE_ID,
accessToken: process.env.STAGING_ACCESS_TOKEN,
apiUrl: 'https://staging-api.dedot.io'
},
production: {
workspace: process.env.PROD_WORKSPACE_ID,
accessToken: process.env.PROD_ACCESS_TOKEN,
apiUrl: 'https://api.dedot.io'
}
}
const env = process.env.NODE_ENV || 'development'
export default config[env]
// Usage
import config from './config'
const access = new De.Access(config)
