diff --git a/.gitignore b/.gitignore index b6135323..b7ae7651 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,6 @@ android/keystores/debug.keystore # generated by bob lib/ node_modules + +# SwiftPM +.build/ diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000..24f68ca2 --- /dev/null +++ b/Package.swift @@ -0,0 +1,41 @@ +// swift-tools-version: 6.0 +import PackageDescription + +// Rewritten in place by scripts/write-hyper-sdk-version.js on `npm install` +// (reads hyperSdkIOSVersion from the consuming app's package.json). +var hyperSdkVersion: Version = "2.2.3" + +let package = Package( + name: "HyperSdkReact", + platforms: [.iOS(.v15)], + products: [ + .library(name: "HyperSdkReact", targets: ["HyperSdkReact"]), + ], + dependencies: [ + .package(name: "ReactNative", path: "../../../../xcframeworks"), + .package(name: "React-GeneratedCode", path: "../../../ios"), + .package(url: "https://github.com/juspay/hypersdk-ios.git", exact: hyperSdkVersion), + ], + targets: [ + .target( + name: "HyperSdkReact", + dependencies: [ + .product(name: "ReactHeaders", package: "ReactNative"), + .product(name: "ReactNativeHeaders", package: "ReactNative"), + .product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"), + .product(name: "ReactAppHeaders", package: "React-GeneratedCode"), + .product(name: "HyperSDK", package: "hypersdk-ios"), + ], + path: ".", + exclude: ["example", "node_modules"], + sources: [ + "ios/include/HyperMerchantView.h", + "ios/include/HyperSdkReact.h", + "ios/HyperSdkReact.mm", + "ios/latest/HyperMerchantView.mm", + ], + publicHeadersPath: "ios/include" + ), + ], + cxxLanguageStandard: .cxx20 +) diff --git a/README.md b/README.md index 4f5b5558..ab9fa85e 100644 --- a/README.md +++ b/README.md @@ -79,12 +79,58 @@ post_install do |installer| end ``` -Place the `MerchantConfig.txt` file inside the folder where the Podfile is present. This file doesn't need to be added to the project. The content of the file should be as below +Place a `MerchantConfig.json` file inside the folder where the Podfile is present. This file doesn't need to be added to the project. The content of the file should be as below -```txt -clientId = +```json +{ + "clientConfigs": { + "": {} + } +} ``` +#### iOS (Swift Package Manager) + +React Native 0.87+ introduced experimental SwiftPM autolinking. CocoaPods (above) remains the default, production-supported integration path — use this only if your app is already fully SwiftPM-based. + +Run the following command inside your react native project: + +```sh +npx react-native spm +``` + +Overriding the base SDK version works the same way as CocoaPods — add `hyperSdkIOSVersion` to your project's `package.json` as shown above, then re-run `npm install` (this updates the SPM manifest automatically). + +**Installing Assets Plugin** + +Place a `MerchantConfig.json` file inside the folder where your `.xcodeproj` is present. The content of the file should be as below + +```json +{ + "clientConfigs": { + "": {} + } +} +``` + +Go to **Product → Scheme → Edit Scheme…**, expand **Build**, select **Pre-actions**, add a **New Run Script Action** (set **Provide build settings from** to your app target), and paste: + +```sh +PACKAGE_DIR="${BUILD_DIR%Build/*}SourcePackages/artifacts/hypersdk-ios/HyperSDK" +XCFRAMEWORK_DIR="${PACKAGE_DIR}/HyperSDK.xcframework" +FUSE_SCRIPT="${PACKAGE_DIR}/Fuse.rb" +FUSE_MARKER="${XCFRAMEWORK_DIR}/.fuse_completed" +VALIDATION_SCRIPT="${PACKAGE_DIR}/ValidateHyperSDK.rb" + +[ ! -f "$FUSE_MARKER" ] || [ "${ACTION}" == "clean" ] && { cd "${PROJECT_DIR}"; echo "Running Fuse.rb script..."; ruby "$FUSE_SCRIPT"; } + +ruby "$VALIDATION_SCRIPT" && touch "$FUSE_MARKER" || exit 1 +``` + +This runs on every **Clean Build Folder**. + +See [hypersdk-ios's own integration guide](https://github.com/juspay/hypersdk-ios#11-installing-assets-plugin) for the full walkthrough with screenshots. + ## Usage ### Exposed APIs diff --git a/hyper-sdk-react.podspec b/hyper-sdk-react.podspec index f018772a..c124bffe 100644 --- a/hyper-sdk-react.podspec +++ b/hyper-sdk-react.podspec @@ -67,7 +67,7 @@ puts ("Found react native minor version as #{rn_major_version}.#{rn_minor_versio folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_CFG_NO_COROUTINES=1 -Wno-comma -Wno-shorten-64-to-32' -hyper_sdk_version = "2.2.2.8" +hyper_sdk_version = package["hyperSdkIOSVersion"] begin package_json_path = File.expand_path(File.join(__dir__, "../../package.json")) diff --git a/ios/HyperMerchantView.h b/ios/include/HyperMerchantView.h similarity index 100% rename from ios/HyperMerchantView.h rename to ios/include/HyperMerchantView.h diff --git a/ios/HyperSdkReact.h b/ios/include/HyperSdkReact.h similarity index 99% rename from ios/HyperSdkReact.h rename to ios/include/HyperSdkReact.h index 599da25c..40b1a669 100644 --- a/ios/HyperSdkReact.h +++ b/ios/include/HyperSdkReact.h @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ - #import #import #import diff --git a/package.json b/package.json index d7753c67..1455b716 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "ios", "cpp", "*.podspec", + "Package.swift", + "scripts/write-hyper-sdk-version.js", "!lib/typescript/example", "!ios/build", "!android/build", @@ -28,10 +30,11 @@ "!**/__mocks__" ], "scripts": { + "postinstall": "node scripts/write-hyper-sdk-version.js", "test": "jest", "typecheck": "tsc --noEmit", "lint": "eslint \"**/*.{js,ts,tsx}\"", - "prepack": "bob build", + "prepack": "node scripts/write-hyper-sdk-version.js && bob build", "example": "yarn --cwd example", "bootstrap": "yarn example && yarn install && yarn example pods", "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build" @@ -51,6 +54,7 @@ "publishConfig": { "registry": "https://registry.npmjs.org/" }, + "hyperSdkIOSVersion": "2.2.3", "devDependencies": { "@commitlint/config-conventional": "^17.0.2", "@evilmartians/lefthook": "^1.2.2", diff --git a/scripts/write-hyper-sdk-version.js b/scripts/write-hyper-sdk-version.js new file mode 100644 index 00000000..6b4b7f2e --- /dev/null +++ b/scripts/write-hyper-sdk-version.js @@ -0,0 +1,62 @@ +#!/usr/bin/env node +// Runs as hyper-sdk-react's own `postinstall`. Rewrites the +// `hyperSdkVersion` literal in Package.swift with hyperSdkIOSVersion from +// the consuming app's package.json (found via INIT_CWD, the directory +// `npm install` was originally run from). +const fs = require('fs'); +const path = require('path'); + +// Single source of truth for the base version — also read directly by +// hyper-sdk-react.podspec via package["hyperSdkIOSVersion"]. +const ownPackageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8')); +const BASE_HYPER_SDK_VERSION = ownPackageJson.hyperSdkIOSVersion; + +const packageSwiftPath = path.join(__dirname, '..', 'Package.swift'); +const versionLinePattern = /var hyperSdkVersion: Version = "[^"]+"/; + +function compareVersions(a, b) { + const partsA = a.split(/[.-]/).map((p) => (Number.isNaN(Number(p)) ? p : Number(p))); + const partsB = b.split(/[.-]/).map((p) => (Number.isNaN(Number(p)) ? p : Number(p))); + const length = Math.max(partsA.length, partsB.length); + for (let i = 0; i < length; i++) { + const partA = partsA[i] ?? 0; + const partB = partsB[i] ?? 0; + if (partA === partB) continue; + if (typeof partA === 'number' && typeof partB === 'number') return partA - partB; + return String(partA).localeCompare(String(partB)); + } + return 0; +} + +function resolveEffectiveVersion() { + try { + const appDir = process.env.INIT_CWD || process.cwd(); + const appPackageJson = JSON.parse(fs.readFileSync(path.join(appDir, 'package.json'), 'utf8')); + const overrideVersion = appPackageJson.hyperSdkIOSVersion; + if (typeof overrideVersion === 'string' && overrideVersion.length > 0 && + compareVersions(overrideVersion, BASE_HYPER_SDK_VERSION) > 0) { + return overrideVersion; + } + } catch (e) { + // No app package.json found / unreadable / no override — fall through to base. + } + return BASE_HYPER_SDK_VERSION; +} + +const effectiveVersion = resolveEffectiveVersion(); +const packageSwiftContents = fs.readFileSync(packageSwiftPath, 'utf8'); +const updatedContents = packageSwiftContents.replace( + versionLinePattern, + `var hyperSdkVersion: Version = "${effectiveVersion}"` +); + +if (updatedContents !== packageSwiftContents) { + fs.writeFileSync(packageSwiftPath, updatedContents); +} + +// Clean up the old (pre-direct-rewrite) local file, if present from an +// earlier install of this package. +const legacyLocalVersionFile = path.join(__dirname, '..', '.hyper-sdk-version'); +if (fs.existsSync(legacyLocalVersionFile)) { + fs.unlinkSync(legacyLocalVersionFile); +}