diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml deleted file mode 100644 index fb98c79..0000000 --- a/.github/actions/setup/action.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Setup -description: Setup Node.js and install dependencies - -runs: - using: composite - steps: - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version-file: .nvmrc - - - name: Cache dependencies - id: yarn-cache - uses: actions/cache@v3 - with: - path: | - **/node_modules - .yarn/install-state.gz - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} - restore-keys: | - ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - ${{ runner.os }}-yarn- - - - name: Install dependencies - if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn install --immutable - shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6297ef1..0c2d2bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,154 +1,33 @@ name: CI + on: - push: - branches: - - main pull_request: - branches: - - main jobs: - lint: + lint-and-build: + name: Lint, Type Check & Build runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Lint files - run: yarn lint - - name: Typecheck files - run: yarn typecheck - - test: - runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Run unit tests - run: yarn test --maxWorkers=2 --coverage + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd - build-library: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Build package - run: yarn prepare - - build-android: - runs-on: ubuntu-latest - env: - TURBO_CACHE_DIR: .turbo/android - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Cache turborepo for Android - uses: actions/cache@v3 - with: - path: ${{ env.TURBO_CACHE_DIR }} - key: ${{ runner.os }}-turborepo-android-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-turborepo-android- - - - name: Check turborepo cache for Android - run: | - TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:android').cache.status") - - if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then - echo "turbo_cache_hit=1" >> $GITHUB_ENV - fi - - - name: Install JDK - if: env.turbo_cache_hit != 1 - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: '17' - - - name: Finalize Android SDK - if: env.turbo_cache_hit != 1 - run: | - /bin/bash -c "yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/null" - - - name: Cache Gradle - if: env.turbo_cache_hit != 1 - uses: actions/cache@v3 - with: - path: | - ~/.gradle/wrapper - ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('example/android/gradle/wrapper/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Build example for Android - env: - JAVA_OPTS: "-XX:MaxHeapSize=6g" - run: | - yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" - - build-ios: - runs-on: macos-14 - env: - TURBO_CACHE_DIR: .turbo/ios - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Cache turborepo for iOS - uses: actions/cache@v3 + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: - path: ${{ env.TURBO_CACHE_DIR }} - key: ${{ runner.os }}-turborepo-ios-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-turborepo-ios- + node-version-file: '.nvmrc' - - name: Check turborepo cache for iOS - run: | - TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status") + - name: Enable corepack + run: corepack enable - if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then - echo "turbo_cache_hit=1" >> $GITHUB_ENV - fi + - name: Install dependencies + run: yarn install --immutable - - name: Cache cocoapods - if: env.turbo_cache_hit != 1 - id: cocoapods-cache - uses: actions/cache@v3 - with: - path: | - **/ios/Pods - key: ${{ runner.os }}-cocoapods-${{ hashFiles('example/ios/Podfile.lock') }} - restore-keys: | - ${{ runner.os }}-cocoapods- + - name: Type check + run: yarn typecheck - - name: Install cocoapods - if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true' - run: | - cd example/ios - pod install - env: - NO_FLIPPER: 1 + - name: Lint check + run: yarn lint - - name: Build example for iOS - run: | - yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" + - name: Build + run: yarn prepare diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..27a474c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,75 @@ +name: Release + +on: + workflow_dispatch: + inputs: + version: + description: "Version bump type" + required: true + type: choice + options: + - patch + - minor + - major + +jobs: + release: + runs-on: ubuntu-latest + + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd + with: + fetch-depth: 0 + + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version-file: '.nvmrc' + + - name: Enable corepack + run: corepack enable + + - name: Bump version and update CHANGELOG + id: bump + run: | + NEW_VERSION=$(npm version ${{ github.event.inputs.version }} --no-git-tag-version) + echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT + sed -i "s/## \[Unreleased\]/## [Unreleased]\n\n## [$NEW_VERSION] - $(date +%Y-%m-%d)/" CHANGELOG.md + + - name: Extract release notes + id: changelog + run: | + NOTES=$(awk '/## \[Unreleased\]/ {flag=1; next} /^## \[/ {flag=0} flag {print}' CHANGELOG.md) + echo "notes<> $GITHUB_OUTPUT + echo "$NOTES" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Build and pack + id: pack + run: | + yarn install + yarn prepare + yarn pack --filename mendix-native-${{ steps.bump.outputs.version }}.tgz + echo "tgz=mendix-native-${{ steps.bump.outputs.version }}.tgz" >> $GITHUB_OUTPUT + + - name: Create GitHub Release + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b + with: + tag_name: ${{ steps.bump.outputs.version }} + name: ${{ steps.bump.outputs.version }} + body: ${{ steps.changelog.outputs.notes }} + files: ${{ steps.pack.outputs.tgz }} + + - name: Create Pull Request + uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 + with: + commit-message: "chore: release ${{ steps.bump.outputs.version }}" + branch: release/${{ steps.bump.outputs.version }} + title: "Release ${{ steps.bump.outputs.version }}" + body: "This PR updates CHANGELOG.md and package.json for release ${{ steps.bump.outputs.version }}." + base: main diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml deleted file mode 100644 index 9509231..0000000 --- a/.github/workflows/secret-scan.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Secret Scan - -on: - push: - branches: [ "**" ] - pull_request: - branches: [ "**" ] - workflow_dispatch: - -permissions: - contents: read - security-events: write - -jobs: - gitleaks: - name: Gitleaks Scan - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Run gitleaks - id: gitleaks - uses: gitleaks/gitleaks-action@v2 - with: - config-path: .gitleaks.toml - args: --report-format sarif --report-path gitleaks.sarif - - - name: Upload SARIF to code scanning - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: gitleaks.sarif diff --git a/.gitignore b/.gitignore index 821dab1..d8bf499 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ node_modules/ npm-debug.log yarn-debug.log yarn-error.log +*.tgz # BUCK buck-out/ diff --git a/.gitleaks.toml b/.gitleaks.toml deleted file mode 100644 index 1faa223..0000000 --- a/.gitleaks.toml +++ /dev/null @@ -1,71 +0,0 @@ -title = "mendix-native gitleaks config" -# Base config uses gitleaks defaults; we extend with allowlists and a few custom regexes - -[allowlist] - description = "Global allowlist" - files = [ - "yarn.lock", - "package-lock.json", - "pnpm-lock.yaml", - "gradlew", - "gradlew.bat", - "example/ios/Pods/", - "example/android/" - ] - regexes = [ - # Common false positives - '''(?i)localhost(:[0-9]{2,5})?''', - '''(?i)internal-slot''', - '''(?i)eastasianwidth''' - ] - -[[rules]] - id = "generic-api-key" - description = "Generic API key format" - regex = '''(?i)(api|access|auth)[_-]?key["'\s:=]+[A-Za-z0-9_\-]{16,}''' - tags = ["api", "key", "generic"] - -[[rules]] - id = "bearer-token-inline" - description = "Potential hard-coded bearer token" - regex = '''Bearer\s+[A-Za-z0-9\-_.]{20,}''' - tags = ["auth", "token"] - -[[rules]] - id = "jwt" - description = "JSON Web Token" - regex = '''eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}''' - tags = ["jwt", "token"] - -[[rules]] - id = "aws-access-key" - description = "AWS Access Key ID" - regex = '''AKIA[0-9A-Z]{16}''' - tags = ["aws", "key"] - -[[rules]] - id = "github-token" - description = "GitHub Personal Access Token" - regex = '''ghp_[A-Za-z0-9]{36,}''' - tags = ["github", "token"] - -[[rules]] - id = "slack-token" - description = "Slack token" - regex = '''xox[baprs]-[A-Za-z0-9\-]{10,}''' - tags = ["slack", "token"] - -[[rules]] - id = "stripe-secret-key" - description = "Stripe live secret key" - regex = '''sk_live_[0-9a-zA-Z]{10,}''' - tags = ["stripe", "secret"] - -[[rules]] - id = "private-key-block" - description = "Private key block" - regex = '''-----BEGIN (EC|RSA|DSA|OPENSSH|PRIVATE) KEY-----''' - tags = ["crypto", "private-key"] - -[whitelist] # backward compatibility for older gitleaks versions - description = "Legacy whitelist alias" diff --git a/.nvmrc b/.nvmrc index 3f430af..a45fd52 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18 +24 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..593a8ce --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +All notable changes to `mendix-native` package will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## [Unreleased] + +## [0.1.2] - 2025-11-17 + +- We upgraded mendix-native to use React Native’s New Architecture to improve performance and future compatibility. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62fbd6b..31e6e73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,7 +52,7 @@ yarn example ios To confirm that the app is running with the new architecture, you can check the Metro logs for a message like this: ```sh -Running "MendixNativeExample" with {"fabric":true,"initialProps":{"concurrentRoot":true},"rootTag":1} +Running "App" with {"fabric":true,"initialProps":{"concurrentRoot":true},"rootTag":1} ``` Note the `"fabric":true` and `"concurrentRoot":true` properties. @@ -97,16 +97,6 @@ We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint] Our pre-commit hooks verify that the linter and tests pass when committing. -### Publishing to npm - -We use [release-it](https://github.com/release-it/release-it) to make it easier to publish new versions. It handles common tasks like bumping version based on semver, creating tags and releases etc. - -To publish new versions, run the following: - -```sh -yarn release -``` - ### Scripts The `package.json` file contains various scripts for common tasks: diff --git a/README.md b/README.md index e69de29..2a8be0b 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,260 @@ +# Mendix Native + +Mendix native mobile package for React Native applications. + +## Prerequisites + +Before you begin, ensure you have the following installed: + +- **Node.js**: Version 18 (specified in `.nvmrc`) +- **Yarn**: Package manager (Yarn workspaces are required) +- **React Native development environment** (optional, only needed if running the example app): Follow the [React Native environment setup guide](https://reactnative.dev/docs/environment-setup) + - For iOS: Xcode and CocoaPods + - For Android: Android Studio and Android SDK + +## Local Development Setup + +This project is a monorepo managed using Yarn workspaces with: +- The library package in the root directory +- An example app in the `example/` directory + +### 1. Clone the Repository + +```bash +git clone https://github.com/YogendraShelke/mendix-native.git +cd mendix-native +``` + +### 2. Enable Corepack and Install Dependencies + +```bash +corepack enable +yarn install +``` + +This will enable Yarn via Corepack and install dependencies for both the library and the example app. + +### 3. Build the Library + +```bash +yarn prepare +``` + +This compiles the TypeScript code and generates the `lib` folder. + +### 4. Run the Example App + +The example app demonstrates library usage and reflects your local changes in real-time. + +#### Start Metro Bundler + +```bash +yarn example start +``` + +#### Run on iOS + +```bash +yarn example ios +``` + +Or open in Xcode: + +```bash +yarn dev:ios +``` + +#### Run on Android + +```bash +yarn example android +``` + +### 5. Development Workflow + +#### Making Changes + +- **JavaScript/TypeScript changes**: Automatically reflected without rebuild +- **Native code changes**: Require rebuilding the example app + +#### Edit Native Code + +**iOS (Objective-C/Swift):** +- Open `example/ios/MendixNativeExample.xcworkspace` in Xcode +- Find source files at: `Pods > Development Pods > mendix-native` + +**Android (Java/Kotlin):** +- Open `example/android` in Android Studio +- Find source files under: `mendix-native` in the Android view + +#### Verify Your Code + +Run type checking: + +```bash +yarn typecheck +``` + +Run linter: + +```bash +yarn lint +``` + +Fix linting issues: + +```bash +yarn lint --fix +``` + +Run tests: + +```bash +yarn test +``` + +### 6. Clean Build Artifacts + +If you encounter build issues: + +```bash +yarn clean +``` + +## Available Scripts + +- `yarn install` - Install dependencies +- `yarn prepare` - Build the library +- `yarn typecheck` - Type-check with TypeScript +- `yarn lint` - Lint code with ESLint +- `yarn test` - Run unit tests +- `yarn clean` - Remove build artifacts +- `yarn example start` - Start Metro bundler +- `yarn example ios` - Run example app on iOS +- `yarn example android` - Run example app on Android +- `yarn dev:ios` - Build, install pods, and open iOS project + +## Contributing + +See [CONTRIBUTING.md](./CONTRIBUTING.md) for detailed contribution guidelines. + +--- + +## Release Process + +This repository supports automated releases using a GitHub Actions workflow. +A manual fallback process is also documented below for situations where the workflow cannot be used. + +## Automated Release (Recommended) + +The automated workflow handles: + +- Bumping the package version +- Building and generating the lib folder +- Creating the tarball (.tgz) +- Creating a GitHub Release with attached artifact +- Moving the Unreleased notes from CHANGELOG.md into a new version section +- Creating a pull request against master with updated files + +### Steps + +1. Go to GitHub → Actions → Manual Release. +2. Select Run workflow. +3. Choose the version bump type: + - patch + - minor + - major +4. Run the workflow. + +The workflow will: + +- Update package.json version +- Run `yarn install && yarn prepare` to generate the build +- Run `yarn pack` to generate the .tgz file +- Create a new GitHub Release with: + - tag = new version + - release notes from the Unreleased section in CHANGELOG.md + - the generated .tgz file attached +- Commit updated CHANGELOG.md and package.json +- Create a pull request: + - branch: `release/` + - base: `master` + +After the PR is merged, the release is complete. + +## Manual Release (Fallback) + +If the automated workflow fails, the release can be performed manually with the same steps. + +### 1. Bump the Version + +Choose one: + +```bash +npm version patch +npm version minor +npm version major +``` + +This updates package.json locally (you'll commit this later). + +### 2. Install and Build + +```bash +yarn install +yarn prepare +``` + +The prepare script should generate the lib folder. + +### 3. Generate the Tarball + +```bash +yarn pack +``` + +This creates a file like: + +``` +package-name-vX.Y.Z.tgz +``` + +Keep this file for the release. + +### 4. Update CHANGELOG.md + +Move the content under Unreleased into a new version heading. + +Example: + +```markdown +## [Unreleased] + +## [1.2.0] - 2025-01-15 + +``` + +### 5. Commit Changes + +```bash +git add CHANGELOG.md package.json +git commit -m "chore: release " +git push +``` + +### 6. Create a GitHub Release Manually + +1. Go to Releases → Draft a new release. +2. Use the version number as the tag and title. +3. Paste the notes you moved from the Unreleased section. +4. Upload the .tgz file from the yarn pack step. +5. Publish the release. + +### 7. Create Pull Request (If Needed) + +If your project requires PR-based updates, create a PR against master with the same changes you committed. + +## Summary + +Use the automated workflow whenever possible because it handles every repetitive step. +When needed, the fallback manual process mirrors the workflow exactly so releases remain consistent and predictable. diff --git a/lefthook.yml b/lefthook.yml index 9695c12..b5ccec8 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -7,6 +7,13 @@ pre-commit: types: glob: "*.{js,ts, jsx, tsx}" run: npx tsc + version-check: + glob: "package.json" + run: | + if git diff --cached package.json | grep -q '^\+.*"version":'; then + echo "❌ Please don't edit the version manually. Version bumps are handled automatically when the package is released via the release workflow." + exit 1 + fi commit-msg: parallel: true commands: