@bennyblader/ddk-rn 0.2.3 ā 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +1 -0
- package/cpp/bennyblader-ddk-rn.cpp +16 -0
- package/cpp/bennyblader-ddk-rn.h +15 -0
- package/ddk-ffi/Cargo.lock +1096 -0
- package/ddk-ffi/Cargo.toml +31 -0
- package/ddk-ffi/build.rs +3 -0
- package/ddk-ffi/rust-toolchain.toml +10 -0
- package/ddk-ffi/scratchpad.txt +243 -0
- package/ddk-ffi/src/ddk_ffi.udl +230 -0
- package/ddk-ffi/src/lib.rs +1093 -0
- package/ddk-ffi/src/uniffi-bindgen.rs +3 -0
- package/ddk-ffi/uniffi.toml +18 -0
- package/package.json +6 -5
- package/scripts/postinstall.js +67 -59
- package/scripts/prepare-rust-src.js +51 -0
- package/src/NativeDdkRn.ts +10 -0
- package/src/index.tsx +41 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# uniffi.toml
|
|
2
|
+
[bindings.typescript]
|
|
3
|
+
logLevel = "verbose"
|
|
4
|
+
|
|
5
|
+
[bindings.cpp]
|
|
6
|
+
|
|
7
|
+
[turbo_module]
|
|
8
|
+
# The name of your Turbo Module as it appears in React Native
|
|
9
|
+
name = "Ddk"
|
|
10
|
+
# The iOS framework name
|
|
11
|
+
ios_framework = "Ddk"
|
|
12
|
+
# The Android package name
|
|
13
|
+
android_package = "dev.bennyblader.ddk"
|
|
14
|
+
|
|
15
|
+
[namespace.ddk_ffi]
|
|
16
|
+
# Configuration specific to your ddk_ffi namespace
|
|
17
|
+
# This tells the generator how to handle this particular namespace
|
|
18
|
+
js_module_name = "Ddk"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bennyblader/ddk-rn",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "dlcdevkit bindings for react-native",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/commonjs/index.js",
|
|
@@ -19,11 +19,10 @@
|
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
|
-
"src
|
|
23
|
-
"
|
|
24
|
-
"cpp/ddk_ffi.hpp",
|
|
25
|
-
"cpp/ddk_ffi.cpp",
|
|
22
|
+
"src",
|
|
23
|
+
"cpp",
|
|
26
24
|
"lib",
|
|
25
|
+
"ddk-ffi",
|
|
27
26
|
"android/build.gradle",
|
|
28
27
|
"android/CMakeLists.txt",
|
|
29
28
|
"android/cpp-adapter.cpp",
|
|
@@ -35,10 +34,12 @@
|
|
|
35
34
|
"ios/DdkRn.h",
|
|
36
35
|
"ios/DdkRn.mm",
|
|
37
36
|
"scripts/postinstall.js",
|
|
37
|
+
"scripts/prepare-rust-src.js",
|
|
38
38
|
"ubrn.config.yaml",
|
|
39
39
|
"*.podspec",
|
|
40
40
|
"react-native.config.js",
|
|
41
41
|
"README.md",
|
|
42
|
+
"!ddk-ffi/target",
|
|
42
43
|
"!**/*.a",
|
|
43
44
|
"!**/*.so",
|
|
44
45
|
"!**/*.dylib",
|
package/scripts/postinstall.js
CHANGED
|
@@ -5,8 +5,9 @@ const path = require('path');
|
|
|
5
5
|
const { execSync } = require('child_process');
|
|
6
6
|
|
|
7
7
|
const packageRoot = path.join(__dirname, '..');
|
|
8
|
+
const ddkFfiRoot = path.join(packageRoot, 'ddk-ffi');
|
|
8
9
|
|
|
9
|
-
console.log('š¦ DDK-RN Post-install:
|
|
10
|
+
console.log('š¦ DDK-RN Post-install: Building native libraries...');
|
|
10
11
|
|
|
11
12
|
// Check if uniffi-bindgen-react-native is available (prefer npx)
|
|
12
13
|
function hasUniffiBingen() {
|
|
@@ -40,26 +41,6 @@ function ensureDir(dir) {
|
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
// Generate turbo module specifications from existing JSI bindings
|
|
44
|
-
function generateTurboModule() {
|
|
45
|
-
console.log('\nā” Generating turbo module from existing bindings...');
|
|
46
|
-
|
|
47
|
-
const configFile = path.join(packageRoot, 'ubrn.config.yaml');
|
|
48
|
-
const uniffiCmd = getUniffiCommand();
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const cmd = `${uniffiCmd} generate jsi turbo-module ddk_ffi --config "${configFile}" --native-bindings`;
|
|
52
|
-
console.log(`Running: ${cmd}`);
|
|
53
|
-
execSync(cmd, {
|
|
54
|
-
stdio: 'inherit',
|
|
55
|
-
cwd: packageRoot
|
|
56
|
-
});
|
|
57
|
-
console.log('ā
Turbo module generated');
|
|
58
|
-
} catch (error) {
|
|
59
|
-
throw new Error(`Failed to generate turbo module: ${error.message}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
44
|
// Build iOS libraries and create XCFramework
|
|
64
45
|
function buildIOS() {
|
|
65
46
|
const platform = process.platform;
|
|
@@ -72,6 +53,9 @@ function buildIOS() {
|
|
|
72
53
|
console.log('\nš Building iOS libraries...');
|
|
73
54
|
const uniffiCmd = getUniffiCommand();
|
|
74
55
|
|
|
56
|
+
// Update ubrn.config.yaml to point to the included Rust source
|
|
57
|
+
updateConfigFile();
|
|
58
|
+
|
|
75
59
|
try {
|
|
76
60
|
const cmd = `${uniffiCmd} build ios --and-generate`;
|
|
77
61
|
console.log(`Running: ${cmd}`);
|
|
@@ -98,6 +82,9 @@ function buildAndroid() {
|
|
|
98
82
|
|
|
99
83
|
const uniffiCmd = getUniffiCommand();
|
|
100
84
|
|
|
85
|
+
// Update ubrn.config.yaml to point to the included Rust source
|
|
86
|
+
updateConfigFile();
|
|
87
|
+
|
|
101
88
|
try {
|
|
102
89
|
const cmd = `${uniffiCmd} build android --and-generate`;
|
|
103
90
|
console.log(`Running: ${cmd}`);
|
|
@@ -112,7 +99,26 @@ function buildAndroid() {
|
|
|
112
99
|
}
|
|
113
100
|
}
|
|
114
101
|
|
|
115
|
-
//
|
|
102
|
+
// Update the ubrn.config.yaml to use the local Rust source
|
|
103
|
+
function updateConfigFile() {
|
|
104
|
+
const configPath = path.join(packageRoot, 'ubrn.config.yaml');
|
|
105
|
+
|
|
106
|
+
if (fs.existsSync(configPath)) {
|
|
107
|
+
let config = fs.readFileSync(configPath, 'utf8');
|
|
108
|
+
|
|
109
|
+
// Update the Rust directory to point to the included ddk-ffi
|
|
110
|
+
if (!config.includes('directory: ddk-ffi')) {
|
|
111
|
+
config = config.replace(
|
|
112
|
+
/rust:\s*\n\s*directory:\s*[^\n]+/,
|
|
113
|
+
'rust:\n directory: ddk-ffi'
|
|
114
|
+
);
|
|
115
|
+
fs.writeFileSync(configPath, config);
|
|
116
|
+
console.log('š Updated config to use included Rust source');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Fix the C++ include path issue if needed
|
|
116
122
|
function fixCppIncludePath() {
|
|
117
123
|
const cppFile = path.join(packageRoot, 'cpp', 'bennyblader-ddk-rn.cpp');
|
|
118
124
|
if (fs.existsSync(cppFile)) {
|
|
@@ -129,38 +135,29 @@ function fixCppIncludePath() {
|
|
|
129
135
|
function verifyAllFiles() {
|
|
130
136
|
console.log('\nš Verifying installation...');
|
|
131
137
|
|
|
132
|
-
const
|
|
138
|
+
const requiredFiles = [
|
|
139
|
+
// Core JSI bindings (shipped with package)
|
|
133
140
|
'src/ddk_ffi.ts',
|
|
134
141
|
'src/ddk_ffi-ffi.ts',
|
|
135
142
|
'cpp/ddk_ffi.hpp',
|
|
136
|
-
'cpp/ddk_ffi.cpp'
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const generatedFiles = [
|
|
143
|
+
'cpp/ddk_ffi.cpp',
|
|
144
|
+
// Generated turbo module files (shipped with package)
|
|
140
145
|
'src/NativeDdkRn.ts',
|
|
141
146
|
'src/index.tsx',
|
|
142
147
|
'cpp/bennyblader-ddk-rn.cpp',
|
|
143
|
-
'cpp/bennyblader-ddk-rn.h'
|
|
148
|
+
'cpp/bennyblader-ddk-rn.h',
|
|
149
|
+
// Rust source (shipped with package)
|
|
150
|
+
'ddk-ffi/Cargo.toml',
|
|
151
|
+
'ddk-ffi/src/lib.rs',
|
|
152
|
+
'ddk-ffi/src/ddk_ffi.udl'
|
|
144
153
|
];
|
|
145
154
|
|
|
146
155
|
const platform = process.platform;
|
|
147
156
|
let allFilesPresent = true;
|
|
148
157
|
|
|
149
|
-
// Check
|
|
150
|
-
console.log('š Checking
|
|
151
|
-
for (const file of
|
|
152
|
-
const filePath = path.join(packageRoot, file);
|
|
153
|
-
if (fs.existsSync(filePath)) {
|
|
154
|
-
console.log(` ā
${file}`);
|
|
155
|
-
} else {
|
|
156
|
-
console.error(` ā Missing: ${file}`);
|
|
157
|
-
allFilesPresent = false;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Check generated files (created by postinstall)
|
|
162
|
-
console.log('š Checking generated files...');
|
|
163
|
-
for (const file of generatedFiles) {
|
|
158
|
+
// Check required files
|
|
159
|
+
console.log('š Checking required files...');
|
|
160
|
+
for (const file of requiredFiles) {
|
|
164
161
|
const filePath = path.join(packageRoot, file);
|
|
165
162
|
if (fs.existsSync(filePath)) {
|
|
166
163
|
console.log(` ā
${file}`);
|
|
@@ -170,18 +167,15 @@ function verifyAllFiles() {
|
|
|
170
167
|
}
|
|
171
168
|
}
|
|
172
169
|
|
|
173
|
-
// Check platform-specific files
|
|
170
|
+
// Check platform-specific files (generated during postinstall)
|
|
174
171
|
if (platform === 'darwin') {
|
|
175
172
|
console.log('š Checking iOS framework...');
|
|
176
173
|
const iosFramework = path.join(packageRoot, 'ios', 'DdkRn.xcframework', 'Info.plist');
|
|
177
174
|
if (fs.existsSync(iosFramework)) {
|
|
178
175
|
console.log(` ā
ios/DdkRn.xcframework`);
|
|
179
176
|
} else {
|
|
180
|
-
console.
|
|
181
|
-
allFilesPresent = false;
|
|
177
|
+
console.log(` ā ļø iOS framework not built yet (will be built now)`);
|
|
182
178
|
}
|
|
183
|
-
} else {
|
|
184
|
-
console.log('š Skipping iOS framework check (not on macOS)');
|
|
185
179
|
}
|
|
186
180
|
|
|
187
181
|
console.log('š Checking Android libraries...');
|
|
@@ -196,15 +190,12 @@ function verifyAllFiles() {
|
|
|
196
190
|
for (const lib of androidLibs) {
|
|
197
191
|
const libPath = path.join(packageRoot, lib);
|
|
198
192
|
if (fs.existsSync(libPath)) {
|
|
199
|
-
console.log(` ā
${lib}`);
|
|
200
193
|
androidLibsPresent++;
|
|
201
|
-
} else {
|
|
202
|
-
console.log(` ā ļø Missing: ${lib}`);
|
|
203
194
|
}
|
|
204
195
|
}
|
|
205
196
|
|
|
206
197
|
if (androidLibsPresent === 0) {
|
|
207
|
-
console.log(' ā ļø
|
|
198
|
+
console.log(' ā ļø Android libraries not built yet (may be due to missing NDK)');
|
|
208
199
|
} else {
|
|
209
200
|
console.log(` ā
Found ${androidLibsPresent}/${androidLibs.length} Android libraries`);
|
|
210
201
|
}
|
|
@@ -214,9 +205,9 @@ function verifyAllFiles() {
|
|
|
214
205
|
|
|
215
206
|
async function main() {
|
|
216
207
|
// Skip in CI unless explicitly requested
|
|
217
|
-
if (process.env.CI && !process.env.
|
|
218
|
-
console.log('ā ļø Skipping
|
|
219
|
-
console.log(' Set
|
|
208
|
+
if (process.env.CI && !process.env.BUILD_NATIVE_LIBS) {
|
|
209
|
+
console.log('ā ļø Skipping native library builds in CI environment.');
|
|
210
|
+
console.log(' Set BUILD_NATIVE_LIBS=1 to force builds in CI.');
|
|
220
211
|
process.exit(0);
|
|
221
212
|
}
|
|
222
213
|
|
|
@@ -228,12 +219,27 @@ async function main() {
|
|
|
228
219
|
process.exit(1);
|
|
229
220
|
}
|
|
230
221
|
|
|
222
|
+
// Check if Rust source is included
|
|
223
|
+
if (!fs.existsSync(ddkFfiRoot)) {
|
|
224
|
+
console.error('ā Rust source not found in package!');
|
|
225
|
+
console.error(` Expected at: ${ddkFfiRoot}`);
|
|
226
|
+
console.error(' This indicates a problem with the NPM package.');
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
|
|
231
230
|
// Verify source files are present (should be included in NPM package)
|
|
232
231
|
const sourceFiles = [
|
|
233
232
|
'src/ddk_ffi.ts',
|
|
234
233
|
'src/ddk_ffi-ffi.ts',
|
|
234
|
+
'src/NativeDdkRn.ts',
|
|
235
|
+
'src/index.tsx',
|
|
235
236
|
'cpp/ddk_ffi.hpp',
|
|
236
|
-
'cpp/ddk_ffi.cpp'
|
|
237
|
+
'cpp/ddk_ffi.cpp',
|
|
238
|
+
'cpp/bennyblader-ddk-rn.cpp',
|
|
239
|
+
'cpp/bennyblader-ddk-rn.h',
|
|
240
|
+
'ddk-ffi/Cargo.toml',
|
|
241
|
+
'ddk-ffi/src/lib.rs',
|
|
242
|
+
'ddk-ffi/src/ddk_ffi.udl'
|
|
237
243
|
];
|
|
238
244
|
|
|
239
245
|
console.log('š Checking source files...');
|
|
@@ -248,9 +254,10 @@ async function main() {
|
|
|
248
254
|
console.log('ā
All source files present');
|
|
249
255
|
|
|
250
256
|
try {
|
|
251
|
-
//
|
|
252
|
-
generateTurboModule();
|
|
257
|
+
// Fix include path if needed
|
|
253
258
|
fixCppIncludePath();
|
|
259
|
+
|
|
260
|
+
// Build native libraries only (turbo module already generated)
|
|
254
261
|
buildIOS();
|
|
255
262
|
buildAndroid();
|
|
256
263
|
|
|
@@ -263,7 +270,7 @@ async function main() {
|
|
|
263
270
|
process.exit(1);
|
|
264
271
|
}
|
|
265
272
|
|
|
266
|
-
console.log('\nā
|
|
273
|
+
console.log('\nā
Installation completed successfully!');
|
|
267
274
|
console.log('š DDK-RN is ready to use!\n');
|
|
268
275
|
|
|
269
276
|
} catch (error) {
|
|
@@ -273,6 +280,7 @@ async function main() {
|
|
|
273
280
|
console.error(' - Missing uniffi-bindgen-react-native (install globally)');
|
|
274
281
|
console.error(' - Missing Android NDK (for Android builds)');
|
|
275
282
|
console.error(' - Missing Xcode/iOS toolchain (for iOS builds on macOS)');
|
|
283
|
+
console.error(' - Missing Rust toolchain');
|
|
276
284
|
console.error('');
|
|
277
285
|
console.error('Report issues at: https://github.com/bennyhodl/ddk-ffi/issues');
|
|
278
286
|
process.exit(1);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
const ddkRnRoot = path.join(__dirname, '..');
|
|
8
|
+
const projectRoot = path.join(ddkRnRoot, '..');
|
|
9
|
+
const ddkFfiSource = path.join(projectRoot, 'ddk-ffi');
|
|
10
|
+
const ddkFfiDest = path.join(ddkRnRoot, 'ddk-ffi');
|
|
11
|
+
|
|
12
|
+
console.log('š¦ Preparing Rust source for npm package...');
|
|
13
|
+
|
|
14
|
+
function copyDirectory(src, dest) {
|
|
15
|
+
// Remove existing destination if it exists
|
|
16
|
+
if (fs.existsSync(dest)) {
|
|
17
|
+
console.log(`šļø Removing existing ${path.basename(dest)}...`);
|
|
18
|
+
execSync(`rm -rf "${dest}"`, { stdio: 'inherit' });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Create destination directory
|
|
22
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
23
|
+
|
|
24
|
+
// Copy all files except target directory
|
|
25
|
+
console.log(`š Copying ${path.basename(src)} to ${path.basename(dest)}...`);
|
|
26
|
+
execSync(`rsync -av --exclude=target/ --exclude=.git/ "${src}/" "${dest}/"`, {
|
|
27
|
+
stdio: 'inherit'
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function main() {
|
|
32
|
+
try {
|
|
33
|
+
// Check if source exists
|
|
34
|
+
if (!fs.existsSync(ddkFfiSource)) {
|
|
35
|
+
console.error(`ā Source directory not found: ${ddkFfiSource}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Copy the Rust source
|
|
40
|
+
copyDirectory(ddkFfiSource, ddkFfiDest);
|
|
41
|
+
|
|
42
|
+
console.log('ā
Rust source prepared for npm package');
|
|
43
|
+
console.log(`š Location: ${ddkFfiDest}`);
|
|
44
|
+
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('ā Failed to prepare Rust source:', error.message);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
main();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Generated by uniffi-bindgen-react-native
|
|
2
|
+
import type { TurboModule } from 'react-native';
|
|
3
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
4
|
+
|
|
5
|
+
export interface Spec extends TurboModule {
|
|
6
|
+
installRustCrate(): boolean;
|
|
7
|
+
cleanupRustCrate(): boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('DdkRn');
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Generated by uniffi-bindgen-react-native
|
|
2
|
+
import installer from './NativeDdkRn';
|
|
3
|
+
|
|
4
|
+
// Register the rust crate with Hermes
|
|
5
|
+
// - the boolean flag ensures this loads exactly once, even if the JS
|
|
6
|
+
// code is reloaded (e.g. during development with metro).
|
|
7
|
+
let rustInstalled = false;
|
|
8
|
+
if (!rustInstalled) {
|
|
9
|
+
installer.installRustCrate();
|
|
10
|
+
rustInstalled = true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Export the generated bindings to the app.
|
|
14
|
+
export * from './/ddk_ffi';
|
|
15
|
+
|
|
16
|
+
// Now import the bindings so we can:
|
|
17
|
+
// - intialize them
|
|
18
|
+
// - export them as namespaced objects as the default export.
|
|
19
|
+
import * as ddk_ffi from './/ddk_ffi';
|
|
20
|
+
|
|
21
|
+
// Initialize the generated bindings: mostly checksums, but also callbacks.
|
|
22
|
+
// - the boolean flag ensures this loads exactly once, even if the JS code
|
|
23
|
+
// is reloaded (e.g. during development with metro).
|
|
24
|
+
let initialized = false;
|
|
25
|
+
if (!initialized) {
|
|
26
|
+
ddk_ffi.default.initialize();
|
|
27
|
+
initialized = true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// This provides parity with the index.web.ts version of this file.
|
|
31
|
+
// The web version relies on an asynchronous fetch, which this doesn't
|
|
32
|
+
// need, so we just no-op.
|
|
33
|
+
export async function uniffiInitAsync() {
|
|
34
|
+
// NOOP.
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Export the crates as individually namespaced objects.
|
|
38
|
+
export default {
|
|
39
|
+
ddk_ffi,
|
|
40
|
+
};
|
|
41
|
+
|