-PreactNativeArchitectures=x86_64
28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
29 |
30 | # Use this property to enable support to the new architecture.
31 | # This will allow you to use TurboModules and the Fabric render in
32 | # your application. You should enable this flag either if you want
33 | # to write custom TurboModules/Fabric components OR use libraries that
34 | # are providing them.
35 | newArchEnabled=true
36 |
37 | # Use this property to enable or disable the Hermes JS engine.
38 | # If set to false, you will be using JSC instead.
39 | hermesEnabled=true
40 |
41 | ReactNativeStaticServer_webdav = true
42 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
2 | plugins { id("com.facebook.react.settings") }
3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
4 | rootProject.name = 'drpogodin.reactnativestaticserver.example'
5 | include ':app'
6 | includeBuild('../node_modules/@react-native/gradle-plugin')
7 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactNativeStaticServerExample",
3 | "displayName": "ReactNativeStaticServerExample"
4 | }
5 |
--------------------------------------------------------------------------------
/example/assets/webroot/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | @dr.pogodin/react-native-static-server
13 | — Embed HTTP server for React Native applications.
14 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/example/assets/webroot/script.js:
--------------------------------------------------------------------------------
1 | // This will handle incoming messages from the React Native layer,
2 | // the actual .onNativeMessage name can be any name we decide to use
3 | // in our message envelope on the native side.
4 | window.onNativeMessage = function (message) {
5 | // eslint-disable-next-line no-alert
6 | alert(`Got message from React Native layer: ${message}`);
7 | };
8 |
9 | document.getElementById('message-to-rn').addEventListener('click', function () {
10 | // .ReactNativeWebView is automatically attached to the `window` by the host
11 | // WebView component, and it has .postMessage() method allowing to send text
12 | // messages to the React Native layer.
13 | if (window.ReactNativeWebView) {
14 | const message = 'Hello from the WebView content!';
15 | window.ReactNativeWebView.postMessage(message);
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/example/assets/webroot/style.css:
--------------------------------------------------------------------------------
1 | .header {
2 | background: linear-gradient(to right, red, orange, yellow, green, skyblue, blue, purple);
3 | background-clip: text;
4 | color: transparent;
5 | display: inline-block;
6 | font-weight: 900;
7 | text-decoration: underline red;
8 | -webkit-background-clip: text;
9 | }
10 |
--------------------------------------------------------------------------------
/example/assets/webroot/version:
--------------------------------------------------------------------------------
1 | 1.0.0
--------------------------------------------------------------------------------
/example/babel.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { getConfig } = require('react-native-builder-bob/babel-config');
3 | const pkg = require('../package.json');
4 |
5 | const root = path.resolve(__dirname, '..');
6 |
7 | module.exports = getConfig(
8 | {
9 | presets: ['module:@react-native/babel-preset'],
10 | },
11 | { root, pkg }
12 | );
13 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import { AppRegistry } from 'react-native';
2 | import App from './src/App';
3 | import { name as appName } from './app.json';
4 |
5 | AppRegistry.registerComponent(appName, () => App);
6 |
--------------------------------------------------------------------------------
/example/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 |
6 | # NODE_BINARY variable contains the PATH to the node executable.
7 | #
8 | # Customize the NODE_BINARY variable here.
9 | # For example, to use nvm with brew, add the following line
10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
11 |
12 | # To allow finding Node installed via NVM.
13 | export NVM_DIR="$HOME/.nvm"
14 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
15 |
16 | export NODE_BINARY=$(command -v node)
17 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | ENV['RCT_NEW_ARCH_ENABLED'] = '1'
2 |
3 | # Resolve react_native_pods.rb with node to allow for hoisting
4 | require Pod::Executable.execute_command('node', ['-p',
5 | 'require.resolve(
6 | "react-native/scripts/react_native_pods.rb",
7 | {paths: [process.argv[1]]},
8 | )', __dir__]).strip
9 |
10 | platform :ios, min_ios_version_supported
11 | prepare_react_native_project!
12 |
13 | linkage = ENV['USE_FRAMEWORKS']
14 | if linkage != nil
15 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
16 | use_frameworks! :linkage => linkage.to_sym
17 | end
18 |
19 | target 'ReactNativeStaticServerExample' do
20 | config = use_native_modules!
21 |
22 | use_react_native!(
23 | :path => config[:reactNativePath],
24 | # An absolute path to your application root.
25 | :app_path => "#{Pod::Config.instance.installation_root}/.."
26 | )
27 |
28 |
29 | # Run Codegen during development for the example app.
30 | pre_install do |installer|
31 | system("cd ../../ && npx bob build --target codegen")
32 | end
33 |
34 | post_install do |installer|
35 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
36 | react_native_post_install(
37 | installer,
38 | config[:reactNativePath],
39 | :mac_catalyst_enabled => ENV['MAC_CATALYST'] == '1'
40 | # :ccache_enabled => true
41 | )
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample.xcodeproj/xcshareddata/xcschemes/ReactNativeStaticServerExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import React
3 | import React_RCTAppDelegate
4 | import ReactAppDependencyProvider
5 |
6 | @main
7 | class AppDelegate: UIResponder, UIApplicationDelegate {
8 | var window: UIWindow?
9 |
10 | var reactNativeDelegate: ReactNativeDelegate?
11 | var reactNativeFactory: RCTReactNativeFactory?
12 |
13 | func application(
14 | _ application: UIApplication,
15 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
16 | ) -> Bool {
17 | let delegate = ReactNativeDelegate()
18 | let factory = RCTReactNativeFactory(delegate: delegate)
19 | delegate.dependencyProvider = RCTAppDependencyProvider()
20 |
21 | reactNativeDelegate = delegate
22 | reactNativeFactory = factory
23 |
24 | window = UIWindow(frame: UIScreen.main.bounds)
25 |
26 | factory.startReactNative(
27 | withModuleName: "ReactNativeStaticServerExample",
28 | in: window,
29 | launchOptions: launchOptions
30 | )
31 |
32 | return true
33 | }
34 | }
35 |
36 | class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
37 | override func sourceURL(for bridge: RCTBridge) -> URL? {
38 | self.bundleURL()
39 | }
40 |
41 | override func bundleURL() -> URL? {
42 | #if DEBUG
43 | RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
44 | #else
45 | Bundle.main.url(forResource: "main", withExtension: "jsbundle")
46 | #endif
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ReactNativeStaticServerExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 |
30 | NSAllowsArbitraryLoads
31 |
32 | NSAllowsLocalNetworking
33 |
34 |
35 | NSLocationWhenInUseUsageDescription
36 |
37 | UILaunchStoryboardName
38 | LaunchScreen
39 | UIRequiredDeviceCapabilities
40 |
41 | arm64
42 |
43 | UISupportedInterfaceOrientations
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationLandscapeLeft
47 | UIInterfaceOrientationLandscapeRight
48 |
49 | UIViewControllerBasedStatusBarAppearance
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyAccessedAPITypes
6 |
7 |
8 | NSPrivacyAccessedAPIType
9 | NSPrivacyAccessedAPICategoryFileTimestamp
10 | NSPrivacyAccessedAPITypeReasons
11 |
12 | C617.1
13 | 0A2A.1
14 |
15 |
16 |
17 | NSPrivacyAccessedAPIType
18 | NSPrivacyAccessedAPICategoryUserDefaults
19 | NSPrivacyAccessedAPITypeReasons
20 |
21 | CA92.1
22 |
23 |
24 |
25 | NSPrivacyAccessedAPIType
26 | NSPrivacyAccessedAPICategoryDiskSpace
27 | NSPrivacyAccessedAPITypeReasons
28 |
29 | 85F4.1
30 | E174.1
31 |
32 |
33 |
34 | NSPrivacyAccessedAPIType
35 | NSPrivacyAccessedAPICategorySystemBootTime
36 | NSPrivacyAccessedAPITypeReasons
37 |
38 | 35F9.1
39 |
40 |
41 |
42 | NSPrivacyCollectedDataTypes
43 |
44 | NSPrivacyTracking
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/example/ios/ReactNativeStaticServerExample/ReactNativeStaticServerExample.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 | com.apple.security.network.server
10 |
11 | com.apple.security.personal-information.location
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'react-native',
3 | };
4 |
--------------------------------------------------------------------------------
/example/metro.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { getDefaultConfig } = require('@react-native/metro-config');
3 | const { getConfig } = require('react-native-builder-bob/metro-config');
4 | const pkg = require('../package.json');
5 |
6 | const root = path.resolve(__dirname, '..');
7 |
8 | /**
9 | * Metro configuration
10 | * https://facebook.github.io/metro/docs/configuration
11 | *
12 | * @type {import('metro-config').MetroConfig}
13 | */
14 | module.exports = getConfig(getDefaultConfig(__dirname), {
15 | root,
16 | pkg,
17 | project: __dirname,
18 | });
19 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@dr.pogodin/react-native-static-server-example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "windows:autolink": "./node_modules/.bin/rnc-cli autolink-windows --sln \"windows\\ReactNativeStaticServerExample.sln\" --proj \"windows\\ReactNativeStaticServerExample\\ReactNativeStaticServerExample.vcxproj\"",
10 | "build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"",
11 | "build:ios": "react-native build-ios --scheme ReactNativeStaticServerExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\""
12 | },
13 | "dependencies": {
14 | "@dr.pogodin/react-native-fs": "^2.33.1",
15 | "@dr.pogodin/react-native-webview": "^13.15.8",
16 | "react": "19.0.0",
17 | "react-native": "0.79.1",
18 | "react-native-windows": "0.78.5"
19 | },
20 | "devDependencies": {
21 | "@babel/core": "^7.26.10",
22 | "@babel/preset-env": "^7.26.9",
23 | "@babel/runtime": "^7.27.0",
24 | "@react-native-community/cli": "18.0.0",
25 | "@react-native-community/cli-platform-android": "18.0.0",
26 | "@react-native-community/cli-platform-ios": "18.0.0",
27 | "@react-native/babel-preset": "0.79.1",
28 | "@react-native/metro-config": "0.79.1",
29 | "@react-native/typescript-config": "0.79.1",
30 | "@types/react": "^19.0.0",
31 | "react-native-builder-bob": "^0.40.6"
32 | },
33 | "engines": {
34 | "node": ">=18"
35 | },
36 | "react-native-windows": {
37 | "init-windows": {
38 | "name": "ReactNativeStaticServerExample",
39 | "namespace": "ReactNativeStaticServerExample",
40 | "template": "old/uwp-cpp-app"
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/example/react-native.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const pkg = require('../package.json');
3 |
4 | module.exports = {
5 | project: {
6 | ios: {
7 | automaticPodsInstallation: true,
8 | },
9 | },
10 | dependencies: {
11 | [pkg.name]: {
12 | root: path.join(__dirname, '..'),
13 | platforms: {
14 | // Codegen script incorrectly fails without this
15 | // So we explicitly specify the platforms with empty object
16 | ios: {},
17 | android: {},
18 | },
19 | },
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/example/windows/.gitignore:
--------------------------------------------------------------------------------
1 | *AppPackages*
2 | *BundleArtifacts*
3 |
4 | #OS junk files
5 | [Tt]humbs.db
6 | *.DS_Store
7 |
8 | #Visual Studio files
9 | *.[Oo]bj
10 | *.user
11 | *.aps
12 | *.pch
13 | *.vspscc
14 | *.vssscc
15 | *_i.c
16 | *_p.c
17 | *.ncb
18 | *.suo
19 | *.tlb
20 | *.tlh
21 | *.bak
22 | *.[Cc]ache
23 | *.ilk
24 | *.log
25 | *.lib
26 | *.sbr
27 | *.sdf
28 | *.opensdf
29 | *.opendb
30 | *.unsuccessfulbuild
31 | ipch/
32 | [Oo]bj/
33 | [Bb]in
34 | [Dd]ebug*/
35 | [Rr]elease*/
36 | Ankh.NoLoad
37 |
38 | # Visual C++ cache files
39 | ipch/
40 | *.aps
41 | *.ncb
42 | *.opendb
43 | *.opensdf
44 | *.sdf
45 | *.cachefile
46 | *.VC.db
47 | *.VC.VC.opendb
48 |
49 | #MonoDevelop
50 | *.pidb
51 | *.userprefs
52 |
53 | #Tooling
54 | _ReSharper*/
55 | *.resharper
56 | [Tt]est[Rr]esult*
57 | *.sass-cache
58 |
59 | #Project files
60 | [Bb]uild/
61 |
62 | #Subversion files
63 | .svn
64 |
65 | # Office Temp Files
66 | ~$*
67 |
68 | # vim Temp Files
69 | *~
70 |
71 | #NuGet
72 | packages/
73 | *.nupkg
74 |
75 | #ncrunch
76 | *ncrunch*
77 | *crunch*.local.xml
78 |
79 | # visual studio database projects
80 | *.dbmdl
81 |
82 | #Test files
83 | *.testsettings
84 |
85 | #Other files
86 | *.DotSettings
87 | .vs/
88 | *project.lock.json
89 |
90 | #Files generated by the VS build
91 | **/Generated Files/**
92 |
93 |
--------------------------------------------------------------------------------
/example/windows/ExperimentalFeatures.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
17 | true
18 |
19 |
26 | false
27 |
28 | true
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/windows/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/.gitignore:
--------------------------------------------------------------------------------
1 | /Bundle
2 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/App.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | // #pragma warning(disable:4996)
4 |
5 | #include "App.h"
6 |
7 | #include "AutolinkedNativeModules.g.h"
8 | #include "ReactPackageProvider.h"
9 |
10 | using namespace winrt;
11 | using namespace xaml;
12 | using namespace xaml::Controls;
13 | using namespace xaml::Navigation;
14 |
15 | using namespace Windows::ApplicationModel;
16 | namespace winrt::ReactNativeStaticServerExample::implementation
17 | {
18 | ///
19 | /// Initializes the singleton application object. This is the first line of
20 | /// authored code executed, and as such is the logical equivalent of main() or
21 | /// WinMain().
22 | ///
23 | App::App() noexcept
24 | {
25 | /*
26 | AllocConsole();
27 | freopen("CONOUT$", "w", stdout);
28 | freopen("CONOUT$", "w", stderr);
29 | */
30 | #if BUNDLE
31 | JavaScriptBundleFile(L"index.windows");
32 | InstanceSettings().UseFastRefresh(false);
33 | #else
34 | JavaScriptBundleFile(L"index");
35 | InstanceSettings().UseFastRefresh(true);
36 | #endif
37 |
38 | #if _DEBUG
39 | InstanceSettings().UseDirectDebugger(true);
40 | InstanceSettings().UseDeveloperSupport(true);
41 | #else
42 | InstanceSettings().UseDirectDebugger(false);
43 | InstanceSettings().UseDeveloperSupport(false);
44 | #endif
45 |
46 | RegisterAutolinkedNativeModulePackages(PackageProviders()); // Includes any autolinked modules
47 |
48 | PackageProviders().Append(make()); // Includes all modules in this project
49 |
50 | InitializeComponent();
51 | }
52 |
53 | ///
54 | /// Invoked when the application is launched normally by the end user. Other entry points
55 | /// will be used such as when the application is launched to open a specific file.
56 | ///
57 | /// Details about the launch request and process.
58 | void App::OnLaunched(activation::LaunchActivatedEventArgs const& e)
59 | {
60 | super::OnLaunched(e);
61 |
62 | Frame rootFrame = Window::Current().Content().as();
63 | rootFrame.Navigate(xaml_typename(), box_value(e.Arguments()));
64 | }
65 |
66 | ///
67 | /// Invoked when the application is activated by some means other than normal launching.
68 | ///
69 | void App::OnActivated(Activation::IActivatedEventArgs const &e) {
70 | auto preActivationContent = Window::Current().Content();
71 | super::OnActivated(e);
72 | if (!preActivationContent && Window::Current()) {
73 | Frame rootFrame = Window::Current().Content().as();
74 | rootFrame.Navigate(xaml_typename(), nullptr);
75 | }
76 | }
77 |
78 | ///
79 | /// Invoked when application execution is being suspended. Application state is saved
80 | /// without knowing whether the application will be terminated or resumed with the contents
81 | /// of memory still intact.
82 | ///
83 | /// The source of the suspend request.
84 | /// Details about the suspend request.
85 | void App::OnSuspending([[maybe_unused]] IInspectable const& sender, [[maybe_unused]] SuspendingEventArgs const& e)
86 | {
87 | // Save application state and stop any background activity
88 | }
89 |
90 | ///
91 | /// Invoked when Navigation to a certain page fails
92 | ///
93 | /// The Frame which failed navigation
94 | /// Details about the navigation failure
95 | void App::OnNavigationFailed(IInspectable const&, NavigationFailedEventArgs const& e)
96 | {
97 | throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name);
98 | }
99 |
100 | } // namespace winrt::ReactNativeStaticServerExample::implementation
101 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/App.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "App.xaml.g.h"
4 |
5 | #include
6 |
7 | namespace activation = winrt::Windows::ApplicationModel::Activation;
8 |
9 | namespace winrt::ReactNativeStaticServerExample::implementation
10 | {
11 | struct App : AppT
12 | {
13 | App() noexcept;
14 | void OnLaunched(activation::LaunchActivatedEventArgs const&);
15 | void OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs const &e);
16 | void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&);
17 | void OnNavigationFailed(IInspectable const&, xaml::Navigation::NavigationFailedEventArgs const&);
18 | private:
19 | using super = AppT;
20 | };
21 | } // namespace winrt::ReactNativeStaticServerExample::implementation
22 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/App.idl:
--------------------------------------------------------------------------------
1 | namespace ReactNativeStaticServerExample
2 | {
3 | }
4 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/windows/ReactNativeStaticServerExample/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/windows/ReactNativeStaticServerExample/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/windows/ReactNativeStaticServerExample/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/windows/ReactNativeStaticServerExample/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/windows/ReactNativeStaticServerExample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/windows/ReactNativeStaticServerExample/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/example/windows/ReactNativeStaticServerExample/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/AutolinkedNativeModules.g.cpp:
--------------------------------------------------------------------------------
1 | // AutolinkedNativeModules.g.cpp contents generated by "npx @react-native-community/cli autolink-windows"
2 | // clang-format off
3 | #include "pch.h"
4 | #include "AutolinkedNativeModules.g.h"
5 |
6 | // Includes from @dr.pogodin/react-native-static-server
7 | #include
8 |
9 | // Includes from @dr.pogodin/react-native-fs
10 | #include
11 |
12 | // Includes from @dr.pogodin/react-native-webview
13 | #include
14 |
15 | namespace winrt::Microsoft::ReactNative
16 | {
17 |
18 | void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders)
19 | {
20 | // IReactPackageProviders from @dr.pogodin/react-native-static-server
21 | packageProviders.Append(winrt::ReactNativeStaticServer::ReactPackageProvider());
22 | // IReactPackageProviders from @dr.pogodin/react-native-fs
23 | packageProviders.Append(winrt::ReactNativeFs::ReactPackageProvider());
24 | // IReactPackageProviders from @dr.pogodin/react-native-webview
25 | packageProviders.Append(winrt::ReactNativeWebView::ReactPackageProvider());
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/AutolinkedNativeModules.g.h:
--------------------------------------------------------------------------------
1 | // AutolinkedNativeModules.g.h contents generated by "npx @react-native-community/cli autolink-windows"
2 | // clang-format off
3 | #pragma once
4 |
5 | namespace winrt::Microsoft::ReactNative
6 | {
7 |
8 | void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/AutolinkedNativeModules.g.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/AutolinkedNativeModules.g.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {16da6f7d-0d78-4550-bcf3-a340a17c7fd9}
8 |
9 |
10 |
11 | {53640a4d-6b5f-4963-872b-27e5aa4f96ee}
12 |
13 |
14 |
15 | {00AA3765-C6A0-4713-B3F9-BFE47B9C83F5}
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/MainPage.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "MainPage.h"
3 | #if __has_include("MainPage.g.cpp")
4 | #include "MainPage.g.cpp"
5 | #endif
6 |
7 | #include "App.h"
8 |
9 | using namespace winrt;
10 | using namespace xaml;
11 |
12 | namespace winrt::ReactNativeStaticServerExample::implementation
13 | {
14 | MainPage::MainPage()
15 | {
16 | InitializeComponent();
17 | auto app = Application::Current().as();
18 | ReactRootView().ReactNativeHost(app->Host());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/MainPage.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "MainPage.g.h"
3 | #include
4 |
5 | namespace winrt::ReactNativeStaticServerExample::implementation
6 | {
7 | struct MainPage : MainPageT
8 | {
9 | MainPage();
10 | };
11 | }
12 |
13 | namespace winrt::ReactNativeStaticServerExample::factory_implementation
14 | {
15 | struct MainPage : MainPageT
16 | {
17 | };
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/MainPage.idl:
--------------------------------------------------------------------------------
1 | #include "NamespaceRedirect.h"
2 |
3 | namespace ReactNativeStaticServerExample
4 | {
5 | [default_interface]
6 | runtimeclass MainPage : XAML_NAMESPACE.Controls.Page
7 | {
8 | MainPage();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
11 |
16 |
17 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | ReactNativeStaticServerExample
18 | drpog
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/PropertySheet.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
20 |
21 | <_CustomResource Include="..\..\assets\webroot\**\*">
22 | webroot\%(RecursiveDir)%(FileName)%(Extension)
23 | true
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/ReactNativeStaticServerExample.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Assets
25 |
26 |
27 | Assets
28 |
29 |
30 | Assets
31 |
32 |
33 | Assets
34 |
35 |
36 | Assets
37 |
38 |
39 | Assets
40 |
41 |
42 | Assets
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | {e48dc53e-40b1-40cb-970a-f89935452892}
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/ReactPackageProvider.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ReactPackageProvider.h"
3 | #include "NativeModules.h"
4 |
5 | using namespace winrt::Microsoft::ReactNative;
6 |
7 | namespace winrt::ReactNativeStaticServerExample::implementation
8 | {
9 |
10 | void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept
11 | {
12 | AddAttributedModules(packageBuilder, true);
13 | }
14 |
15 | } // namespace winrt::ReactNativeStaticServerExample::implementation
16 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/ReactPackageProvider.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "winrt/Microsoft.ReactNative.h"
4 |
5 | namespace winrt::ReactNativeStaticServerExample::implementation
6 | {
7 | struct ReactPackageProvider : winrt::implements
8 | {
9 | public: // IReactPackageProvider
10 | void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept;
11 | };
12 | } // namespace winrt::ReactNativeStaticServerExample::implementation
13 |
14 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/packages.lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "dependencies": {
4 | "native,Version=v0.0": {
5 | "Microsoft.JavaScript.Hermes": {
6 | "type": "Direct",
7 | "requested": "[0.1.23, )",
8 | "resolved": "0.1.23",
9 | "contentHash": "cA9t1GjY4Yo0JD1AfA//e1lOwk48hLANfuX6GXrikmEBNZVr2TIX5ONJt5tqCnpZyLz6xGiPDgTfFNKbSfb21g=="
10 | },
11 | "Microsoft.UI.Xaml": {
12 | "type": "Direct",
13 | "requested": "[2.8.0, )",
14 | "resolved": "2.8.0",
15 | "contentHash": "vxdHxTr63s5KVtNddMFpgvjBjUH50z7seq/5jLWmmSuf8poxg+sXrywkofUdE8ZstbpO9y3FL/IXXUcPYbeesA==",
16 | "dependencies": {
17 | "Microsoft.Web.WebView2": "1.0.1264.42"
18 | }
19 | },
20 | "Microsoft.Windows.CppWinRT": {
21 | "type": "Direct",
22 | "requested": "[2.0.230706.1, )",
23 | "resolved": "2.0.230706.1",
24 | "contentHash": "l0D7oCw/5X+xIKHqZTi62TtV+1qeSz7KVluNFdrJ9hXsst4ghvqQ/Yhura7JqRdZWBXAuDS0G0KwALptdoxweQ=="
25 | },
26 | "boost": {
27 | "type": "Transitive",
28 | "resolved": "1.83.0",
29 | "contentHash": "cy53VNMzysEMvhBixDe8ujPk67Fcj3v6FPHQnH91NYJNLHpc6jxa2xq9ruCaaJjE4M3YrGSHDi4uUSTGBWw6EQ=="
30 | },
31 | "Microsoft.Web.WebView2": {
32 | "type": "Transitive",
33 | "resolved": "1.0.1264.42",
34 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
35 | },
36 | "common": {
37 | "type": "Project",
38 | "dependencies": {
39 | "boost": "[1.83.0, )"
40 | }
41 | },
42 | "fmt": {
43 | "type": "Project"
44 | },
45 | "folly": {
46 | "type": "Project",
47 | "dependencies": {
48 | "Fmt": "[1.0.0, )",
49 | "boost": "[1.83.0, )"
50 | }
51 | },
52 | "microsoft.reactnative": {
53 | "type": "Project",
54 | "dependencies": {
55 | "Common": "[1.0.0, )",
56 | "Folly": "[1.0.0, )",
57 | "Microsoft.JavaScript.Hermes": "[0.1.23, )",
58 | "Microsoft.UI.Xaml": "[2.8.0, )",
59 | "ReactCommon": "[1.0.0, )",
60 | "boost": "[1.83.0, )"
61 | }
62 | },
63 | "reactcommon": {
64 | "type": "Project",
65 | "dependencies": {
66 | "Folly": "[1.0.0, )",
67 | "boost": "[1.83.0, )"
68 | }
69 | },
70 | "reactnativefs": {
71 | "type": "Project",
72 | "dependencies": {
73 | "Microsoft.ReactNative": "[1.0.0, )",
74 | "Microsoft.UI.Xaml": "[2.8.0, )"
75 | }
76 | },
77 | "reactnativestaticserver": {
78 | "type": "Project",
79 | "dependencies": {
80 | "Microsoft.ReactNative": "[1.0.0, )",
81 | "Microsoft.UI.Xaml": "[2.8.0, )"
82 | }
83 | },
84 | "reactnativewebview": {
85 | "type": "Project",
86 | "dependencies": {
87 | "Microsoft.ReactNative": "[1.0.0, )",
88 | "Microsoft.UI.Xaml": "[2.8.0, )"
89 | }
90 | }
91 | },
92 | "native,Version=v0.0/win10-arm": {
93 | "Microsoft.Web.WebView2": {
94 | "type": "Transitive",
95 | "resolved": "1.0.1264.42",
96 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
97 | }
98 | },
99 | "native,Version=v0.0/win10-arm-aot": {
100 | "Microsoft.Web.WebView2": {
101 | "type": "Transitive",
102 | "resolved": "1.0.1264.42",
103 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
104 | }
105 | },
106 | "native,Version=v0.0/win10-arm64-aot": {
107 | "Microsoft.Web.WebView2": {
108 | "type": "Transitive",
109 | "resolved": "1.0.1264.42",
110 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
111 | }
112 | },
113 | "native,Version=v0.0/win10-x64": {
114 | "Microsoft.Web.WebView2": {
115 | "type": "Transitive",
116 | "resolved": "1.0.1264.42",
117 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
118 | }
119 | },
120 | "native,Version=v0.0/win10-x64-aot": {
121 | "Microsoft.Web.WebView2": {
122 | "type": "Transitive",
123 | "resolved": "1.0.1264.42",
124 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
125 | }
126 | },
127 | "native,Version=v0.0/win10-x86": {
128 | "Microsoft.Web.WebView2": {
129 | "type": "Transitive",
130 | "resolved": "1.0.1264.42",
131 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
132 | }
133 | },
134 | "native,Version=v0.0/win10-x86-aot": {
135 | "Microsoft.Web.WebView2": {
136 | "type": "Transitive",
137 | "resolved": "1.0.1264.42",
138 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
139 | }
140 | }
141 | }
142 | }
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/pch.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
--------------------------------------------------------------------------------
/example/windows/ReactNativeStaticServerExample/pch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define NOMINMAX
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | using namespace winrt::Windows::Foundation;
25 |
--------------------------------------------------------------------------------
/glob/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
2 | project(GLOB C)
3 |
4 | set(CMAKE_C_STANDARD 99)
5 | set(CMAKE_C_STANDARD_REQUIRED TRUE)
6 |
7 | set(HEADERS collate.h freebsd-compat.h glob.h)
8 | set(SOURCES glob.c)
9 |
10 | add_compile_definitions(__USE_BSD)
11 | add_library(glob ${HEADERS} ${SOURCES})
12 |
13 | install(TARGETS glob)
14 | install(FILES ${HEADERS} DESTINATION include)
15 |
--------------------------------------------------------------------------------
/glob/README.md:
--------------------------------------------------------------------------------
1 | The Glob library is a part of Android SDK starting from SDK 28; thus, to support
2 | older SDKs we compile it from sources. These source files are taken from
3 | the https://android.googlesource.com/platform/bionic repository
4 | ([bionic](https://en.wikipedia.org/wiki/Bionic_%28software%29)
5 | is Android's C library, math library, and dynamic linker).
6 |
--------------------------------------------------------------------------------
/glob/collate.h:
--------------------------------------------------------------------------------
1 | #include "freebsd-compat.h"
2 |
3 | /**
4 | * [reallocarray(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
5 | * allocated memory on the heap.
6 | *
7 | * Equivalent to `realloc(__ptr, __item_count * __item_size)` but fails if the
8 | * multiplication overflows.
9 | *
10 | * Returns a pointer (which may be different from `__ptr`) to the resized
11 | * memory on success and returns a null pointer and sets `errno` on failure
12 | * (but see the notes for malloc()).
13 | */
14 | #if __ANDROID_API__ >= 29
15 | void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __INTRODUCED_IN(29);
16 | #else
17 | #include
18 | static __inline void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) {
19 | size_t __new_size;
20 | if (__builtin_mul_overflow(__item_count, __item_size, &__new_size)) {
21 | errno = ENOMEM;
22 | return NULL;
23 | }
24 | return realloc(__ptr, __new_size);
25 | }
26 | #endif
27 |
--------------------------------------------------------------------------------
/glob/freebsd-compat.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #define _BSD_SOURCE
20 |
21 | #define REPLACE_GETOPT
22 |
23 | /* FreeBSD has this, but we can't really implement it correctly on Linux. */
24 | #define issetugid() 0
25 |
26 | #define __compiler_membar() __asm __volatile(" " : : : "memory")
27 |
--------------------------------------------------------------------------------
/glob/glob.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1989, 1993
3 | * The Regents of the University of California. All rights reserved.
4 | *
5 | * This code is derived from software contributed to Berkeley by
6 | * Guido van Rossum.
7 | *
8 | * Redistribution and use in source and binary forms, with or without
9 | * modification, are permitted provided that the following conditions
10 | * are met:
11 | * 1. Redistributions of source code must retain the above copyright
12 | * notice, this list of conditions and the following disclaimer.
13 | * 2. Redistributions in binary form must reproduce the above copyright
14 | * notice, this list of conditions and the following disclaimer in the
15 | * documentation and/or other materials provided with the distribution.
16 | * 3. Neither the name of the University nor the names of its contributors
17 | * may be used to endorse or promote products derived from this software
18 | * without specific prior written permission.
19 | *
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 | * SUCH DAMAGE.
31 | *
32 | * @(#)glob.h 8.1 (Berkeley) 6/2/93
33 | * $FreeBSD$
34 | */
35 |
36 | #ifndef _GLOB_H_
37 | #define _GLOB_H_
38 |
39 | #include
40 | #include
41 |
42 | struct dirent;
43 | struct stat;
44 |
45 | typedef struct {
46 | size_t gl_pathc; /* Count of total paths so far. */
47 | size_t gl_matchc; /* Count of paths matching pattern. */
48 | size_t gl_offs; /* Reserved at beginning of gl_pathv. */
49 | int gl_flags; /* Copy of flags parameter to glob. */
50 |
51 | /** List of paths matching pattern. */
52 | char* _Nullable * _Nullable gl_pathv;
53 |
54 | /** Copy of `__error_callback` parameter to glob. */
55 | int (* _Nullable gl_errfunc)(const char* _Nonnull __failure_path, int __failure_errno);
56 |
57 | /** Called instead of closedir() when GLOB_ALTDIRFUNC flag is specified. */
58 | void (* _Nullable gl_closedir)(void* _Nonnull);
59 | /** Called instead of readdir() when GLOB_ALTDIRFUNC flag is specified. */
60 | struct dirent* _Nullable (* _Nonnull gl_readdir)(void* _Nonnull);
61 | /** Called instead of opendir() when GLOB_ALTDIRFUNC flag is specified. */
62 | void* _Nullable (* _Nonnull gl_opendir)(const char* _Nonnull);
63 | /** Called instead of lstat() when GLOB_ALTDIRFUNC flag is specified. */
64 | int (* _Nullable gl_lstat)(const char* _Nonnull, struct stat* _Nonnull);
65 | /** Called instead of stat() when GLOB_ALTDIRFUNC flag is specified. */
66 | int (* _Nullable gl_stat)(const char* _Nonnull, struct stat* _Nonnull);
67 | } glob_t;
68 |
69 | /* Believed to have been introduced in 1003.2-1992 */
70 | #define GLOB_APPEND 0x0001 /* Append to output from previous call. */
71 | #define GLOB_DOOFFS 0x0002 /* Prepend `gl_offs` null pointers (leaving space for exec, say). */
72 | #define GLOB_ERR 0x0004 /* Return on error. */
73 | #define GLOB_MARK 0x0008 /* Append "/" to the names of returned directories. */
74 | #define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
75 | #define GLOB_NOSORT 0x0020 /* Don't sort. */
76 | #define GLOB_NOESCAPE 0x2000 /* Disable backslash escaping. */
77 |
78 | /* Error values returned by glob(3) */
79 | #define GLOB_NOSPACE (-1) /* Malloc call failed. */
80 | #define GLOB_ABORTED (-2) /* Unignored error. */
81 | #define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK was not set. */
82 |
83 | #if __USE_BSD
84 | #define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
85 | #define GLOB_BRACE 0x0080 /* Expand braces like csh. */
86 | #define GLOB_MAGCHAR 0x0100 /* Set in `gl_flags` if the pattern had globbing characters. */
87 | #define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
88 | #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
89 | #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
90 | #define GLOB_LIMIT 0x1000 /* limit number of returned paths */
91 | #endif
92 |
93 | __BEGIN_DECLS
94 |
95 | int glob(const char* _Nonnull __pattern, int __flags, int (* _Nullable __error_callback)(const char* _Nonnull __failure_path, int __failure_errno), glob_t* _Nonnull __result_ptr);
96 | void globfree(glob_t* _Nonnull __result_ptr);
97 |
98 | __END_DECLS
99 |
100 | #endif
101 |
--------------------------------------------------------------------------------
/ios/Errors.h:
--------------------------------------------------------------------------------
1 | //
2 | // Errors.h
3 | // ReactNativeStaticServer
4 | //
5 | // Created by Sergey Pogodin on 10/4/23.
6 | //
7 |
8 | #ifndef Errors_h
9 | #define Errors_h
10 |
11 | #import
12 |
13 | @interface RNSSException : NSException
14 | - (id) initWithName: (NSString*)name details: (NSString*)details;
15 | - (NSError*) error;
16 | - (RNSSException*) log;
17 | - (void) reject:(RCTPromiseRejectBlock)reject;
18 | + (RNSSException*) from: (NSException*)exception;
19 | + (RNSSException*) name: (NSString*)name;
20 | + (RNSSException*) name: (NSString*)name details: (NSString*)details;
21 |
22 | @property(readonly) NSInteger code;
23 | @end
24 |
25 | #endif /* Errors_h */
26 |
--------------------------------------------------------------------------------
/ios/Errors.mm:
--------------------------------------------------------------------------------
1 | #import "Errors.h"
2 |
3 | static NSString * const ERROR_DOMAIN = @"RNStaticServer";
4 |
5 | @implementation RNSSException;
6 |
7 | - (id) initWithName:(NSString*)name details:(NSString*)details
8 | {
9 | self = [super initWithName:name reason:details userInfo:nil];
10 | return self;
11 | }
12 |
13 | /**
14 | * Creates a new NSError object based on this RNSSException
15 | */
16 | - (NSError*) error
17 | {
18 | return [NSError
19 | errorWithDomain: ERROR_DOMAIN
20 | code: self.code
21 | userInfo: self.userInfo
22 | ];
23 | }
24 |
25 | - (RNSSException*) log
26 | {
27 | NSLog(@"%@: %@", self.name, self.reason);
28 | return self;
29 | }
30 |
31 | - (void) reject: (RCTPromiseRejectBlock)reject
32 | {
33 | reject(self.name, self.reason, [self error]);
34 | }
35 |
36 | + (RNSSException*) from: (NSException*)exception
37 | {
38 | return [[RNSSException alloc]
39 | initWithName: exception.name
40 | reason: exception.reason
41 | userInfo: exception.userInfo
42 | ];
43 | }
44 |
45 | + (RNSSException*) name: (NSString*)name
46 | {
47 | return [[RNSSException alloc] initWithName:name details:nil];
48 | }
49 |
50 | + (RNSSException*) name: (NSString*)name details:(NSString*)details
51 | {
52 | return [[RNSSException alloc] initWithName:name details:details];
53 | }
54 |
55 | @end;
56 |
--------------------------------------------------------------------------------
/ios/ReactNativeStaticServer.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "generated/RNReactNativeStaticServerSpec/RNReactNativeStaticServerSpec.h"
4 |
5 | @interface ReactNativeStaticServer : RCTEventEmitter
6 |
7 | @end
8 |
--------------------------------------------------------------------------------
/ios/ReactNativeStaticServer.mm:
--------------------------------------------------------------------------------
1 | #import "ReactNativeStaticServer.h"
2 | #import "Server.h"
3 | #import "Errors.h"
4 | #import
5 | #import
6 | #include
7 |
8 | static NSString * const EVENT_NAME = @"RNStaticServer";
9 | static dispatch_semaphore_t sem = dispatch_semaphore_create(1);
10 |
11 | @implementation ReactNativeStaticServer {
12 | Server *server;
13 | }
14 |
15 | RCT_EXPORT_MODULE();
16 |
17 | - (instancetype)init {
18 | return [super init];
19 | }
20 |
21 | - (void)invalidate
22 | {
23 | [super invalidate];
24 | if (self->server) {
25 | [self stop:^void(id){}
26 | reject:^void(NSString *a,NSString *b, NSError *c){}];
27 | }
28 | }
29 |
30 | - (NSDictionary*) constantsToExport {
31 | return @{
32 | @"CRASHED": CRASHED,
33 | @"IS_MAC_CATALYST": @(TARGET_OS_MACCATALYST),
34 | @"LAUNCHED": LAUNCHED,
35 | @"TERMINATED": TERMINATED
36 | };
37 | }
38 |
39 | - (NSDictionary*) getConstants {
40 | return [self constantsToExport];
41 | }
42 |
43 | RCT_REMAP_METHOD(getActiveServerId,
44 | getActiveServerId:(RCTPromiseResolveBlock) resolve
45 | reject:(RCTPromiseRejectBlock)reject
46 | ) {
47 | resolve(self->server ? self->server.serverId : [NSNull null]);
48 | }
49 |
50 | RCT_REMAP_METHOD(getLocalIpAddress,
51 | getLocalIpAddress:(RCTPromiseResolveBlock)resolve
52 | reject:(RCTPromiseRejectBlock)reject
53 | ) {
54 | struct ifaddrs *interfaces = NULL; // a linked list of network interfaces
55 | @try {
56 | struct ifaddrs *temp_addr = NULL;
57 | int success = getifaddrs(&interfaces); // get the list of network interfaces
58 | if (success == 0) {
59 | NSLog(@"Found network interfaces, iterating.");
60 | temp_addr = interfaces;
61 | while(temp_addr != NULL) {
62 | // Check if the current interface is of type AF_INET (IPv4)
63 | // and not the loopback interface (lo0)
64 | if(temp_addr->ifa_addr->sa_family == AF_INET) {
65 | if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
66 | NSLog(@"Found IPv4 address of the local wifi connection. Returning address.");
67 | NSString *ip = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
68 | resolve(ip);
69 | return;
70 | }
71 | }
72 | temp_addr = temp_addr->ifa_next;
73 | }
74 | }
75 | NSLog(@"Could not find IP address, falling back to '127.0.0.1'.");
76 | resolve(@"127.0.0.1");
77 | }
78 | @catch (NSException *e) {
79 | [[RNSSException from:e] reject:reject];
80 | }
81 | @finally {
82 | freeifaddrs(interfaces);
83 | }
84 | }
85 |
86 | RCTPromiseResolveBlock pendingResolve = nil;
87 | RCTPromiseRejectBlock pendingReject = nil;
88 |
89 | RCT_REMAP_METHOD(start,
90 | start:(double)_serverId
91 | configPath:(NSString*)configPath
92 | errlogPath:(NSString*)errlogPath
93 | resolve:(RCTPromiseResolveBlock)resolve
94 | reject:(RCTPromiseRejectBlock)reject
95 | ) {
96 | NSLog(@"Starting the server...");
97 |
98 | NSNumber *serverId = [NSNumber numberWithDouble:_serverId];
99 |
100 | dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
101 |
102 | if (self->server) {
103 | NSString *name = [NSString stringWithFormat:@"Failed to launch server #%@, another server instance (#%@) is active", serverId, self->server.serverId];
104 | auto e = [[RNSSException name:name] log];
105 | [e reject:reject];
106 | dispatch_semaphore_signal(sem);
107 | return;
108 | }
109 |
110 | if (pendingResolve != nil || pendingReject != nil) {
111 | NSString *name = [NSString stringWithFormat:@"Internal error (server #%@)", serverId];
112 | auto e = [[RNSSException name:name details:@"Non-expected pending promise"] log];
113 | [e reject:reject];
114 | dispatch_semaphore_signal(sem);
115 | return;
116 | }
117 |
118 | pendingResolve = resolve;
119 | pendingReject = reject;
120 |
121 | SignalConsumer signalConsumer = ^void(NSString * const signal,
122 | NSString * const details)
123 | {
124 | if (signal != LAUNCHED) self->server = nil;
125 | if (pendingResolve == nil && pendingReject == nil) {
126 | [self sendEventWithName:EVENT_NAME
127 | body: @{
128 | @"serverId": serverId,
129 | @"event": signal,
130 | @"details": details == nil ? @"" : details
131 | }
132 | ];
133 | } else {
134 | if (signal == CRASHED) {
135 | NSString *name = [NSString stringWithFormat:@"Server #%@ crashed", serverId];
136 | [[RNSSException name:name details:details]
137 | reject:pendingReject];
138 | } else pendingResolve(details);
139 | pendingResolve = nil;
140 | pendingReject = nil;
141 | dispatch_semaphore_signal(sem);
142 | }
143 | };
144 |
145 | self->server = [Server
146 | serverWithId:serverId
147 | configPath:configPath
148 | errlogPath:errlogPath
149 | signalConsumer:signalConsumer
150 | ];
151 |
152 | [self->server start];
153 | }
154 |
155 | - (NSArray *)supportedEvents {
156 | return @[EVENT_NAME];
157 | }
158 |
159 | RCT_REMAP_METHOD(stop,
160 | stop:(RCTPromiseResolveBlock)resolve
161 | reject:(RCTPromiseRejectBlock)reject
162 | ) {
163 | try {
164 | if (self->server) {
165 | NSLog(@"Stopping...");
166 |
167 | dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
168 |
169 | if (pendingResolve != nil || pendingReject != nil) {
170 | auto e = [[RNSSException name:@"Internal error"
171 | details:@"Unexpected pending promise"] log];
172 | [e reject:reject];
173 | dispatch_semaphore_signal(sem);
174 | return;
175 | }
176 |
177 | pendingResolve = resolve;
178 | pendingReject = reject;
179 | [self->server cancel];
180 | }
181 | } catch (NSException *e) {
182 | [[RNSSException from:e] reject:reject];
183 | }
184 | }
185 |
186 | RCT_REMAP_METHOD(getOpenPort,
187 | getOpenPort:(NSString*) address
188 | resolve:(RCTPromiseResolveBlock)resolve
189 | reject:(RCTPromiseRejectBlock)reject
190 | ) {
191 | @try {
192 | int sockfd = socket(AF_INET, SOCK_STREAM, 0);
193 | if (sockfd < 0) {
194 | [[RNSSException name:@"Error creating socket"] reject:reject];
195 | return;
196 | }
197 |
198 | struct sockaddr_in serv_addr;
199 | memset(&serv_addr, 0, sizeof(serv_addr));
200 | serv_addr.sin_family = AF_INET;
201 | serv_addr.sin_port = 0;
202 | if (!inet_aton([address cStringUsingEncoding:NSUTF8StringEncoding], &(serv_addr.sin_addr))) {
203 | [[RNSSException name:@"Invalid address format"] reject:reject];
204 | return;
205 | }
206 |
207 | if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
208 | [[RNSSException name:@"Error binding socket"] reject:reject];
209 | return;
210 | }
211 |
212 | socklen_t len = sizeof(serv_addr);
213 | if (getsockname(sockfd, (struct sockaddr *) &serv_addr, &len) < 0) {
214 | [[RNSSException name:@"Error getting socket name"] reject:reject];
215 | return;
216 | }
217 | int port = ntohs(serv_addr.sin_port);
218 |
219 | close(sockfd);
220 | resolve(@(port));
221 | }
222 | @catch (NSException *e) {
223 | [[RNSSException from:e] reject:reject];
224 | }
225 | }
226 |
227 | - (void) startObserving {
228 | // NOOP: Triggered when the first listener from JS side is added.
229 | }
230 |
231 | - (void) stopObserving {
232 | // NOOP: Triggered when the last listener from JS side is removed.
233 | }
234 |
235 | + (BOOL)requiresMainQueueSetup
236 | {
237 | return NO;
238 | }
239 |
240 | - (std::shared_ptr)getTurboModule:
241 | (const facebook::react::ObjCTurboModule::InitParams &)params
242 | {
243 | return std::make_shared(params);
244 | }
245 |
246 | @end
247 |
--------------------------------------------------------------------------------
/ios/Server.h:
--------------------------------------------------------------------------------
1 | static NSString * const CRASHED = @"CRASHED";
2 | static NSString * const LAUNCHED = @"LAUNCHED";
3 | static NSString * const TERMINATED = @"TERMINATED";
4 |
5 | typedef void (^SignalConsumer)(NSString * const signal, NSString * const details);
6 |
7 | @interface Server : NSThread
8 | - (void) cancel;
9 | - (void) main;
10 |
11 | + (Server*) serverWithId:(NSNumber*)serverId
12 | configPath:(NSString*)configPath
13 | errlogPath:(NSString*)errlogPath
14 | signalConsumer:(SignalConsumer)signalConsumer;
15 |
16 | @property (readonly) NSNumber *serverId;
17 | @property SignalConsumer signalConsumer;
18 | @end
19 |
--------------------------------------------------------------------------------
/ios/Server.mm:
--------------------------------------------------------------------------------
1 | #import "Server.h"
2 |
3 | Server *activeServer;
4 |
5 | void onLaunchedCallback() {
6 | activeServer.signalConsumer(LAUNCHED, nil);
7 | }
8 |
9 | extern "C" {
10 | int lighttpd_launch(
11 | const char * config_path,
12 | const char * module_path,
13 | const char * errlog_path,
14 | void (*cb)()
15 | );
16 |
17 | void lighttpd_graceful_shutdown();
18 | }
19 |
20 | @implementation Server {
21 | NSString *configPath;
22 | NSString *errlogPath;
23 | }
24 |
25 | - (id) initWithServerId:(NSNumber*)serverId
26 | configPath:(NSString*)configPath
27 | errlogPath:(NSString*)errlogPath
28 | signalConsumer:(SignalConsumer)signalConsumer
29 | {
30 | self = [super init];
31 | self->_serverId = serverId;
32 | self->configPath = configPath;
33 | self->errlogPath = errlogPath;
34 | self.signalConsumer = signalConsumer;
35 | return self;
36 | }
37 |
38 | - (void) cancel {
39 | NSLog(@"Server.cancel() triggered");
40 | lighttpd_graceful_shutdown();
41 | [super cancel];
42 | }
43 |
44 | - (void) main {
45 | NSLog(@"Server.main() triggered");
46 |
47 | if (activeServer) {
48 | NSString *msg = @"Another Server instance is active";
49 | NSLog(@"%@", msg);
50 | self.signalConsumer(CRASHED, msg);
51 | return;
52 | }
53 |
54 | @try {
55 | activeServer = self;
56 | int res = lighttpd_launch(
57 | [self->configPath cStringUsingEncoding:NSASCIIStringEncoding],
58 | nil,
59 | [self->errlogPath cStringUsingEncoding:NSASCIIStringEncoding],
60 | onLaunchedCallback
61 | );
62 | if (res) [NSException raise:@"Server exited with error" format:@"%d", res];
63 |
64 | activeServer = NULL;
65 |
66 | NSLog(@"Server terminated gracefully");
67 | self.signalConsumer(TERMINATED, nil);
68 | }
69 | @catch (NSException *error) {
70 | activeServer = NULL;
71 | NSLog(@"Server crashed %@", error.name);
72 | self.signalConsumer(CRASHED, error.name);
73 | }
74 | }
75 |
76 | + (Server*) serverWithId:(NSNumber*)serverId
77 | configPath:(NSString*)configPath
78 | errlogPath:(NSString*)errlogPath
79 | signalConsumer:(SignalConsumer)signalConsumer
80 | {
81 | return [[Server alloc]
82 | initWithServerId:serverId
83 | configPath:configPath
84 | errlogPath:errlogPath
85 | signalConsumer:signalConsumer];
86 | }
87 |
88 | @end
89 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@dr.pogodin/react-native-static-server",
3 | "version": "0.21.0",
4 | "description": "Embedded HTTP server for React Native",
5 | "source": "./src/index.tsx",
6 | "main": "./lib/module/index.js",
7 | "types": "./lib/typescript/src/index.d.ts",
8 | "exports": {
9 | ".": {
10 | "types": "./lib/typescript/src/index.d.ts",
11 | "default": "./lib/module/index.js"
12 | },
13 | "./package.json": "./package.json"
14 | },
15 | "scripts": {
16 | "codegen-windows": "./node_modules/.bin/rnc-cli codegen-windows",
17 | "example": "yarn workspace @dr.pogodin/react-native-static-server-example",
18 | "test": "yarn lint && yarn typecheck",
19 | "typecheck": "tsc",
20 | "lint": "eslint \"**/*.{js,ts,tsx}\"",
21 | "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
22 | "prepare": "bob build"
23 | },
24 | "keywords": [
25 | "react-native",
26 | "ios",
27 | "android",
28 | "lighttpd",
29 | "windows",
30 | "embed",
31 | "server",
32 | "http",
33 | "https",
34 | "react"
35 | ],
36 | "repository": {
37 | "type": "git",
38 | "url": "git+https://github.com/birdofpreyru/react-native-static-server.git"
39 | },
40 | "author": "Dr. Sergey Pogodin (https://dr.pogodin.studio)",
41 | "license": "MIT",
42 | "licenseFilename": "LICENSE.md",
43 | "readmeFilename": "README.md",
44 | "bugs": {
45 | "url": "https://github.com/birdofpreyru/react-native-static-server/issues"
46 | },
47 | "homepage": "https://dr.pogodin.studio/docs/react-native-static-server",
48 | "title": "React Native Static Server",
49 | "funding": {
50 | "type": "github",
51 | "url": "https://github.com/sponsors/birdofpreyru"
52 | },
53 | "publishConfig": {
54 | "registry": "https://registry.npmjs.org/"
55 | },
56 | "devDependencies": {
57 | "@dr.pogodin/react-native-fs": "^2.33.1",
58 | "@eslint/compat": "^1.2.8",
59 | "@eslint/eslintrc": "^3.3.1",
60 | "@eslint/js": "^9.25.1",
61 | "@react-native-community/cli": "18.0.0",
62 | "@react-native/eslint-config": "^0.79.1",
63 | "@types/jest": "^29.5.14",
64 | "@types/react": "^19.0.12",
65 | "del-cli": "^6.0.0",
66 | "eslint": "^9.25.1",
67 | "jest": "^29.7.0",
68 | "react": "19.0.0",
69 | "react-native": "0.79.1",
70 | "react-native-builder-bob": "^0.40.6",
71 | "react-native-windows": "^0.78.5",
72 | "typescript": "^5.8.3"
73 | },
74 | "peerDependencies": {
75 | "@dr.pogodin/react-native-fs": ">= 2.22.0",
76 | "react": "*",
77 | "react-native": "*",
78 | "react-native-windows": "*"
79 | },
80 | "workspaces": [
81 | "example"
82 | ],
83 | "packageManager": "yarn@4.9.1",
84 | "jest": {
85 | "preset": "react-native",
86 | "modulePathIgnorePatterns": [
87 | "/example/node_modules",
88 | "/lib/"
89 | ]
90 | },
91 | "react-native-builder-bob": {
92 | "source": "src",
93 | "output": "lib",
94 | "targets": [
95 | "codegen",
96 | [
97 | "module",
98 | {
99 | "esm": true
100 | }
101 | ],
102 | [
103 | "typescript",
104 | {
105 | "project": "tsconfig.build.json"
106 | }
107 | ]
108 | ]
109 | },
110 | "codegenConfig": {
111 | "name": "RNReactNativeStaticServerSpec",
112 | "type": "modules",
113 | "jsSrcsDir": "src",
114 | "windows": {
115 | "namespace": "winrt::ReactNativeStaticServer",
116 | "outputDirectory": "windows/ReactNativeStaticServer/codegen"
117 | },
118 | "outputDir": {
119 | "ios": "ios/generated",
120 | "android": "android/generated"
121 | },
122 | "android": {
123 | "javaPackageName": "com.drpogodin.reactnativestaticserver"
124 | },
125 | "includesGeneratedCode": true
126 | },
127 | "dependencies": {
128 | "@dr.pogodin/js-utils": "^0.0.17"
129 | },
130 | "create-react-native-library": {
131 | "type": "turbo-module",
132 | "languages": "kotlin-objc",
133 | "version": "0.49.8"
134 | },
135 | "react-native-windows": {
136 | "init-windows": {
137 | "name": "ReactNativeStaticServer",
138 | "namespace": "ReactNativeStaticServer",
139 | "template": "old/uwp-cpp-lib"
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/react-native.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {import('@react-native-community/cli-types').UserDependencyConfig}
3 | */
4 | module.exports = {
5 | dependency: {
6 | platforms: {
7 | android: {
8 | cmakeListsPath: 'generated/jni/CMakeLists.txt',
9 | },
10 | },
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/src/NativeReactNativeStaticServer.ts:
--------------------------------------------------------------------------------
1 | import type { TurboModule } from 'react-native';
2 | import { TurboModuleRegistry } from 'react-native';
3 |
4 | export interface Spec extends TurboModule {
5 | readonly getConstants: () => {
6 | CRASHED: string;
7 | IS_MAC_CATALYST: boolean;
8 | LAUNCHED: string;
9 | TERMINATED: string;
10 | };
11 |
12 | addListener(eventName: string): void;
13 |
14 | getActiveServerId(): Promise;
15 |
16 | removeListeners(count: number): void;
17 |
18 | start(id: number, configPath: string, errlogPath: string): Promise;
19 |
20 | // TODO: Instead of implementing these methods in native code ourselves,
21 | // we probably can use `@react-native-community/netinfo` library to retrieve
22 | // local IP address and a random open port (thus a bit less native code
23 | // to maintain ourselves in this library).
24 | getLocalIpAddress(): Promise;
25 |
26 | getOpenPort(address: string): Promise;
27 | stop(): Promise;
28 | }
29 |
30 | export default TurboModuleRegistry.getEnforcing('ReactNativeStaticServer');
31 |
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
1 | // Encapsulates the standard Lighttpd configuration for the library.
2 |
3 | import {
4 | mkdir,
5 | TemporaryDirectoryPath,
6 | writeFile,
7 | } from '@dr.pogodin/react-native-fs';
8 |
9 | /**
10 | * Filesystem location where the library will keep its working files (configs,
11 | * logs, uploads) for the app.
12 | */
13 | export const WORK_DIR = `${TemporaryDirectoryPath}/__rn-static-server__`;
14 |
15 | /**
16 | * Filesystem location for the error log file.
17 | */
18 | export const ERROR_LOG_FILE = `${WORK_DIR}/errorlog.txt`;
19 |
20 | /**
21 | * Filesystem locations where the library will keep uploads for the app.
22 | */
23 | export const UPLOADS_DIR = `${WORK_DIR}/uploads`;
24 |
25 | /**
26 | * Options for error log, they mirror debug options of Lighttpd config:
27 | * https://redmine.lighttpd.net/projects/lighttpd/wiki/DebugVariables
28 | */
29 | export type ErrorLogOptions = {
30 | conditionHandling?: boolean;
31 | fileNotFound?: boolean;
32 | requestHandling?: boolean;
33 | requestHeader?: boolean;
34 | requestHeaderOnError?: boolean;
35 | responseHeader?: boolean;
36 |
37 | // "debug.log-ssl-noise" is recognized by Lighttpd only when the Lighttpd TLS
38 | // module is loaded, otherwise it is reported as an unknown config key. As we
39 | // don't use TLS module currently, let's remove this option, at least for now.
40 | // See: https://github.com/birdofpreyru/react-native-static-server/issues/59#issuecomment-1646752111
41 | // sslNoise?: boolean;
42 |
43 | timeouts?: boolean;
44 | };
45 |
46 | /**
47 | * Options for the standard Lighttpd configuration for the library.
48 | */
49 | export type StandardConfigOptions = {
50 | errorLog?: ErrorLogOptions;
51 | extraConfig: string;
52 | fileDir: string;
53 | hostname: string;
54 | port: number;
55 | webdav?: string[]; // DEPRECATED
56 | };
57 |
58 | /**
59 | * Generates a fragment of Lighttpd config related to error and debug logging.
60 | * @param errorLogOptions
61 | * @returns
62 | */
63 | function errorLogConfig(errorLogOptions?: ErrorLogOptions): string {
64 | const res = [];
65 |
66 | if (errorLogOptions) {
67 | const ops: ErrorLogOptions = errorLogOptions;
68 | const enable = (op: string) => {
69 | res.push(`debug.log-${op} = "enable"`);
70 | };
71 | if (ops.conditionHandling) enable('condition-handling');
72 | if (ops.fileNotFound) enable('file-not-found');
73 | if (ops.requestHandling) enable('request-handling');
74 | if (ops.requestHeader) enable('request-header');
75 | if (ops.requestHeaderOnError) enable('request-header-on-error');
76 | if (ops.responseHeader) enable('response-header');
77 |
78 | // Not a valid option, without TLS module (see more details in a comment
79 | // earlier in the file).
80 | // if (ops.sslNoise) enable('ssl-noise');
81 |
82 | if (ops.timeouts) enable('timeouts');
83 | } else res.push('server.errorlog-use-syslog = "enable"');
84 |
85 | return res.join('\n');
86 | }
87 |
88 | /**
89 | * Generates the standard Lighttpd config.
90 | * @param param0
91 | * @returns
92 | */
93 | function standardConfig({
94 | errorLog,
95 | extraConfig,
96 | fileDir,
97 | hostname,
98 | port,
99 | webdav, // DEPRECATED
100 | }: StandardConfigOptions) {
101 | let webdavConfig = '';
102 | if (webdav) {
103 | webdavConfig += 'server.modules += ("mod_webdav")';
104 | for (let i = 0; i < webdav.length; ++i) {
105 | webdavConfig += `$HTTP["url"] =~ "${webdav[i]}" { webdav.activate = "enable" }`;
106 | }
107 | }
108 |
109 | return `server.document-root = "${fileDir}"
110 | server.bind = "${hostname}"
111 | server.upload-dirs = ( "${UPLOADS_DIR}" )
112 | server.port = ${port}
113 | ${errorLogConfig(errorLog)}
114 | index-file.names += ("index.xhtml", "index.html", "index.htm", "default.htm", "index.php")
115 |
116 | ${webdavConfig}
117 | ${extraConfig}`;
118 | }
119 |
120 | /**
121 | * Creates a new file with the standard Lighttpd configuration in the WORK_DIR,
122 | * and returns resolves to its path.
123 | * @param fileDir
124 | * @param hostname
125 | * @param port
126 | * @return {Promise} Resolves to the name of the created config file.
127 | */
128 | export async function newStandardConfigFile(
129 | options: StandardConfigOptions,
130 | ): Promise {
131 | // NOTE: Lighttpd exits with error right away if the specified uploads
132 | // directory does not exist.
133 | await mkdir(UPLOADS_DIR);
134 |
135 | const configFile = `${WORK_DIR}/config-${Date.now()}.txt`;
136 | await writeFile(configFile, standardConfig(options), 'utf8');
137 | return configFile;
138 | }
139 |
--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------
1 | // Imports internal constants defined within the native layer,
2 | // and exports user-facing constants for server states.
3 |
4 | import ReactNativeStaticServer from './NativeReactNativeStaticServer';
5 |
6 | const CONSTANTS = ReactNativeStaticServer.getConstants();
7 |
8 | export const IS_MAC_CATALYST = CONSTANTS.IS_MAC_CATALYST;
9 |
10 | export const SIGNALS = {
11 | CRASHED: CONSTANTS.CRASHED,
12 | LAUNCHED: CONSTANTS.LAUNCHED,
13 | TERMINATED: CONSTANTS.TERMINATED,
14 | };
15 |
16 | export enum STATES {
17 | ACTIVE,
18 | CRASHED,
19 | INACTIVE,
20 | STARTING,
21 | STOPPING,
22 | }
23 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import { Platform } from 'react-native';
2 |
3 | import {
4 | DocumentDirectoryPath,
5 | MainBundlePath,
6 | } from '@dr.pogodin/react-native-fs';
7 |
8 | import { IS_MAC_CATALYST } from './constants';
9 |
10 | type PLATFORM = 'ANDROID' | 'IOS' | 'MACOS' | 'WINDOWS';
11 |
12 | function getPlatform(): PLATFORM {
13 | switch (Platform.OS) {
14 | case 'android':
15 | return 'ANDROID';
16 | case 'ios':
17 | return IS_MAC_CATALYST ? 'MACOS' : 'IOS';
18 | case 'windows':
19 | return 'WINDOWS';
20 | default:
21 | throw Error(`Unsupported platform ${Platform.OS}`);
22 | }
23 | }
24 |
25 | const PLATFORM: PLATFORM = getPlatform();
26 |
27 | const BASE_ASSET_DIRS: { [key in typeof PLATFORM]: string } = {
28 | ANDROID: DocumentDirectoryPath,
29 | IOS: MainBundlePath || '',
30 | MACOS: `${MainBundlePath}/Contents/Resources`,
31 | WINDOWS: MainBundlePath || '',
32 | };
33 |
34 | const BASE_ASSET_DIR = BASE_ASSET_DIRS[PLATFORM];
35 |
36 | const SEP = PLATFORM === 'WINDOWS' ? '\\' : '/';
37 |
38 | /**
39 | * Returns `true` if given path is absolute, `false` otherwise.
40 | * @param {string} path
41 | * @return {boolean}
42 | */
43 | function isAbsolutePath(path: string): boolean {
44 | if (!path) return false;
45 |
46 | if (Platform.OS === 'windows') {
47 | return !!path.match(/^[a-zA-Z]:\\/);
48 | }
49 |
50 | // This should do for Android and iOS.
51 | return path.startsWith('/') || path.startsWith('file:///');
52 | }
53 |
54 | /**
55 | * If given `path` is relative, it returns the corresponding absolute path,
56 | * resolved relative to the platform-specific base location for bundled assets;
57 | * otherwise, it just returns given absolute path as is.
58 | * @param path Absolute or relative path.
59 | * @return Absolute path.
60 | */
61 | export function resolveAssetsPath(path: string): string {
62 | return isAbsolutePath(path) ? path : `${BASE_ASSET_DIR}${SEP}${path}`;
63 | }
64 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "exclude": ["example", "lib"]
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": ".",
4 | "paths": {
5 | "@dr.pogodin/react-native-static-server": ["./src/index"]
6 | },
7 | "allowUnreachableCode": false,
8 | "allowUnusedLabels": false,
9 | "esModuleInterop": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "jsx": "react-jsx",
12 | "lib": ["ESNext"],
13 | "module": "ESNext",
14 | "moduleResolution": "bundler",
15 | "noEmit": true,
16 | "noFallthroughCasesInSwitch": true,
17 | "noImplicitReturns": true,
18 | "noImplicitUseStrict": false,
19 | "noStrictGenericChecks": false,
20 | "noUncheckedIndexedAccess": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "resolveJsonModule": true,
24 | "skipLibCheck": true,
25 | "strict": true,
26 | "target": "ESNext",
27 | "verbatimModuleSyntax": true
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/windows/.gitignore:
--------------------------------------------------------------------------------
1 | *AppPackages*
2 | *BundleArtifacts*
3 |
4 | #OS junk files
5 | [Tt]humbs.db
6 | *.DS_Store
7 |
8 | #Visual Studio files
9 | *.[Oo]bj
10 | *.user
11 | *.aps
12 | *.pch
13 | *.vspscc
14 | *.vssscc
15 | *_i.c
16 | *_p.c
17 | *.ncb
18 | *.suo
19 | *.tlb
20 | *.tlh
21 | *.bak
22 | *.[Cc]ache
23 | *.ilk
24 | *.log
25 | *.lib
26 | *.sbr
27 | *.sdf
28 | *.opensdf
29 | *.opendb
30 | *.unsuccessfulbuild
31 | ipch/
32 | [Oo]bj/
33 | [Bb]in
34 | [Dd]ebug*/
35 | [Rr]elease*/
36 | Ankh.NoLoad
37 |
38 | # Visual C++ cache files
39 | ipch/
40 | *.aps
41 | *.ncb
42 | *.opendb
43 | *.opensdf
44 | *.sdf
45 | *.cachefile
46 | *.VC.db
47 | *.VC.VC.opendb
48 |
49 | #MonoDevelop
50 | *.pidb
51 | *.userprefs
52 |
53 | #Tooling
54 | _ReSharper*/
55 | *.resharper
56 | [Tt]est[Rr]esult*
57 | *.sass-cache
58 |
59 | #Project files
60 | [Bb]uild/
61 |
62 | #Subversion files
63 | .svn
64 |
65 | # Office Temp Files
66 | ~$*
67 |
68 | # vim Temp Files
69 | *~
70 |
71 | #NuGet
72 | packages/
73 | *.nupkg
74 |
75 | #ncrunch
76 | *ncrunch*
77 | *crunch*.local.xml
78 |
79 | # visual studio database projects
80 | *.dbmdl
81 |
82 | #Test files
83 | *.testsettings
84 |
85 | #Other files
86 | *.DotSettings
87 | .vs/
88 | *project.lock.json
89 |
90 | #Files generated by the VS build
91 | **/Generated Files/**
92 |
93 |
--------------------------------------------------------------------------------
/windows/ExperimentalFeatures.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
17 | true
18 |
19 |
26 | false
27 |
28 | true
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/windows/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/Errors.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Errors.h"
4 |
5 | RNException::RNException(std::string && message) {
6 | this->Message = std::move(message);
7 | }
8 |
9 | const char* RNException::what() {
10 | return this->Message.c_str();
11 | }
12 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/Errors.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "NativeModules.h"
5 |
6 | using namespace winrt::Microsoft::ReactNative;
7 |
8 | class RNException : public std::exception, public ReactError {
9 | public:
10 | // TODO: ReactError also has Code (string) and UserInfo (JSValueObject)
11 | // fields, we may accept here, and use. For now, just getting message is ok.
12 | RNException(std::string && message);
13 |
14 | virtual const char* what();
15 |
16 | template
17 | void reject(ReactPromise& promise);
18 | };
19 |
20 | template
21 | void RNException::reject(ReactPromise& promise) {
22 | promise.Reject(*this);
23 | }
24 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/PropertySheet.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/ReactNativeModule.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ReactNativeModule.h"
3 | #include
4 |
5 | #include
6 | #include
7 |
8 | #include "Errors.h"
9 | #include "Server.h"
10 |
11 | using namespace std::chrono_literals;
12 | using namespace winrt::ReactNativeStaticServer;
13 | using namespace winrt::Windows::Networking::Connectivity;
14 |
15 | ReactNativeModule* mod;
16 | React::ReactPromise* pendingResult;
17 | Server *server;
18 |
19 | // There is no semaphore in C++ STL prior to C++20,
20 | // thus we have to make it ourselves.
21 | boolean sem = true;
22 | std::mutex sem_guard;
23 | std::condition_variable sem_cv;
24 |
25 | void lock_sem() {
26 | std::unique_lock lk(sem_guard);
27 | sem_cv.wait(lk, [] { return sem; });
28 | sem = false;
29 | }
30 |
31 | void unlock_sem() {
32 | std::lock_guard lk(sem_guard);
33 | if (sem) throw std::exception("Internal synchronization error");
34 | sem = true;
35 | sem_cv.notify_one();
36 | }
37 |
38 | void OnSignal(std::string signal, std::string details) {
39 | // BEWARE: .sendEvent() depends on the server object to get its ID,
40 | // thus MUST BE called before the object is dropped below, if it is.
41 | if (!pendingResult) mod->sendEvent(signal, details);
42 |
43 | double id = server->id();
44 | if (signal == CRASHED || signal == TERMINATED) {
45 | delete server;
46 | server = NULL;
47 | }
48 |
49 | if (pendingResult) {
50 | if (signal == CRASHED) {
51 | RNException("Server #" + std::to_string(id) + " crashed").reject(*pendingResult);
52 | }
53 | else pendingResult->Resolve(details);
54 | delete pendingResult;
55 | pendingResult = NULL;
56 | unlock_sem();
57 | }
58 | }
59 |
60 | ReactNativeStaticServerSpec_Constants ReactNativeModule::GetConstants() noexcept {
61 | ReactNativeStaticServerSpec_Constants res;
62 | res.CRASHED = CRASHED;
63 | res.IS_MAC_CATALYST = false;
64 | res.LAUNCHED = LAUNCHED;
65 | res.TERMINATED = TERMINATED;
66 | return res;
67 | }
68 |
69 | void ReactNativeModule::getActiveServerId(React::ReactPromise>&& result) noexcept {
70 | result.Resolve(server ? std::optional(server->id()) : std::nullopt);
71 | }
72 |
73 | void ReactNativeModule::getLocalIpAddress(React::ReactPromise&& result) noexcept {
74 | try {
75 | auto hosts = NetworkInformation::GetHostNames();
76 | for (winrt::Windows::Networking::HostName host: hosts) {
77 | if (host.Type() == winrt::Windows::Networking::HostNameType::Ipv4) {
78 | auto network = host.IPInformation().NetworkAdapter();
79 | int32_t netType = network.IanaInterfaceType();
80 | // TODO: This needs second thoughts, and a lot of testing.
81 | // The current values 6 & 72 mean "either Ethernet network,
82 | // or IEEE 802.11 wireless network interface", see:
83 | // https://learn.microsoft.com/en-us/uwp/api/windows.networking.connectivity.networkadapter.ianainterfacetype?view=winrt-22621#property-value
84 | // For now we just pick up the first IP for such connected
85 | // network, but we probably should give library consumer
86 | // control over what network is selected, and stuff (there
87 | // are related tickets for other os).
88 | if (netType == 6 || netType == 71) {
89 | // TODO: Here we can use network.GetConnectedProfileAsync()
90 | // to get more info about the current connection status,
91 | // but for now just let return the first IP we found.
92 | return result.Resolve(winrt::to_string(host.CanonicalName()));
93 | }
94 | }
95 | }
96 | }
97 | catch (...) {
98 | // NOOP
99 | }
100 | RNException("Failed to get a non-local IP address").reject(result);
101 | }
102 |
103 | void ReactNativeModule::getOpenPort(
104 | std::string address,
105 | React::ReactPromise&& result
106 | ) noexcept {
107 | try {
108 | auto socket = winrt::Windows::Networking::Sockets::StreamSocketListener();
109 | // TODO: This will fail if nor InternetClientServer neither PrivateNetworkClientServer
110 | // capability is granted to the app. The error messaging should be improved, to make it
111 | // clear to the library consumer why the failure happened.
112 | winrt::Windows::Networking::HostName hostname(winrt::to_hstring(address));
113 | if (socket.BindEndpointAsync(hostname, L"").wait_for(5s) != AsyncStatus::Completed) {
114 | return RNException("Binding time out").reject(result);
115 | }
116 | double port = std::stod(winrt::to_string(socket.Information().LocalPort()));
117 | socket.Close();
118 | return result.Resolve(port);
119 | }
120 | catch (...) {
121 | // NOOP
122 | }
123 | RNException("Failed to get an open port").reject(result);
124 | }
125 |
126 | void ReactNativeModule::sendEvent(std::string signal, std::string details) {
127 | JSValueObject obj = JSValueObject{
128 | {"serverId", server->id()},
129 | {"event", signal},
130 | {"details", details}
131 | };
132 | this->EmitEvent(std::move(obj));
133 | }
134 |
135 | void ReactNativeModule::start(
136 | double id,
137 | std::string configPath,
138 | std::string errlogPath,
139 | React::ReactPromise&& result
140 | ) noexcept {
141 | lock_sem();
142 |
143 | if (server) {
144 | RNException(
145 | "Failed to launch server #" + std::to_string(id) +
146 | ", another server instance (#" + server->id_str() + ") is active").reject(result);
147 | unlock_sem();
148 | return;
149 | };
150 |
151 | if (pendingResult) {
152 | RNException("Internal error").reject(result);
153 | unlock_sem();
154 | return;
155 | }
156 |
157 | mod = this;
158 | pendingResult = new React::ReactPromise(result);
159 | server = new Server(id, configPath, errlogPath, OnSignal);
160 | server->launch();
161 | }
162 |
163 | void ReactNativeModule::stop(React::ReactPromise&& result) noexcept {
164 | try {
165 | lock_sem();
166 |
167 | // The synchronization in JS layer is supposed to ensure this native
168 | // .stop() is never called before any previous pendingResult is settled
169 | // and cleaned up.
170 | if (pendingResult) {
171 | unlock_sem();
172 | RNException("Internal error").reject(result);
173 | return;
174 | }
175 |
176 | // This means either the server has crashed at the same time we were
177 | // about to ask it to gracefully shutdown, or there is some error in
178 | // JS layer, which is not supposed to call this native .stop() unless
179 | // an active server instance exists.
180 | if (!server) {
181 | RNException("No active server").reject(result);
182 | unlock_sem();
183 | return;
184 | }
185 |
186 | pendingResult = new React::ReactPromise(result);
187 | server->shutdown();
188 |
189 | // The OnSignal() handler will dispose the server once TERMINATED,
190 | // or CRASHED signal is received, and it will settle and clean up
191 | // pendingPromise; anything else going wrong, the try/catch block
192 | // will catch it and report to JS layer in RN way.
193 | }
194 | catch (...) {
195 | RNException("Failed to gracefully shutdown the server #" + server->id_str()).reject(result);
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/ReactNativeModule.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "codegen/NativeReactNativeStaticServerSpec.g.h"
4 |
5 | #include "JSValue.h"
6 | #include "NativeModules.h"
7 |
8 | using namespace winrt::Microsoft::ReactNative;
9 |
10 | namespace winrt::ReactNativeStaticServer
11 | {
12 |
13 | REACT_MODULE(ReactNativeModule, L"ReactNativeStaticServer")
14 | struct ReactNativeModule
15 | {
16 | using ModuleSpec = ReactNativeStaticServerSpec;
17 |
18 | REACT_GET_CONSTANTS(GetConstants)
19 | ReactNativeStaticServerSpec_Constants GetConstants() noexcept;
20 |
21 | REACT_METHOD(addListener)
22 | void addListener(std::string eventName) noexcept {
23 | // NOOP
24 | }
25 |
26 | REACT_METHOD(removeListeners)
27 | void removeListeners(double count) noexcept {
28 | // NOOP
29 | }
30 |
31 | REACT_EVENT(EmitEvent, L"RNStaticServer");
32 | std::function EmitEvent;
33 |
34 | void sendEvent(std::string signal, std::string details);
35 |
36 | REACT_METHOD(getActiveServerId)
37 | void getActiveServerId(React::ReactPromise>&& result) noexcept;
38 |
39 | REACT_METHOD(getLocalIpAddress)
40 | void getLocalIpAddress(React::ReactPromise&& result) noexcept;
41 |
42 | REACT_METHOD(getOpenPort)
43 | void getOpenPort(std::string address, React::ReactPromise&& result) noexcept;
44 |
45 | REACT_METHOD(start)
46 | void start(double id,
47 | std::string configPath,
48 | std::string errlogPath,
49 | React::ReactPromise&& result) noexcept;
50 |
51 | REACT_METHOD(stop)
52 | void stop(React::ReactPromise&& result) noexcept;
53 | };
54 |
55 | } // namespace winrt::ReactNativeStaticServer
56 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/ReactNativeStaticServer.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
4 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/ReactNativeStaticServer.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {ac89e086-a7ef-46ed-8566-8e8bbcc1eab4}
28 |
29 |
30 |
31 |
32 | Lighttpd
33 |
34 |
35 | Lighttpd
36 |
37 |
38 | Lighttpd
39 |
40 |
41 | Lighttpd
42 |
43 |
44 | Lighttpd
45 |
46 |
47 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/ReactPackageProvider.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "ReactPackageProvider.h"
3 | #if __has_include("ReactPackageProvider.g.cpp")
4 | #include "ReactPackageProvider.g.cpp"
5 | #endif
6 |
7 | #include "ReactNativeModule.h"
8 |
9 | using namespace winrt::Microsoft::ReactNative;
10 |
11 | namespace winrt::ReactNativeStaticServer::implementation
12 | {
13 |
14 | void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept
15 | {
16 | AddAttributedModules(packageBuilder, true);
17 | }
18 |
19 | } // namespace winrt::ReactNativeStaticServer::implementation
20 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/ReactPackageProvider.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "ReactPackageProvider.g.h"
3 |
4 | using namespace winrt::Microsoft::ReactNative;
5 |
6 | namespace winrt::ReactNativeStaticServer::implementation
7 | {
8 | struct ReactPackageProvider : ReactPackageProviderT
9 | {
10 | ReactPackageProvider() = default;
11 |
12 | void CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept;
13 | };
14 | } // namespace winrt::ReactNativeStaticServer::implementation
15 |
16 | namespace winrt::ReactNativeStaticServer::factory_implementation
17 | {
18 |
19 | struct ReactPackageProvider : ReactPackageProviderT {};
20 |
21 | } // namespace winrt::ReactNativeStaticServer::factory_implementation
22 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/ReactPackageProvider.idl:
--------------------------------------------------------------------------------
1 | namespace ReactNativeStaticServer
2 | {
3 | [webhosthidden]
4 | [default_interface]
5 | runtimeclass ReactPackageProvider : Microsoft.ReactNative.IReactPackageProvider
6 | {
7 | ReactPackageProvider();
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/Server.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Server.h"
3 | #include
4 |
5 | using namespace winrt::ReactNativeStaticServer;
6 | using namespace winrt::Windows::ApplicationModel;
7 | using namespace winrt::Windows::Storage;
8 |
9 | typedef void (*CallbackT)();
10 |
11 | typedef int (*LighttpdLaunchT)(
12 | const char *configPath,
13 | const char *modulesPath,
14 | const char *errlogPath,
15 | CallbackT
16 | );
17 |
18 | typedef void (*LighttpdShutdownT)();
19 |
20 | LighttpdLaunchT LighttpdLaunch;
21 | LighttpdShutdownT LighttpdShutdown;
22 |
23 | Server* Server::activeServer;
24 |
25 | void LoadLighttpdDll() {
26 | LoadPackagedLibrary(L"ReactNativeStaticServer\\libpcre2-8.dll", 0);
27 | LoadPackagedLibrary(L"ReactNativeStaticServer\\libwinpthread-1.dll", 0);
28 | HMODULE dll = LoadPackagedLibrary(L"ReactNativeStaticServer\\lighttpd.dll", 0);
29 | if (dll) {
30 | LighttpdLaunch = (LighttpdLaunchT)GetProcAddress(dll, "lighttpd_launch");
31 | LighttpdShutdown = (LighttpdShutdownT)GetProcAddress(dll, "lighttpd_graceful_shutdown");
32 | }
33 | else {
34 | // The DLLs we tried to import above are pre-build and bundled into
35 | // an UWP app by this library, so failure to locate and load them is
36 | // a fatal crash, meaning there is something wrong with our library,
37 | // and we terminate the app in such case.
38 | //
39 | // NOTE: The next few lines retrieve the failure cause, but don't forward it anywhere,
40 | // for now they can be seen in debugger.
41 | DWORD errcode = GetLastError();
42 | LPSTR errmsg = nullptr;
43 | FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
44 | NULL, errcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)& errmsg, 0, NULL);
45 |
46 | terminate();
47 | }
48 | }
49 |
50 | void Server::OnLaunchedCallback() {
51 | Server::activeServer->_signalConsumer(LAUNCHED, "");
52 | }
53 |
54 | Server::Server(
55 | double id,
56 | std::string configPath,
57 | std::string errlogPath,
58 | SignalConsumer signalConsumer
59 | ):
60 | _id(id),
61 | _configPath(configPath),
62 | _errlogPath(errlogPath),
63 | _signalConsumer(signalConsumer)
64 | {
65 | if (!LighttpdLaunch) LoadLighttpdDll();
66 | }
67 |
68 | void Server::launch() {
69 | concurrency::task task = concurrency::create_task(
70 | [this] {
71 | if (Server::activeServer) {
72 | // Bail out with error if another server instance is running.
73 | this->_signalConsumer(CRASHED, "Another Server instance is active");
74 | return;
75 | }
76 | winrt::hstring appPath = Package::Current().InstalledLocation().Path();
77 | std::string modulesPath(appPath.begin(), appPath.end());
78 | modulesPath += "\\ReactNativeStaticServer";
79 | try {
80 | Server::activeServer = this;
81 | int res = LighttpdLaunch(
82 | this->_configPath.c_str(),
83 | modulesPath.c_str(),
84 | this->_errlogPath.c_str(),
85 | Server::OnLaunchedCallback
86 | );
87 | if (res) {
88 | throw new std::exception("Ligttpd exited with status " + res);
89 | }
90 | Server::activeServer = NULL;
91 | this->_signalConsumer(TERMINATED, "");
92 | }
93 | catch (...) {
94 | Server::activeServer = NULL;
95 | this->_signalConsumer(CRASHED, "");
96 | }
97 | }
98 | );
99 | }
100 |
101 | void Server::shutdown() {
102 | LighttpdShutdown();
103 | }
104 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/Server.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace winrt::ReactNativeStaticServer {
6 |
7 | static const std::string CRASHED = "CRASHED";
8 | static const std::string LAUNCHED = "LAUNCHED";
9 | static const std::string TERMINATED = "TERMINATED";
10 |
11 | typedef void (*SignalConsumer)(std::string signal, std::string details);
12 |
13 | class Server {
14 | public:
15 | Server(
16 | double id,
17 | std::string configPath,
18 | std::string errlogPath,
19 | SignalConsumer signalConsumer);
20 |
21 | inline double id() { return _id; }
22 | inline std::string id_str() { return std::to_string(_id); }
23 |
24 | void launch();
25 | void shutdown();
26 | private:
27 | double _id;
28 | std::string _configPath;
29 | std::string _errlogPath;
30 | SignalConsumer _signalConsumer;
31 |
32 | static Server* activeServer;
33 |
34 | static void OnLaunchedCallback();
35 | };
36 |
37 | } // namespace winrt::ReactNativeStaticServer
38 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/codegen/.clang-format:
--------------------------------------------------------------------------------
1 | DisableFormat: true
2 | SortIncludes: false
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/codegen/NativeReactNativeStaticServerSpec.g.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * This file is auto-generated from a NativeModule spec file in js.
4 | *
5 | * This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules
6 | * in a way that also verifies at compile time that the native module matches the interface required
7 | * by the TurboModule JS spec.
8 | */
9 | #pragma once
10 | // clang-format off
11 |
12 | #include
13 | #include
14 |
15 | namespace winrt::ReactNativeStaticServer {
16 |
17 | struct ReactNativeStaticServerSpec_Constants {
18 | std::string CRASHED;
19 | bool IS_MAC_CATALYST;
20 | std::string LAUNCHED;
21 | std::string TERMINATED;
22 | };
23 |
24 |
25 | inline winrt::Microsoft::ReactNative::FieldMap GetStructInfo(ReactNativeStaticServerSpec_Constants*) noexcept {
26 | winrt::Microsoft::ReactNative::FieldMap fieldMap {
27 | {L"CRASHED", &ReactNativeStaticServerSpec_Constants::CRASHED},
28 | {L"IS_MAC_CATALYST", &ReactNativeStaticServerSpec_Constants::IS_MAC_CATALYST},
29 | {L"LAUNCHED", &ReactNativeStaticServerSpec_Constants::LAUNCHED},
30 | {L"TERMINATED", &ReactNativeStaticServerSpec_Constants::TERMINATED},
31 | };
32 | return fieldMap;
33 | }
34 |
35 | struct ReactNativeStaticServerSpec : winrt::Microsoft::ReactNative::TurboModuleSpec {
36 | static constexpr auto constants = std::tuple{
37 | TypedConstant{0},
38 | };
39 | static constexpr auto methods = std::tuple{
40 | Method{0, L"addListener"},
41 | Method>) noexcept>{1, L"getActiveServerId"},
42 | Method{2, L"removeListeners"},
43 | Method) noexcept>{3, L"start"},
44 | Method) noexcept>{4, L"getLocalIpAddress"},
45 | Method) noexcept>{5, L"getOpenPort"},
46 | Method) noexcept>{6, L"stop"},
47 | };
48 |
49 | template
50 | static constexpr void ValidateModule() noexcept {
51 | constexpr auto constantCheckResults = CheckConstants();
52 | constexpr auto methodCheckResults = CheckMethods();
53 |
54 | REACT_SHOW_CONSTANT_SPEC_ERRORS(
55 | 0,
56 | "ReactNativeStaticServerSpec_Constants",
57 | " REACT_GET_CONSTANTS(GetConstants) ReactNativeStaticServerSpec_Constants GetConstants() noexcept {/*implementation*/}\n"
58 | " REACT_GET_CONSTANTS(GetConstants) static ReactNativeStaticServerSpec_Constants GetConstants() noexcept {/*implementation*/}\n");
59 |
60 | REACT_SHOW_METHOD_SPEC_ERRORS(
61 | 0,
62 | "addListener",
63 | " REACT_METHOD(addListener) void addListener(std::string eventName) noexcept { /* implementation */ }\n"
64 | " REACT_METHOD(addListener) static void addListener(std::string eventName) noexcept { /* implementation */ }\n");
65 | REACT_SHOW_METHOD_SPEC_ERRORS(
66 | 1,
67 | "getActiveServerId",
68 | " REACT_METHOD(getActiveServerId) void getActiveServerId(::React::ReactPromise> &&result) noexcept { /* implementation */ }\n"
69 | " REACT_METHOD(getActiveServerId) static void getActiveServerId(::React::ReactPromise> &&result) noexcept { /* implementation */ }\n");
70 | REACT_SHOW_METHOD_SPEC_ERRORS(
71 | 2,
72 | "removeListeners",
73 | " REACT_METHOD(removeListeners) void removeListeners(double count) noexcept { /* implementation */ }\n"
74 | " REACT_METHOD(removeListeners) static void removeListeners(double count) noexcept { /* implementation */ }\n");
75 | REACT_SHOW_METHOD_SPEC_ERRORS(
76 | 3,
77 | "start",
78 | " REACT_METHOD(start) void start(double id, std::string configPath, std::string errlogPath, ::React::ReactPromise &&result) noexcept { /* implementation */ }\n"
79 | " REACT_METHOD(start) static void start(double id, std::string configPath, std::string errlogPath, ::React::ReactPromise &&result) noexcept { /* implementation */ }\n");
80 | REACT_SHOW_METHOD_SPEC_ERRORS(
81 | 4,
82 | "getLocalIpAddress",
83 | " REACT_METHOD(getLocalIpAddress) void getLocalIpAddress(::React::ReactPromise &&result) noexcept { /* implementation */ }\n"
84 | " REACT_METHOD(getLocalIpAddress) static void getLocalIpAddress(::React::ReactPromise &&result) noexcept { /* implementation */ }\n");
85 | REACT_SHOW_METHOD_SPEC_ERRORS(
86 | 5,
87 | "getOpenPort",
88 | " REACT_METHOD(getOpenPort) void getOpenPort(std::string address, ::React::ReactPromise &&result) noexcept { /* implementation */ }\n"
89 | " REACT_METHOD(getOpenPort) static void getOpenPort(std::string address, ::React::ReactPromise &&result) noexcept { /* implementation */ }\n");
90 | REACT_SHOW_METHOD_SPEC_ERRORS(
91 | 6,
92 | "stop",
93 | " REACT_METHOD(stop) void stop(::React::ReactPromise &&result) noexcept { /* implementation */ }\n"
94 | " REACT_METHOD(stop) static void stop(::React::ReactPromise &&result) noexcept { /* implementation */ }\n");
95 | }
96 | };
97 |
98 | } // namespace winrt::ReactNativeStaticServer
99 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/lighttpd/lemon.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/windows/ReactNativeStaticServer/lighttpd/lemon.exe
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/lighttpd/libpcre2-8.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/windows/ReactNativeStaticServer/lighttpd/libpcre2-8.dll
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/lighttpd/libwinpthread-1.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/windows/ReactNativeStaticServer/lighttpd/libwinpthread-1.dll
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/lighttpd/lighttpd.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/windows/ReactNativeStaticServer/lighttpd/lighttpd.dll
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/lighttpd/mod_dirlisting.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/windows/ReactNativeStaticServer/lighttpd/mod_dirlisting.dll
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/lighttpd/mod_h2.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/windows/ReactNativeStaticServer/lighttpd/mod_h2.dll
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/lighttpd/mod_webdav.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birdofpreyru/react-native-static-server/bb30302f6de715d0e951d8fdaf7dd4b1240d09e5/windows/ReactNativeStaticServer/lighttpd/mod_webdav.dll
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/packages.lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "dependencies": {
4 | "native,Version=v0.0": {
5 | "Microsoft.UI.Xaml": {
6 | "type": "Direct",
7 | "requested": "[2.8.0, )",
8 | "resolved": "2.8.0",
9 | "contentHash": "vxdHxTr63s5KVtNddMFpgvjBjUH50z7seq/5jLWmmSuf8poxg+sXrywkofUdE8ZstbpO9y3FL/IXXUcPYbeesA==",
10 | "dependencies": {
11 | "Microsoft.Web.WebView2": "1.0.1264.42"
12 | }
13 | },
14 | "Microsoft.Windows.CppWinRT": {
15 | "type": "Direct",
16 | "requested": "[2.0.230706.1, )",
17 | "resolved": "2.0.230706.1",
18 | "contentHash": "l0D7oCw/5X+xIKHqZTi62TtV+1qeSz7KVluNFdrJ9hXsst4ghvqQ/Yhura7JqRdZWBXAuDS0G0KwALptdoxweQ=="
19 | },
20 | "boost": {
21 | "type": "Transitive",
22 | "resolved": "1.83.0",
23 | "contentHash": "cy53VNMzysEMvhBixDe8ujPk67Fcj3v6FPHQnH91NYJNLHpc6jxa2xq9ruCaaJjE4M3YrGSHDi4uUSTGBWw6EQ=="
24 | },
25 | "Microsoft.JavaScript.Hermes": {
26 | "type": "Transitive",
27 | "resolved": "0.1.23",
28 | "contentHash": "cA9t1GjY4Yo0JD1AfA//e1lOwk48hLANfuX6GXrikmEBNZVr2TIX5ONJt5tqCnpZyLz6xGiPDgTfFNKbSfb21g=="
29 | },
30 | "Microsoft.Web.WebView2": {
31 | "type": "Transitive",
32 | "resolved": "1.0.1264.42",
33 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
34 | },
35 | "common": {
36 | "type": "Project",
37 | "dependencies": {
38 | "boost": "[1.83.0, )"
39 | }
40 | },
41 | "fmt": {
42 | "type": "Project"
43 | },
44 | "folly": {
45 | "type": "Project",
46 | "dependencies": {
47 | "boost": "[1.83.0, )",
48 | "fmt": "[1.0.0, )"
49 | }
50 | },
51 | "microsoft.reactnative": {
52 | "type": "Project",
53 | "dependencies": {
54 | "Common": "[1.0.0, )",
55 | "Folly": "[1.0.0, )",
56 | "Microsoft.JavaScript.Hermes": "[0.1.23, )",
57 | "Microsoft.UI.Xaml": "[2.8.0, )",
58 | "ReactCommon": "[1.0.0, )",
59 | "boost": "[1.83.0, )"
60 | }
61 | },
62 | "reactcommon": {
63 | "type": "Project",
64 | "dependencies": {
65 | "Folly": "[1.0.0, )",
66 | "boost": "[1.83.0, )"
67 | }
68 | }
69 | },
70 | "native,Version=v0.0/win10-arm": {
71 | "Microsoft.Web.WebView2": {
72 | "type": "Transitive",
73 | "resolved": "1.0.1264.42",
74 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
75 | }
76 | },
77 | "native,Version=v0.0/win10-arm-aot": {
78 | "Microsoft.Web.WebView2": {
79 | "type": "Transitive",
80 | "resolved": "1.0.1264.42",
81 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
82 | }
83 | },
84 | "native,Version=v0.0/win10-arm64-aot": {
85 | "Microsoft.Web.WebView2": {
86 | "type": "Transitive",
87 | "resolved": "1.0.1264.42",
88 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
89 | }
90 | },
91 | "native,Version=v0.0/win10-x64": {
92 | "Microsoft.Web.WebView2": {
93 | "type": "Transitive",
94 | "resolved": "1.0.1264.42",
95 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
96 | }
97 | },
98 | "native,Version=v0.0/win10-x64-aot": {
99 | "Microsoft.Web.WebView2": {
100 | "type": "Transitive",
101 | "resolved": "1.0.1264.42",
102 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
103 | }
104 | },
105 | "native,Version=v0.0/win10-x86": {
106 | "Microsoft.Web.WebView2": {
107 | "type": "Transitive",
108 | "resolved": "1.0.1264.42",
109 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
110 | }
111 | },
112 | "native,Version=v0.0/win10-x86-aot": {
113 | "Microsoft.Web.WebView2": {
114 | "type": "Transitive",
115 | "resolved": "1.0.1264.42",
116 | "contentHash": "7OBUTkzQ5VI/3gb0ufi5U4zjuCowAJwQg2li0zXXzqkM+S1kmOlivTy1R4jAW+gY5Vyg510M+qMAESCQUjrfgA=="
117 | }
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/pch.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
--------------------------------------------------------------------------------
/windows/ReactNativeStaticServer/pch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define NOMINMAX
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #if __has_include()
11 | #include
12 | #endif
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | using namespace winrt::Windows::Foundation;
28 |
--------------------------------------------------------------------------------
/windows/mingw.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | # This script pre-builds Lighttpd into a static Windows library.
5 | # To use it:
6 | # - Install MSYS2 (https://www.msys2.org).
7 | # - Run the default MSYS2 UCRT64 console, and execute the following command
8 | # to install necessary dependencies:
9 | # $ pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-cmake \
10 | # mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-pcre2
11 | # - Check-out the correct code version in the /lighttpd1.4 folder (the master
12 | # branch of Lighttpd repo does not support MinGW build yet, you need some
13 | # commit from the win32-exp branch).
14 | # - Then run this script from within the same MSYS2 UCRT64 console.
15 |
16 | SCRIPT_FOLDER=$(dirname $(realpath $0))
17 | ROOT_FOLDER=$(dirname $SCRIPT_FOLDER)
18 | BUILD_FOLDER="$SCRIPT_FOLDER/build"
19 | OUTPUT_FOLDER="$SCRIPT_FOLDER/ReactNativeStaticServer/lighttpd"
20 | MSYS2_PATH="/ucrt64"
21 |
22 | cmake $ROOT_FOLDER -B $BUILD_FOLDER -G Ninja \
23 | -DBUILD_LIBRARY=ON -DCMAKE_BUILD_TYPE=Release
24 | cmake --build $BUILD_FOLDER --target mod_dirlisting mod_h2 mod_webdav lighttpd
25 |
26 | mkdir -p $OUTPUT_FOLDER
27 | cd $BUILD_FOLDER/lighttpd1.4/build
28 | cp *.dll $OUTPUT_FOLDER
29 |
30 | # NOTE: The Lemon binary created here is used by Android builds on Windows.
31 | cp lemon.exe $OUTPUT_FOLDER
32 |
33 | cd $BUILD_FOLDER/sysroot/bin
34 | cp libpcre2-8.dll $OUTPUT_FOLDER
35 |
36 | cd $MSYS2_PATH/bin
37 | cp libwinpthread-1.dll $OUTPUT_FOLDER
38 |
--------------------------------------------------------------------------------