@iota-big3/sdk-gateway
Version:
Universal API Gateway with protocol translation, intelligent routing, rate limiting, health checking, and caching
313 lines • 9.94 kB
JavaScript
;
/**
* Migration Helpers for Enhanced Types
* Following Phase 2g: Backward-compatible tools to help packages adopt new types incrementally
* Focused on Education domain patterns
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.migrationHelpers = void 0;
exports.wrapLegacyEventHandler = wrapLegacyEventHandler;
exports.wrapLegacyCallback = wrapLegacyCallback;
exports.convertExpressMiddleware = convertExpressMiddleware;
exports.migrateToEducationUser = migrateToEducationUser;
exports.createEducationContext = createEducationContext;
exports.promiseToResult = promiseToResult;
exports.callbackToResult = callbackToResult;
exports.createTypedEventWrapper = createTypedEventWrapper;
exports.migrateConfig = migrateConfig;
exports.migrateMetadata = migrateMetadata;
// ============================================
// Type Migration Utilities
// ============================================
/**
* Wrap legacy event handler to use new typed pattern
* Helps migrate from: (...args: any[]) => void
* To: EventHandler<TEvent>
*/
function wrapLegacyEventHandler(legacyHandler) {
return (event) => {
// If event is already structured, pass it directly
if (typeof event === 'object' && event !== null) {
return legacyHandler(event);
}
// Otherwise, wrap primitive values
return legacyHandler({ value: event });
};
}
/**
* Wrap legacy callback to use new typed pattern
* Helps migrate from: (err: any, result?: any) => void
* To: Callback<TResult, TError>
*/
function wrapLegacyCallback(legacyCallback) {
return (error, result) => {
legacyCallback(error, result);
};
}
/**
* Convert legacy middleware to typed middleware
* Helps migrate Express middleware to typed patterns
*/
function convertExpressMiddleware(middleware) {
return async (context, next) => {
const { req, res } = context;
return new Promise((resolve, reject) => {
middleware(req, res, (error) => {
if (error) {
reject(error);
}
else {
next().then(resolve).catch(reject);
}
});
});
};
}
// ============================================
// Education-Specific Migration Helpers
// ============================================
/**
* Migrate generic AuthUser to EducationUser
* Adds education-specific fields with safe defaults
*/
function migrateToEducationUser(user, educationData) {
// Infer user type from existing data if not provided
let userType = 'student';
if (educationData?.userType) {
userType = educationData.userType;
}
else if (user.roles) {
// Infer from roles
if (user.roles.includes('teacher') || user.roles.includes('instructor')) {
userType = 'teacher';
}
else if (user.roles.includes('admin') || user.roles.includes('administrator')) {
userType = 'administrator';
}
else if (user.roles.includes('parent') || user.roles.includes('guardian')) {
userType = 'parent';
}
}
return {
...user,
userType,
schoolId: educationData?.schoolId,
districtId: educationData?.districtId,
gradeLevel: educationData?.gradeLevel,
subjects: educationData?.subjects
};
}
/**
* Create education context from request
* Helps build proper ValidationContext for education operations
*/
function createEducationContext(req, action, resource) {
const user = req.user;
const educationUser = user && isLikelyEducationUser(user)
? user
: undefined;
return {
userId: user?.id,
userRole: educationUser?.userType || user?.roles?.[0],
action,
resource,
// Education-specific context
studentId: req.params?.studentId,
parentOfStudent: req.query?.parentOfStudent,
// Compliance flags
studentConsent: req.headers['x-ferpa-consent'] === 'true',
parentalConsent: req.headers['x-parental-consent'] === 'true',
// Audit trail
auditingEnabled: true,
encryptionEnabled: true,
metadata: {
requestId: req.correlationId,
timestamp: new Date().toISOString(),
userAgent: req.headers['user-agent']
}
};
}
/**
* Check if AuthUser might be EducationUser
*/
function isLikelyEducationUser(user) {
const educationRoles = ['student', 'teacher', 'parent', 'administrator', 'instructor', 'faculty'];
return user.roles?.some(role => educationRoles.includes(role.toLowerCase())) || false;
}
// ============================================
// Result Type Migration
// ============================================
/**
* Convert Promise to Result pattern
* Helps migrate from: Promise<T>
* To: Promise<Result<T, E>>
*/
async function promiseToResult(promise) {
try {
const value = await promise;
return { success: true, value };
}
catch (error) {
return { success: false, error: error };
}
}
/**
* Convert callback-based function to Result pattern
*/
function callbackToResult(fn) {
return (...args) => {
return new Promise((resolve) => {
const callback = (err, result) => {
if (err) {
resolve({ success: false, error: err });
}
else {
resolve({ success: true, value: result });
}
};
fn(...args, callback);
});
};
}
// ============================================
// Event System Migration
// ============================================
/**
* Convert legacy event emitter to typed event emitter
*/
function createTypedEventWrapper(legacyEmitter) {
return {
on(event, handler) {
legacyEmitter.on(event, handler);
return this;
},
off(event, handler) {
legacyEmitter.off(event, handler);
return this;
},
emit(event, ...args) {
return legacyEmitter.emit(event, ...args);
},
once(event, handler) {
legacyEmitter.once(event, handler);
return this;
}
};
}
// ============================================
// Configuration Migration
// ============================================
/**
* Migrate loose config object to typed ConfigObject
*/
function migrateConfig(config, defaults, validator) {
// Merge with defaults
const merged = { ...defaults };
// Type-safe property assignment
for (const key in defaults) {
if (key in config) {
const defaultValue = defaults[key];
const configValue = config[key];
// Type checking based on default value type
if (typeof defaultValue === typeof configValue) {
merged[key] = configValue;
}
else if (defaultValue === null || defaultValue === undefined) {
// Allow any type if default is null/undefined
merged[key] = configValue;
}
else {
// Type mismatch: expected type based on default value
// In production, this should be logged via sdk-observability
}
}
}
// Run validation if provided
if (validator) {
const errors = validator(merged);
if (errors.length > 0) {
// Validation warnings detected
// In production, these should be logged via sdk-observability
// Errors are returned for the caller to handle appropriately
}
}
return merged;
}
// ============================================
// Metadata Migration
// ============================================
/**
* Convert loose metadata to typed Metadata
*/
function migrateMetadata(metadata, knownKeys) {
const result = {};
// Add known keys
for (const key in knownKeys) {
if (isJsonValue(knownKeys[key])) {
result[key] = knownKeys[key];
}
}
// Add unknown keys with JSON-safe values
if (metadata && typeof metadata === 'object') {
const metadataObj = metadata;
for (const key in metadataObj) {
const value = metadataObj[key];
if (isJsonValue(value)) {
result[key] = value;
}
else {
// Convert non-JSON values
result[key] = String(value);
}
}
}
return result;
}
/**
* Check if value is JSON-serializable
*/
function isJsonValue(value) {
if (value === null ||
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean') {
return true;
}
if (Array.isArray(value)) {
return value.every(isJsonValue);
}
if (typeof value === 'object' && value !== null) {
// Check for non-JSON types
if (value instanceof Date ||
value instanceof RegExp ||
value instanceof Function ||
value instanceof Map ||
value instanceof Set) {
return false;
}
// Check all properties
return Object.values(value).every(isJsonValue);
}
return false;
}
// ============================================
// Export Migration Kit
// ============================================
exports.migrationHelpers = {
// Function migrations
wrapLegacyEventHandler,
wrapLegacyCallback,
convertExpressMiddleware,
// Education migrations
migrateToEducationUser,
createEducationContext,
// Result pattern migrations
promiseToResult,
callbackToResult,
// Event system migrations
createTypedEventWrapper,
// Configuration migrations
migrateConfig,
migrateMetadata
};
//# sourceMappingURL=migration-helpers.js.map