#import @interface XuqmBundleModule : NSObject @end @implementation XuqmBundleModule RCT_EXPORT_MODULE() - (NSString *)bundleDir { NSString *appSupport = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) firstObject]; NSString *dir = [appSupport stringByAppendingPathComponent:@"rn-bundles"]; [[NSFileManager defaultManager] createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:nil]; return dir; } - (NSString *)bundlePathForModule:(NSString *)moduleId { NSString *filename = [NSString stringWithFormat:@"%@.ios.bundle", moduleId]; return [[self bundleDir] stringByAppendingPathComponent:filename]; } // ── Bundle 文件操作 ────────────────────────────────────────────────────────── RCT_EXPORT_METHOD(bundleExists:(NSString *)moduleId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSString *path = [self bundlePathForModule:moduleId]; BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path]; resolve(@(exists)); } RCT_EXPORT_METHOD(readBundle:(NSString *)moduleId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSString *path = [self bundlePathForModule:moduleId]; if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { reject(@"BUNDLE_NOT_FOUND", [NSString stringWithFormat:@"Bundle not found: %@", moduleId], nil); return; } NSError *error = nil; NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; if (error) { reject(@"BUNDLE_READ_ERROR", error.localizedDescription, error); return; } resolve(content); } RCT_EXPORT_METHOD(writeBundle:(NSString *)moduleId source:(NSString *)source md5:(NSString *)md5 resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSString *path = [self bundlePathForModule:moduleId]; NSError *error = nil; [source writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (error) { reject(@"BUNDLE_WRITE_ERROR", error.localizedDescription, error); return; } resolve(@(YES)); } RCT_EXPORT_METHOD(deleteBundle:(NSString *)moduleId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSString *path = [self bundlePathForModule:moduleId]; if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { NSError *error = nil; [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; if (error) { reject(@"BUNDLE_DELETE_ERROR", error.localizedDescription, error); return; } } resolve(@(YES)); } RCT_EXPORT_METHOD(getBundlePath:(NSString *)moduleId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { resolve([self bundlePathForModule:moduleId]); } // ── Manifest 操作 ──────────────────────────────────────────────────────────── RCT_EXPORT_METHOD(getManifest:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSString *path = [[self bundleDir] stringByAppendingPathComponent:@"manifest.json"]; if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { resolve(@"{}"); return; } NSError *error = nil; NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error]; if (error) { reject(@"MANIFEST_READ_ERROR", error.localizedDescription, error); return; } resolve(content); } RCT_EXPORT_METHOD(writeManifest:(NSString *)manifestJson resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSString *path = [[self bundleDir] stringByAppendingPathComponent:@"manifest.json"]; NSError *error = nil; [manifestJson writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (error) { reject(@"MANIFEST_WRITE_ERROR", error.localizedDescription, error); return; } resolve(@(YES)); } @end