onairos
Version:
The Onairos Library is a collection of functions that enable Applications to connect and communicate data with Onairos Identities via User Authorization. Integration for developers is seamless, simple and effective for all applications. LLM SDK capabiliti
576 lines (506 loc) • 15.5 kB
JavaScript
/**
* Authentication and SDK Type Definitions
*
* This file contains type definitions and validation schemas for the Onairos SDK
* Used for request validation, response formatting, and documentation
*/
/**
* Authentication Types
*/
export const AuthenticationTypes = {
API_KEY: 'api_key',
USER_JWT: 'user_jwt',
DUAL_AUTH: 'dual_auth',
ADMIN: 'admin'
};
/**
* User Types
*/
export const UserTypes = {
ENOCH: 'enoch',
ONAIROS: 'onairos'
};
/**
* Platform Types
*/
export const PlatformTypes = {
YOUTUBE: 'youtube',
LINKEDIN: 'linkedin',
REDDIT: 'reddit',
PINTEREST: 'pinterest',
APPLE: 'apple'
};
/**
* Connection Health Status Types
*/
export const ConnectionHealthStatus = {
HEALTHY: 'healthy',
EXPIRED_REFRESHABLE: 'expired_refreshable',
EXPIRED_NO_REFRESH: 'expired_no_refresh',
INVALID_TOKEN: 'invalid_token',
NOT_CONNECTED: 'not_connected',
ERROR: 'error'
};
/**
* Rate Limit Tiers
*/
export const RateLimitTiers = {
STANDARD: 'ona_',
DEVELOPER: 'dev_',
PUBLIC: 'pk_',
ADMIN: 'admin'
};
/**
* API Response Types
*/
export const ResponseTypes = {
SUCCESS: 'success',
ERROR: 'error',
WARNING: 'warning',
INFO: 'info'
};
/**
* Error Codes
*/
export const ErrorCodes = {
// Authentication Errors
INVALID_API_KEY: 'INVALID_API_KEY',
INVALID_JWT: 'INVALID_JWT',
EXPIRED_JWT: 'EXPIRED_JWT',
MISSING_API_KEY: 'MISSING_API_KEY',
MISSING_JWT: 'MISSING_JWT',
INVALID_CREDENTIALS: 'INVALID_CREDENTIALS',
INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',
// User Errors
USER_NOT_FOUND: 'USER_NOT_FOUND',
INVALID_USER_TYPE: 'INVALID_USER_TYPE',
USER_LOOKUP_FAILED: 'USER_LOOKUP_FAILED',
// Platform Errors
PLATFORM_NOT_SUPPORTED: 'PLATFORM_NOT_SUPPORTED',
PLATFORM_DISABLED: 'PLATFORM_DISABLED',
INVALID_PLATFORM_TOKEN: 'INVALID_PLATFORM_TOKEN',
PLATFORM_API_ERROR: 'PLATFORM_API_ERROR',
// Connection Errors
CONNECTION_NOT_FOUND: 'CONNECTION_NOT_FOUND',
CONNECTION_FAILED: 'CONNECTION_FAILED',
CONNECTION_EXPIRED: 'CONNECTION_EXPIRED',
NO_REFRESH_TOKEN: 'NO_REFRESH_TOKEN',
REFRESH_FAILED: 'REFRESH_FAILED',
// Rate Limiting Errors
RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
API_KEY_RATE_LIMIT_EXCEEDED: 'API_KEY_RATE_LIMIT_EXCEEDED',
PLATFORM_RATE_LIMIT_EXCEEDED: 'PLATFORM_RATE_LIMIT_EXCEEDED',
ENDPOINT_RATE_LIMIT_EXCEEDED: 'ENDPOINT_RATE_LIMIT_EXCEEDED',
BURST_RATE_LIMIT_EXCEEDED: 'BURST_RATE_LIMIT_EXCEEDED',
CONCURRENT_REQUESTS_EXCEEDED: 'CONCURRENT_REQUESTS_EXCEEDED',
// Validation Errors
INVALID_REQUEST_DATA: 'INVALID_REQUEST_DATA',
MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
INVALID_FIELD_TYPE: 'INVALID_FIELD_TYPE',
INVALID_FIELD_VALUE: 'INVALID_FIELD_VALUE',
// System Errors
INTERNAL_ERROR: 'INTERNAL_ERROR',
DATABASE_ERROR: 'DATABASE_ERROR',
NETWORK_ERROR: 'NETWORK_ERROR',
TIMEOUT_ERROR: 'TIMEOUT_ERROR',
CONFIGURATION_ERROR: 'CONFIGURATION_ERROR'
};
/**
* Request Validation Schemas
*/
export const ValidationSchemas = {
// YouTube Native Auth Request
youtubeNativeAuth: {
required: ['accessToken', 'userAccountInfo'],
optional: ['refreshToken', 'idToken', 'session'],
fields: {
accessToken: { type: 'string', minLength: 10 },
refreshToken: { type: 'string', minLength: 10 },
idToken: { type: 'string', minLength: 10 },
userAccountInfo: {
type: 'object',
required: ['username'],
fields: {
username: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
channelName: { type: 'string' },
channelId: { type: 'string' }
}
}
}
},
// LinkedIn Native Auth Request
linkedinNativeAuth: {
required: ['accessToken', 'userAccountInfo'],
optional: ['refreshToken', 'idToken', 'session'],
fields: {
accessToken: { type: 'string', minLength: 10 },
refreshToken: { type: 'string', minLength: 10 },
idToken: { type: 'string', minLength: 10 },
userAccountInfo: {
type: 'object',
required: ['username'],
fields: {
username: { type: 'string', minLength: 1 },
email: { type: 'string', format: 'email' },
firstName: { type: 'string' },
lastName: { type: 'string' }
}
}
}
},
// Token Refresh Request
tokenRefresh: {
required: ['username'],
optional: ['platform'],
fields: {
username: { type: 'string', minLength: 1 },
platform: { type: 'string', enum: Object.values(PlatformTypes) }
}
},
// Health Check Request
healthCheck: {
required: [],
optional: ['platforms', 'detailed'],
fields: {
platforms: { type: 'array', items: { type: 'string', enum: Object.values(PlatformTypes) } },
detailed: { type: 'boolean' }
}
},
// Connection Repair Request
connectionRepair: {
required: [],
optional: ['platforms', 'autoRepair'],
fields: {
platforms: { type: 'array', items: { type: 'string', enum: Object.values(PlatformTypes) } },
autoRepair: { type: 'boolean' }
}
}
};
/**
* Response Schemas
*/
export const ResponseSchemas = {
// Standard Success Response
success: {
success: true,
message: 'string',
data: 'object',
timestamp: 'date',
requestId: 'string'
},
// Standard Error Response
error: {
success: false,
error: 'string',
code: 'string',
details: 'object',
guidance: 'string',
timestamp: 'date',
requestId: 'string'
},
// Authentication Response
authenticationResponse: {
success: 'boolean',
message: 'string',
userType: 'string',
connectionData: {
platform: 'string',
userName: 'string',
connectedAt: 'date',
hasRefreshToken: 'boolean',
tokenExpiry: 'date'
},
connectionHealth: {
status: 'string',
message: 'string',
lastChecked: 'date'
},
recommendations: 'array',
requestId: 'string'
},
// Connection Health Response
connectionHealthResponse: {
success: 'boolean',
username: 'string',
userType: 'string',
summary: {
overallStatus: 'string',
overallScore: 'number',
connectedPlatforms: 'number',
healthyPlatforms: 'number',
needsAttention: 'number'
},
platforms: 'object',
recommendations: 'array',
requestId: 'string'
},
// Token Refresh Response
tokenRefreshResponse: {
success: 'boolean',
message: 'string',
refreshed: 'boolean',
newTokenExpiry: 'date',
requestId: 'string'
}
};
/**
* Data Transfer Objects (DTOs)
*/
export class AuthenticationDTO {
constructor(data) {
this.accessToken = data.accessToken;
this.refreshToken = data.refreshToken;
this.idToken = data.idToken;
this.userAccountInfo = data.userAccountInfo;
this.session = data.session;
this.platform = data.platform;
this.timestamp = new Date();
}
validate() {
const errors = [];
if (!this.accessToken) {
errors.push('accessToken is required');
}
if (!this.userAccountInfo || !this.userAccountInfo.username) {
errors.push('userAccountInfo with username is required');
}
return {
isValid: errors.length === 0,
errors: errors
};
}
}
export class ConnectionHealthDTO {
constructor(data) {
this.status = data.status;
this.connected = data.connected;
this.message = data.message;
this.lastChecked = new Date();
this.tokenDetails = data.tokenDetails;
this.recommendations = data.recommendations || [];
this.needsReauth = data.needsReauth;
this.canRefresh = data.canRefresh;
}
isHealthy() {
return this.status === ConnectionHealthStatus.HEALTHY;
}
needsAttention() {
return [
ConnectionHealthStatus.EXPIRED_REFRESHABLE,
ConnectionHealthStatus.EXPIRED_NO_REFRESH,
ConnectionHealthStatus.INVALID_TOKEN,
ConnectionHealthStatus.ERROR
].includes(this.status);
}
}
export class UserConnectionDTO {
constructor(data) {
this.platform = data.platform;
this.accessToken = data.accessToken;
this.refreshToken = data.refreshToken;
this.tokenExpiry = data.tokenExpiry;
this.userName = data.userName;
this.profileId = data.profileId;
this.connectedAt = data.connectedAt;
this.lastValidated = data.lastValidated;
this.hasRefreshToken = !!data.refreshToken;
}
isExpired() {
return this.tokenExpiry && new Date() > new Date(this.tokenExpiry);
}
canRefresh() {
return this.hasRefreshToken && this.refreshToken;
}
}
export class ApiResponseDTO {
constructor(success, data, error = null) {
this.success = success;
this.timestamp = new Date();
this.requestId = Date.now().toString(36) + Math.random().toString(36).substr(2, 9);
if (success) {
this.message = data.message || 'Operation completed successfully';
this.data = data.data || data;
} else {
this.error = error || data.error || 'Operation failed';
this.code = data.code || 'UNKNOWN_ERROR';
this.details = data.details;
this.guidance = data.guidance;
}
}
static success(data, message = 'Operation completed successfully') {
return new ApiResponseDTO(true, { message, data });
}
static error(error, code = 'UNKNOWN_ERROR', details = null, guidance = null) {
return new ApiResponseDTO(false, { error, code, details, guidance });
}
}
/**
* Validation Utilities
*/
export class ValidationUtils {
static validateSchema(data, schema) {
const errors = [];
// Check required fields
if (schema.required) {
for (const field of schema.required) {
if (!data[field]) {
errors.push(`Required field '${field}' is missing`);
}
}
}
// Validate field types and formats
if (schema.fields) {
for (const [fieldName, fieldSchema] of Object.entries(schema.fields)) {
const value = data[fieldName];
if (value !== undefined && value !== null) {
const fieldErrors = this.validateField(fieldName, value, fieldSchema);
errors.push(...fieldErrors);
}
}
}
return {
isValid: errors.length === 0,
errors: errors
};
}
static validateField(fieldName, value, fieldSchema) {
const errors = [];
// Type validation
if (fieldSchema.type) {
const expectedType = fieldSchema.type;
const actualType = Array.isArray(value) ? 'array' : typeof value;
if (actualType !== expectedType) {
errors.push(`Field '${fieldName}' must be of type ${expectedType}, got ${actualType}`);
return errors; // Don't continue validation if type is wrong
}
}
// String validations
if (fieldSchema.type === 'string') {
if (fieldSchema.minLength && value.length < fieldSchema.minLength) {
errors.push(`Field '${fieldName}' must be at least ${fieldSchema.minLength} characters long`);
}
if (fieldSchema.maxLength && value.length > fieldSchema.maxLength) {
errors.push(`Field '${fieldName}' must be at most ${fieldSchema.maxLength} characters long`);
}
if (fieldSchema.format === 'email' && !this.isValidEmail(value)) {
errors.push(`Field '${fieldName}' must be a valid email address`);
}
if (fieldSchema.enum && !fieldSchema.enum.includes(value)) {
errors.push(`Field '${fieldName}' must be one of: ${fieldSchema.enum.join(', ')}`);
}
}
// Number validations
if (fieldSchema.type === 'number') {
if (fieldSchema.min !== undefined && value < fieldSchema.min) {
errors.push(`Field '${fieldName}' must be at least ${fieldSchema.min}`);
}
if (fieldSchema.max !== undefined && value > fieldSchema.max) {
errors.push(`Field '${fieldName}' must be at most ${fieldSchema.max}`);
}
}
// Array validations
if (fieldSchema.type === 'array') {
if (fieldSchema.minItems && value.length < fieldSchema.minItems) {
errors.push(`Field '${fieldName}' must have at least ${fieldSchema.minItems} items`);
}
if (fieldSchema.maxItems && value.length > fieldSchema.maxItems) {
errors.push(`Field '${fieldName}' must have at most ${fieldSchema.maxItems} items`);
}
if (fieldSchema.items) {
value.forEach((item, index) => {
const itemErrors = this.validateField(`${fieldName}[${index}]`, item, fieldSchema.items);
errors.push(...itemErrors);
});
}
}
// Object validations
if (fieldSchema.type === 'object' && fieldSchema.fields) {
const subValidation = this.validateSchema(value, fieldSchema);
errors.push(...subValidation.errors);
}
return errors;
}
static isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
}
/**
* Type Guards
*/
export class TypeGuards {
static isValidPlatform(platform) {
return Object.values(PlatformTypes).includes(platform);
}
static isValidUserType(userType) {
return Object.values(UserTypes).includes(userType);
}
static isValidConnectionStatus(status) {
return Object.values(ConnectionHealthStatus).includes(status);
}
static isValidAuthenticationType(authType) {
return Object.values(AuthenticationTypes).includes(authType);
}
static isValidErrorCode(code) {
return Object.values(ErrorCodes).includes(code);
}
static isValidRateLimitTier(tier) {
return Object.values(RateLimitTiers).includes(tier);
}
}
/**
* Constants
*/
export const SDK_CONSTANTS = {
// Token expiry times (in milliseconds)
TOKEN_EXPIRY: {
YOUTUBE: 3600000, // 1 hour
LINKEDIN: 5184000000, // 60 days
REDDIT: 3600000, // 1 hour
PINTEREST: 3600000, // 1 hour
APPLE: 86400000 // 24 hours
},
// Rate limit windows
RATE_LIMIT_WINDOWS: {
MINUTE: 60 * 1000,
HOUR: 60 * 60 * 1000,
DAY: 24 * 60 * 60 * 1000
},
// Health check intervals
HEALTH_CHECK_INTERVALS: {
FAST: 30000, // 30 seconds
NORMAL: 300000, // 5 minutes
SLOW: 3600000 // 1 hour
},
// Request timeouts
REQUEST_TIMEOUTS: {
FAST: 5000, // 5 seconds
NORMAL: 30000, // 30 seconds
SLOW: 60000 // 1 minute
},
// Pagination defaults
PAGINATION: {
DEFAULT_LIMIT: 20,
MAX_LIMIT: 100,
DEFAULT_OFFSET: 0
}
};
export default {
AuthenticationTypes,
UserTypes,
PlatformTypes,
ConnectionHealthStatus,
RateLimitTiers,
ResponseTypes,
ErrorCodes,
ValidationSchemas,
ResponseSchemas,
AuthenticationDTO,
ConnectionHealthDTO,
UserConnectionDTO,
ApiResponseDTO,
ValidationUtils,
TypeGuards,
SDK_CONSTANTS
};