Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion android/src/main/java/com/prisma/PrismaModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,17 @@ public void createDir(File dir) throws IOException
public void install() {
ReactApplicationContext context = this.getReactApplicationContext();
long jsContextPointer = context.getJavaScriptContextHolder().get();
CallInvokerHolderImpl jsCallInvokerHolder = (CallInvokerHolderImpl)context.getCatalystInstance().getJSCallInvokerHolder();
if (jsContextPointer == 0) {
throw new RuntimeException("JSI runtime pointer is null. Make sure Hermes is enabled and the runtime is initialized before calling install().");
}
CallInvokerHolderImpl jsCallInvokerHolder;
if (context.getJSCallInvokerHolder() != null) {
jsCallInvokerHolder = (CallInvokerHolderImpl) context.getJSCallInvokerHolder();
} else if (context.getCatalystInstance() != null) {
jsCallInvokerHolder = (CallInvokerHolderImpl) context.getCatalystInstance().getJSCallInvokerHolder();
} else {
throw new RuntimeException("JSCallInvokerHolder is not available yet.");
}
String dbPath = context.getDatabasePath("defaultDatabase").getAbsolutePath().replace("defaultDatabase", "");
String migrationsPath;
try {
Expand Down
3 changes: 1 addition & 2 deletions copy-migrations.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ echo "Copying prisma migration files..."
MIGRATIONS_TARGET=${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}

rm -rf "$MIGRATIONS_TARGET/migrations"
mkdir "$MIGRATIONS_TARGET/migrations"
cp -r ${SRCROOT}/../migrations ${MIGRATIONS_TARGET}
cp -r ${SRCROOT}/../prisma/migrations "${MIGRATIONS_TARGET}/migrations"

echo "migration files copied ✅"
7 changes: 6 additions & 1 deletion cpp/QueryEngineHostObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
#ifndef query_engine_host_object_h
#define query_engine_host_object_h

#include "query_engine.h"
#include <TargetConditionals.h>
#if TARGET_OS_SIMULATOR
#include "../engines/ios/QueryEngine.xcframework/ios-arm64_x86_64-simulator/Headers/query_engine.h"
#else
#include "../engines/ios/QueryEngine.xcframework/ios-arm64/Headers/query_engine.h"
#endif
#include <jsi/jsi.h>
#include <memory>
#include <string>
Expand Down
115 changes: 91 additions & 24 deletions ios/Prisma.mm
Original file line number Diff line number Diff line change
@@ -1,52 +1,119 @@
#import "Prisma.h"
#import <jsi/jsi.h>
#import <React/RCTBridge.h>
#import <React/RCTBridge+Private.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <dispatch/dispatch.h>
#import <ReactCommon/RCTTurboModule.h>
#import <UIKit/UIKit.h>
#import <iostream>

#ifdef RCT_NEW_ARCH_ENABLED
#import "RNPrismaSpecJSI.h"
#endif

// Forward declare runtimeExecutor to silence selector warnings on older headers
@interface RCTBridge (RuntimeExecutorForwardDecl)
- (facebook::react::RuntimeExecutor)runtimeExecutor;
@end

static NSString *PrismaLibraryPath() {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, true);
return [paths objectAtIndex:0];
}

static NSString *PrismaMigrationsPath() {
auto bundleURL = NSBundle.mainBundle.bundleURL;
auto migrations_path_absolute = [NSString stringWithFormat:@"%@%@", bundleURL.absoluteString, @"migrations"];
return [migrations_path_absolute stringByReplacingOccurrencesOfString:@"file://" withString:@""];
}

static inline void InstallInRuntime(facebook::jsi::Runtime &runtime,
std::shared_ptr<facebook::react::CallInvoker> callInvoker) {
NSString *libraryPath = PrismaLibraryPath();
NSString *migrationsPath = PrismaMigrationsPath();
prisma::install_cxx(runtime, callInvoker, [libraryPath UTF8String], [migrationsPath UTF8String]);
}

static RCTBridge *ResolveBridge(id<RCTBridgeModule> module) {
RCTBridge *bridge = nil;
if ([module respondsToSelector:@selector(bridge)]) {
bridge = ((id<RCTBridgeModule>)module).bridge;
}
if (bridge == nil) {
bridge = [RCTBridge currentBridge];
}
return bridge;
}

@implementation Prisma

@synthesize bridge=_bridge;

RCT_EXPORT_MODULE()

// Old-arch sync install for classic bridge
#if !RCT_NEW_ARCH_ENABLED
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
{
RCTCxxBridge *cxxBridge = (RCTCxxBridge *)_bridge;
if (cxxBridge == nil) {
return @false;
#if DEBUG
std::cout << "▲ NSHomeDirectory:\n" << [NSHomeDirectory() UTF8String] << std::endl;
std::cout << "▲ Library Path:\n" << [PrismaLibraryPath() UTF8String] << std::endl;
std::cout << "▲ Migrations Path:\n" << [PrismaMigrationsPath() UTF8String] << std::endl;
#endif

BOOL ok = NO;
auto okPtr = &ok;
RCTBridge *bridge = ResolveBridge(self);

// Try new-arch path first if runtimeExecutor is available
if (bridge && [bridge respondsToSelector:@selector(runtimeExecutor)]) {
facebook::react::RuntimeExecutor executor = RCTRuntimeExecutorFromBridge(bridge);
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
executor([&](facebook::jsi::Runtime &runtime) {
InstallInRuntime(runtime, bridge.jsCallInvoker);
*okPtr = YES;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return @(ok);
}

auto jsiRuntime = (facebook::jsi::Runtime *)cxxBridge.runtime;
if (jsiRuntime == nil) {

// Fallback to old-arch bridge access
RCTBridge *legacyBridge = _bridge ?: bridge;
RCTCxxBridge *cxxBridge = (RCTCxxBridge *)legacyBridge;
if (cxxBridge == nil || cxxBridge.runtime == nil) {
NSLog(@"[Prisma] no runtime available to install cxx");
return @false;
}

auto jsiRuntime = (facebook::jsi::Runtime *)cxxBridge.runtime;
auto &runtime = *jsiRuntime;
auto callInvoker = _bridge.jsCallInvoker;

// get migrations folder
auto bundleURL = NSBundle.mainBundle.bundleURL;
auto migrations_path_absolute = [NSString stringWithFormat:@"%@%@", bundleURL.absoluteString, @"migrations"];
auto migrations_path = [migrations_path_absolute stringByReplacingOccurrencesOfString:@"file://" withString:@""];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, true);
NSString *libraryPath = [paths objectAtIndex:0];

#if DEBUG
std::cout << "▲ NSHomeDirectory:\n" << [NSHomeDirectory() UTF8String] << std::endl;
std::cout << "▲ Library Path:\n" << [libraryPath UTF8String] << std::endl;
std::cout << "▲ Migrations Path:\n" << [migrations_path UTF8String] << std::endl;
#endif
auto callInvoker = _bridge ? _bridge.jsCallInvoker : legacyBridge.jsCallInvoker;

prisma::install_cxx(runtime, callInvoker, [libraryPath UTF8String], [migrations_path UTF8String]);
return nil;
InstallInRuntime(runtime, callInvoker);
return @true;
}
#else
// Required by NativePrismaSpec protocol in new-arch; TurboModule path uses C++ spec below.
- (void)install {}
#endif

#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativePrismaSpecJSI>(params);
class PrismaCxxTurboModule final : public facebook::react::NativePrismaCxxSpec<PrismaCxxTurboModule> {
public:
explicit PrismaCxxTurboModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker)
: NativePrismaCxxSpec(std::move(jsInvoker)) {}

void install(facebook::jsi::Runtime &rt) {
InstallInRuntime(rt, this->jsInvoker_);
}
};

return std::make_shared<PrismaCxxTurboModule>(params.jsInvoker);
}
#endif

Expand Down