diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd13ed7c44..4e3f9b11b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,5 @@ name: Build + on: push: branches: @@ -14,6 +15,7 @@ jobs: name: Build App runs-on: ubuntu-latest timeout-minutes: 60 + steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -23,7 +25,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - name: Setup pnpm uses: pnpm/action-setup@v4 @@ -41,54 +43,24 @@ jobs: restore-keys: | ${{ runner.os }}-pnpm-store- - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: '17' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-read-only: false - - name: Install Dependencies run: pnpm install --frozen-lockfile - - name: Create Environment File - run: | - cat > .env << EOF - MYANIMELIST_CLIENT_ID=${{ vars.MYANIMELIST_CLIENT_ID }} - ANILIST_CLIENT_ID=${{ vars.ANILIST_CLIENT_ID }} - GIT_HASH=$(git rev-parse --short HEAD) - RELEASE_DATE=$(date --utc +'%d/%m/%y %I:%M %p %Z') - BUILD_TYPE=Github Action - EOF - - - name: Make Gradlew Executable - run: cd android && chmod +x ./gradlew - - - name: Set Environment Variables - run: | - set -x - echo "COMMIT_COUNT=$(git rev-list --count HEAD)" >> $GITHUB_ENV - echo "COMMIT_ID=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - - - name: Build Android Release - env: - COMMIT_COUNT: ${{ env.COMMIT_COUNT }} - COMMIT_ID: ${{ env.COMMIT_ID }} + - name: Generate Environment Variables run: | - sed -i 's/lnreader/lnreader-r${{ env.COMMIT_COUNT }}(${{ env.COMMIT_ID }})/g' android/app/src/main/res/values/strings.xml - cd android && ./gradlew assembleRelease -PcustomAppId=com.rajarsheechatterjee.LNReader.commit_${{ env.COMMIT_ID }} --build-cache - mv app/build/outputs/apk/release/app-release.apk app/build/outputs/apk/release/LNReader-r${{ env.COMMIT_COUNT }}-${{ env.COMMIT_ID }}.apk + pnpm generate:env:release \ + --build-type "Github Action" \ + --node-env "production" \ + --myanimelist-client-id "${{ vars.MYANIMELIST_CLIENT_ID }}" \ + --anilist-client-id "${{ vars.ANILIST_CLIENT_ID }}" - - name: Upload Release Artifact + - name: Build Android Release with Rock + uses: callstackincubator/android@v3 env: - COMMIT_COUNT: ${{ env.COMMIT_COUNT }} - COMMIT_ID: ${{ env.COMMIT_ID }} - uses: actions/upload-artifact@v4 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO_OWNER: ${{ github.repository_owner }} + REPO_NAME: ${{ github.event.repository.name }} with: - name: LNReader-r${{ env.COMMIT_COUNT }}-${{ env.COMMIT_ID }} - path: android/app/build/outputs/apk/release/LNReader-r${{ env.COMMIT_COUNT }}-${{ env.COMMIT_ID }}.apk - retention-days: 30 + re-sign: true + github-token: ${{ secrets.GITHUB_TOKEN }} + variant: preRelease diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 90290ee3d1..b20e57da73 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - name: Setup pnpm uses: pnpm/action-setup@v4 diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 65d3c4b4a4..1c6cbe7e37 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - name: Setup pnpm uses: pnpm/action-setup@v4 diff --git a/.github/workflows/types.yml b/.github/workflows/types.yml index ae3e49bd07..2e416bdec8 100644 --- a/.github/workflows/types.yml +++ b/.github/workflows/types.yml @@ -20,7 +20,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '24' - name: Setup pnpm uses: pnpm/action-setup@v4 diff --git a/.gitignore b/.gitignore index b58ccbf0ab..91a18affe4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ npm-debug.* *.mobileprovision *.orig.* web-build/ -.env +.*env reader_playground/index.html # macOS .DS_Store @@ -89,8 +89,16 @@ flake.lock # pnpm .pnpm-store +src/generated/**/* + .cursor/ .agents/ .claude/ .jj/ .sisyphus/ + +# Rock +.rock/ + +# TypeScript +*.tsbuildinfo diff --git a/App.tsx b/App.tsx index 0fcfb58fe5..9800c978cb 100644 --- a/App.tsx +++ b/App.tsx @@ -18,6 +18,7 @@ import AppErrorBoundary, { import Main from './src/navigators/Main'; import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'; import { useInitDatabase } from '@database/db'; +import { ThemeProvider } from '@hooks/persisted/useTheme'; Notifications.setNotificationHandler({ handleNotification: async () => { @@ -49,12 +50,14 @@ const App = () => { - - - -
- - + + + + +
+ + + diff --git a/__mocks__/database.js b/__mocks__/database.js index f023116ec2..103783474c 100644 --- a/__mocks__/database.js +++ b/__mocks__/database.js @@ -1,4 +1,5 @@ jest.mock('@database/queries/NovelQueries', () => ({ + getNovelById: jest.fn(), getNovelByPath: jest.fn(), deleteCachedNovels: jest.fn(), getCachedNovels: jest.fn(), @@ -30,7 +31,9 @@ jest.mock('@database/queries/ChapterQueries', () => ({ insertChapters: jest.fn(), getCustomPages: jest.fn(), getChapterCount: jest.fn(), + getChapterCountSync: jest.fn(), getPageChaptersBatched: jest.fn(), + getNovelChaptersSync: jest.fn(), getFirstUnreadChapter: jest.fn(), updateChapterProgress: jest.fn(), })); diff --git a/__tests-modules__/test-utils.tsx b/__tests-modules__/test-utils.tsx index 9e16ced519..ce0305fa04 100644 --- a/__tests-modules__/test-utils.tsx +++ b/__tests-modules__/test-utils.tsx @@ -4,6 +4,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { Provider as PaperProvider } from 'react-native-paper'; import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'; +import { ThemeProvider } from '@hooks/persisted/useTheme'; import AppErrorBoundary from '@components/AppErrorBoundary/AppErrorBoundary'; import { NovelContextProvider } from '@screens/novel/NovelContext'; @@ -13,11 +14,13 @@ const AllTheProviders = ({ children }: { children: React.ReactElement }) => { return ( - - - {children} - - + + + + {children} + + + ); diff --git a/android/app/build.gradle b/android/app/build.gradle index 6913012930..6aa7b52f98 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,7 +15,7 @@ react { // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen // codegenDir = file("../../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js - // cliFile = file("../../node_modules/react-native/cli.js") + cliFile = file("../../node_modules/rock/dist/src/bin.js") /* Variants */ // The list of variants to that are debuggable. For those we're going to @@ -84,7 +84,7 @@ android { compileSdk rootProject.ext.compileSdkVersion namespace "com.rajarsheechatterjee.LNReader" defaultConfig { - applicationId project.hasProperty('customAppId') ? project.getProperty('customAppId') : 'com.rajarsheechatterjee.LNReader' + applicationId 'com.rajarsheechatterjee.LNReader' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion // Generated version code. Supports versions up to 1024.1024.2048 @@ -105,6 +105,17 @@ android { applicationIdSuffix 'debug' versionNameSuffix '-debug' } + preRelease { + initWith release + matchingFallbacks = ["release"] + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + applicationIdSuffix 'preRelease' + versionNameSuffix '-pre-release' + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } release { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. @@ -134,4 +145,4 @@ dependencies { } else { implementation jscFlavor } -} \ No newline at end of file +} diff --git a/android/app/src/main/assets/js/core.js b/android/app/src/main/assets/js/core.js index a218595dd9..82992b326b 100644 --- a/android/app/src/main/assets/js/core.js +++ b/android/app/src/main/assets/js/core.js @@ -167,6 +167,7 @@ window.tts = new (function () { this.normalizeText = text => { if (!text) return ''; return text + .replace(/^["'“”‘’]+|["'“”‘’]+$/g, '') .replace(/\s+/g, ' ') .replace(/\s*([.,!?;:])\s*/g, '$1 ') .trim(); @@ -780,13 +781,13 @@ window.addEventListener('load', () => { `${ /\/p>/.test(_) ? _.replace( - /
\s*
(?:(?=\s*<\/?p[> ])|(?<=<\/?p\b[^>]*>
\s*
))\s*/g, + /
\s*
(?:(?=\s*<\/?p[> ])|(?<=<\/?p(?:>| [^>]+>)
\s*
))\s*/g, '', ) : _ }`, ) //if p found, delete all double br near p - .replace(/
(?:(?=\s*<\/?p[> ])|(?<=<\/?p>\s*
))\s*/g, ''); + .replace(/
(?:(?=\s*<\/?p[> ])|(?<=<\/?p(?:>| [^>]+>)(?:<[^>]+>)*\s*
))\s*/g, ''); } reader.chapterElement.innerHTML = html; }); diff --git a/android/app/src/main/java/com/rajarsheechatterjee/NativeFile/NativeFile.kt b/android/app/src/main/java/com/rajarsheechatterjee/NativeFile/NativeFile.kt index a65a565053..ed772918d8 100644 --- a/android/app/src/main/java/com/rajarsheechatterjee/NativeFile/NativeFile.kt +++ b/android/app/src/main/java/com/rajarsheechatterjee/NativeFile/NativeFile.kt @@ -150,7 +150,7 @@ class NativeFile(context: ReactApplicationContext) : override fun unlink(filepath: String) { val file = File(filepath) - if (!file.exists()) throw Exception("File does not exist") + if (!file.exists()) return deleteRecursive(file) } diff --git a/android/settings.gradle b/android/settings.gradle index 5bd85f93a4..6021a50ec3 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -23,10 +23,11 @@ plugins { } extensions.configure(com.facebook.react.ReactSettingsExtension) { ex -> + def npxCmd = System.getProperty('os.name').toLowerCase().contains('windows') ? 'npx.cmd' : 'npx' if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') { - ex.autolinkLibrariesFromCommand() + ex.autolinkLibrariesFromCommand([npxCmd, 'rock', 'config', '-p', 'android']) } else { - ex.autolinkLibrariesFromCommand(expoAutolinking.rnConfigCommand) + ex.autolinkLibrariesFromCommand([npxCmd, 'rock', 'config', '-p', 'android']) } } diff --git a/babel.config.js b/babel.config.js index d5de9ae37a..ba8f201809 100644 --- a/babel.config.js +++ b/babel.config.js @@ -27,6 +27,7 @@ export default function (api) { '@type': './src/type', '@specs': './specs', '@test-utils': './__tests-modules__/test-utils', + '@env': './src/generated/build-info', 'react-native-vector-icons/MaterialCommunityIcons': '@react-native-vector-icons/material-design-icons', }, diff --git a/env.d.ts b/env.d.ts deleted file mode 100644 index a62595a633..0000000000 --- a/env.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -declare module 'react-native-config' { - export interface NativeConfig { - MYANIMELIST_CLIENT_ID: string; - ANILIST_CLIENT_ID: string; - GIT_HASH: string; - RELEASE_DATE: string; - BUILD_TYPE: 'Debug' | 'Release' | 'Beta' | 'Github Action'; - } - - export const Config: NativeConfig; - export default Config; -} diff --git a/ios/LNReader.xcodeproj/project.pbxproj b/ios/LNReader.xcodeproj/project.pbxproj index ad17a7e0c7..e86eba4fd6 100644 --- a/ios/LNReader.xcodeproj/project.pbxproj +++ b/ios/LNReader.xcodeproj/project.pbxproj @@ -265,7 +265,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + shellScript = "set -e\nif [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\nsource \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\nsource \"$PODS_ROOT/../.xcode.env.local\"\nfi\nexport CONFIG_CMD=\"dummy-workaround-value\"\nexport CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('rock/package.json')) + '/dist/src/bin.js'\")\"\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\n"; }; 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; diff --git a/ios/Podfile b/ios/Podfile index fc71ca6de9..24affabb0c 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -33,7 +33,7 @@ target 'LNReader' do ] end - config = use_native_modules!(config_command) + config = use_native_modules!(['npx', 'rock', 'config', '-p', 'ios'])(config_command) use_react_native!( :path => config[:reactNativePath], diff --git a/jest.config.js b/jest.config.js index 5268de4553..dd3677fd31 100644 --- a/jest.config.js +++ b/jest.config.js @@ -17,6 +17,7 @@ const baseModuleNameMapper = { '^@type/(.*)$': '/src/type/$1', '^@specs/(.*)$': '/specs/$1', '^@test-utils$': '/__tests-modules__/test-utils', + '^@env$': '/src/generated/build-info', // Mock static assets '\\.(jpg|jpeg|png|gif|webp|svg)$': '/__mocks__/fileMock.js', }; diff --git a/package.json b/package.json index f1c1f52876..f5ca6e0fe1 100644 --- a/package.json +++ b/package.json @@ -3,14 +3,15 @@ "version": "2.0.3", "private": true, "scripts": { - "dev:android": "pnpm run generate:env:debug && react-native run-android --appIdSuffix \"debug\" --active-arch-only", - "dev:ios": "react-native run-ios", - "dev:start": "react-native start", + "dev:android:release": "pnpm run generate:env:release && rock run:android --variant \"release\" --active-arch-only", + "dev:android": "pnpm run generate:env:debug && rock run:android --app-id-suffix \"debug\" --active-arch-only", + "dev:ios": "rock run:ios", + "dev:start": "rock start", "dev:clean-start": "pnpm run dev:start -- --reset-cache", - "build:release:android": "pnpm run generate:env:release && cd android && ./gradlew clean && ./gradlew assembleRelease", + "build:release:android": "pnpm run generate:env:release && rock build:android --variant \"release\"", "build:open-apk": "open ./android/app/build/outputs/apk/release/", - "generate:env:debug": "node scripts/generate-env-file.cjs Debug", - "generate:env:release": "node scripts/generate-env-file.cjs Release", + "generate:env:debug": "node scripts/generate-env-file.cjs --build-type Debug", + "generate:env:release": "node scripts/generate-env-file.cjs --build-type Release", "generate:string-types": "node scripts/generate-string-types.cjs", "generate:db-migration": "drizzle-kit generate", "upgrade:migration-format": "drizzle-kit up", @@ -66,6 +67,7 @@ "@react-navigation/native": "^7.2.2", "@react-navigation/native-stack": "^7.14.10", "@react-navigation/stack": "^7.8.9", + "@shopify/flash-list": "^2.3.1", "babel-plugin-inline-import": "^3.0.0", "cheerio": "1.0.0-rc.12", "color": "^5.0.3", @@ -93,7 +95,6 @@ "react": "^19.2.4", "react-native": "^0.83.4", "react-native-background-actions": "^4.0.1", - "react-native-config": "^1.6.1", "react-native-device-info": "^15.0.2", "react-native-draggable-flatlist": "^4.0.3", "react-native-drawer-layout": "^4.2.2", @@ -112,26 +113,29 @@ "react-native-screens": "^4.24.0", "react-native-shimmer-placeholder": "^2.0.9", "react-native-tab-view": "^4.3.0", + "react-native-theme-switch-animation": "^0.8.0", "react-native-url-polyfill": "^3.0.0", "react-native-webview": "^13.16.1", "react-native-worklets": "^0.8.1", "react-native-zip-archive": "^7.0.2", "sanitize-html": "^2.17.2", - "urlencode": "^2.0.0" + "urlencode": "^2.0.0", + "zustand": "^5.0.12" }, "devDependencies": { "@babel/core": "^7.29.0", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/preset-env": "^7.29.2", "@babel/runtime": "^7.29.2", - "@react-native-community/cli": "^20.1.3", - "@react-native-community/cli-platform-android": "^20.1.3", - "@react-native-community/cli-platform-ios": "^20.1.3", "@react-native/babel-preset": "^0.83.4", "@react-native/eslint-config": "^0.83.4", "@react-native/eslint-plugin": "^0.83.4", "@react-native/metro-config": "^0.83.4", "@react-native/typescript-config": "^0.83.4", + "@rock-js/platform-android": "^0.12.12", + "@rock-js/platform-ios": "^0.12.12", + "@rock-js/plugin-metro": "^0.12.12", + "@rock-js/provider-github": "^0.12.12", "@testing-library/react-native": "^13.3.3", "@types/better-sqlite3": "^7.6.13", "@types/color": "^4.2.1", @@ -143,7 +147,7 @@ "@typescript-eslint/parser": "^8.58.0", "babel-plugin-module-resolver": "^5.0.3", "babel-plugin-react-compiler": "^1.0.0", - "better-sqlite3": "^12.8.0", + "better-sqlite3": "^12.9.0", "drizzle-kit": "1.0.0-beta.20", "eslint": "^8.57.1", "eslint-plugin-eslint-comments": "^3.2.0", @@ -153,13 +157,14 @@ "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-native": "^5.0.0", "eslint-plugin-testing-library": "^7.16.2", - "hermes-compiler": "^250829098.0.2", + "hermes-compiler": "0.14.1", "husky": "^7.0.4", "jest": "^29.7.0", "jest-expo": "^55.0.11", "lint-staged": "^12.5.0", "prettier": "2.8.8", "react-test-renderer": "19.2.4", + "rock": "^0.12.12", "typescript": "~5.9.3" }, "lint-staged": { diff --git a/patches/@rock-js__plugin-metro@0.12.12.patch b/patches/@rock-js__plugin-metro@0.12.12.patch new file mode 100644 index 0000000000..783b626342 --- /dev/null +++ b/patches/@rock-js__plugin-metro@0.12.12.patch @@ -0,0 +1,23 @@ +diff --git a/dist/src/lib/getReactNativeDeps.js b/dist/src/lib/getReactNativeDeps.js +index d523e094eb456f91ee8c4de0f65500e4ec002991..1aa6f27ca1cef322db66d2f47a7cbd8a980dcbc2 100644 +--- a/dist/src/lib/getReactNativeDeps.js ++++ b/dist/src/lib/getReactNativeDeps.js +@@ -1,15 +1,16 @@ + import { createRequire } from 'node:module'; ++import { pathToFileURL } from 'node:url'; + export async function getDevMiddleware(reactNativePath) { + const require = createRequire(import.meta.url); + const reactNativeCommunityCliPluginPath = require.resolve('@react-native/community-cli-plugin', { paths: [reactNativePath] }); + const devMiddlewarePath = require.resolve('@react-native/dev-middleware', { + paths: [reactNativeCommunityCliPluginPath], + }); +- return import(devMiddlewarePath); ++ return import(pathToFileURL(devMiddlewarePath).href); + } + export async function getReactNativeCommunityCliPlugin(reactNativePath) { + const require = createRequire(import.meta.url); + const reactNativeCommunityCliPluginPath = require.resolve('@react-native/community-cli-plugin', { paths: [reactNativePath] }); +- return import(reactNativeCommunityCliPluginPath); ++ return import(pathToFileURL(reactNativeCommunityCliPluginPath).href); + } + //# sourceMappingURL=getReactNativeDeps.js.map diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e09012fea1..55203247ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,11 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + '@rock-js/plugin-metro@0.12.12': + hash: fb21d963fa0452524ca33673321a4a405c81e09817a628b64e4c72eee6c39747 + path: patches/@rock-js__plugin-metro@0.12.12.patch + importers: .: @@ -62,6 +67,9 @@ importers: '@react-navigation/stack': specifier: ^7.8.9 version: 7.8.9(05167d8527e2c9f68e950b4e3fb9e48b) + '@shopify/flash-list': + specifier: ^2.3.1 + version: 2.3.1(@babel/runtime@7.29.2)(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) babel-plugin-inline-import: specifier: ^3.0.0 version: 3.0.0 @@ -76,7 +84,7 @@ importers: version: 1.11.20 drizzle-orm: specifier: 1.0.0-beta.20 - version: 1.0.0-beta.20(@op-engineering/op-sqlite@15.2.9(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@sinclair/typebox@0.34.49)(@types/better-sqlite3@7.6.13)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(better-sqlite3@12.8.0)(expo-sqlite@16.0.10(expo@55.0.9)(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(mssql@11.0.1(@azure/core-client@1.10.1))(zod@4.3.6) + version: 1.0.0-beta.20(@op-engineering/op-sqlite@15.2.9(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@sinclair/typebox@0.34.49)(@types/better-sqlite3@7.6.13)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(better-sqlite3@12.9.0)(expo-sqlite@16.0.10(expo@55.0.9)(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(mssql@11.0.1(@azure/core-client@1.10.1))(zod@4.3.6) expo: specifier: ^55.0.9 version: 55.0.9(@babel/core@7.29.0)(@expo/dom-webview@55.0.3)(react-native-webview@13.16.1(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)(typescript@5.9.3) @@ -143,9 +151,6 @@ importers: react-native-background-actions: specifier: ^4.0.1 version: 4.0.1(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4)) - react-native-config: - specifier: ^1.6.1 - version: 1.6.1(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) react-native-device-info: specifier: ^15.0.2 version: 15.0.2(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4)) @@ -200,6 +205,9 @@ importers: react-native-tab-view: specifier: ^4.3.0 version: 4.3.0(react-native-pager-view@8.0.0(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) + react-native-theme-switch-animation: + specifier: ^0.8.0 + version: 0.8.0(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) react-native-url-polyfill: specifier: ^3.0.0 version: 3.0.0(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4)) @@ -218,6 +226,9 @@ importers: urlencode: specifier: ^2.0.0 version: 2.0.0 + zustand: + specifier: ^5.0.12 + version: 5.0.12(@types/react@19.2.14)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) devDependencies: '@babel/core': specifier: ^7.29.0 @@ -231,15 +242,6 @@ importers: '@babel/runtime': specifier: ^7.29.2 version: 7.29.2 - '@react-native-community/cli': - specifier: ^20.1.3 - version: 20.1.3(typescript@5.9.3) - '@react-native-community/cli-platform-android': - specifier: ^20.1.3 - version: 20.1.3 - '@react-native-community/cli-platform-ios': - specifier: ^20.1.3 - version: 20.1.3 '@react-native/babel-preset': specifier: ^0.83.4 version: 0.83.4(@babel/core@7.29.0) @@ -255,6 +257,18 @@ importers: '@react-native/typescript-config': specifier: ^0.83.4 version: 0.83.4 + '@rock-js/platform-android': + specifier: ^0.12.12 + version: 0.12.12 + '@rock-js/platform-ios': + specifier: ^0.12.12 + version: 0.12.12(typescript@5.9.3) + '@rock-js/plugin-metro': + specifier: ^0.12.12 + version: 0.12.12(patch_hash=fb21d963fa0452524ca33673321a4a405c81e09817a628b64e4c72eee6c39747) + '@rock-js/provider-github': + specifier: ^0.12.12 + version: 0.12.12 '@testing-library/react-native': specifier: ^13.3.3 version: 13.3.3(jest@29.7.0(@types/node@25.5.0))(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react-test-renderer@19.2.4(react@19.2.4))(react@19.2.4) @@ -289,8 +303,8 @@ importers: specifier: ^1.0.0 version: 1.0.0 better-sqlite3: - specifier: ^12.8.0 - version: 12.8.0 + specifier: ^12.9.0 + version: 12.9.0 drizzle-kit: specifier: 1.0.0-beta.20 version: 1.0.0-beta.20 @@ -319,8 +333,8 @@ importers: specifier: ^7.16.2 version: 7.16.2(eslint@8.57.1)(typescript@5.9.3) hermes-compiler: - specifier: ^250829098.0.2 - version: 250829098.0.2 + specifier: 0.14.1 + version: 0.14.1 husky: specifier: ^7.0.4 version: 7.0.4 @@ -339,6 +353,9 @@ importers: react-test-renderer: specifier: 19.2.4 version: 19.2.4(react@19.2.4) + rock: + specifier: ^0.12.12 + version: 0.12.12(typescript@5.9.3) typescript: specifier: ~5.9.3 version: 5.9.3 @@ -1121,6 +1138,12 @@ packages: react: '*' react-native: '*' + '@clack/core@0.5.0': + resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==} + + '@clack/prompts@0.11.0': + resolution: {integrity: sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==} + '@drizzle-team/brocli@0.11.0': resolution: {integrity: sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg==} @@ -1496,6 +1519,10 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + '@isaacs/ttlcache@1.4.1': resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} engines: {node: '>=12'} @@ -1906,6 +1933,34 @@ packages: react-native-safe-area-context: '>= 4.0.0' react-native-screens: '>= 4.0.0' + '@rock-js/config@0.12.12': + resolution: {integrity: sha512-EMdmUOPQ7TJq4kzHdxID6rJlN64ovPPz5hr3dP3wA5B3t/HWf02idmL28yrOWV3ICgSWMI/2QNAnEadAlwnVZw==} + + '@rock-js/platform-android@0.12.12': + resolution: {integrity: sha512-3CzqSOb6WT+ovAqaHpQ0V+73HO+17AeZVnZydHVWqZQ8frrXD2ik3zDD4Fjqocrouc5MtllNJBKkpscTZPdcQQ==} + + '@rock-js/platform-apple-helpers@0.12.12': + resolution: {integrity: sha512-P0gllR++x5dwAopwX/bV25tzESbp43YglvHK7HeruZcwAvUAEefElaVlaK4Y/go6VkYBYwogt3LF3ceF4vTuOA==} + + '@rock-js/platform-ios@0.12.12': + resolution: {integrity: sha512-/kBq8CCe43eLlqF1VWaDeTnntBcASXNtwUaAKuSbIE5GoBOxgdjeGcuZXnvxLLYKJSHuTrrNO2cF3th1fMki2A==} + + '@rock-js/plugin-metro@0.12.12': + resolution: {integrity: sha512-TeUFkXmOSyl6Wq7G1SKxNbnMrlwuduj833glDmdl8Ug90+6jYCRCsUC47Xy9svKz3XEDBJtEbcQfm0qX8XP30A==} + + '@rock-js/provider-github@0.12.12': + resolution: {integrity: sha512-+5eoluqIVYtBmUC3yLPEmuSG/YdVFpaxVKOe3gIc7V/UZzMNGiaJx6dTeqOh8UDBKJb3Q8KqeV6f7rjKHIrU4g==} + + '@rock-js/tools@0.12.12': + resolution: {integrity: sha512-/uXanOQp2biH92G/2YFqlitH7l+8dQ6oRb4o/GDd5z27gFp3+b1E7xVsyhLumcfEoSzQKm6vjr/7u98d+qAyKQ==} + + '@shopify/flash-list@2.3.1': + resolution: {integrity: sha512-7oktg2NQR7KAODjFoDaWe8/OBzyYbdTE3zQTrUBMxjIbxHTHN7UXRX1hX3DHk8KvtkgQdRfZOV8Gjj2l4fGrXw==} + peerDependencies: + '@babel/runtime': '*' + react: '*' + react-native: '*' + '@sideway/address@4.1.5': resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} @@ -2096,6 +2151,7 @@ packages: '@xmldom/xmldom@0.8.12': resolution: {integrity: sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==} engines: {node: '>=10.0.0'} + deprecated: this version has critical issues, please update to the latest version abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} @@ -2130,6 +2186,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + adm-zip@0.5.17: + resolution: {integrity: sha512-+Ut8d9LLqwEvHHJl1+PIHqoyDxFgVN847JTVM3Izi3xHDWPE4UtzzXysMZQs64DMcrJfBeS/uoEP4AD3HQHnQQ==} + engines: {node: '>=12.0'} + agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -2362,8 +2422,8 @@ packages: resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} engines: {node: '>=12.0.0'} - better-sqlite3@12.8.0: - resolution: {integrity: sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==} + better-sqlite3@12.9.0: + resolution: {integrity: sha512-wqUv4Gm3toFpHDQmaKD4QhZm3g1DjUBI0yzS4UBl6lElUmXFYdTQmmEDpAFa5o8FiFiymURypEnfVHzILKaxqQ==} engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x} big-integer@1.6.52: @@ -2499,6 +2559,10 @@ packages: chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + chrome-launcher@0.15.2: resolution: {integrity: sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==} engines: {node: '>=12.13.0'} @@ -3439,6 +3503,10 @@ packages: fast-xml-builder@1.1.4: resolution: {integrity: sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==} + fast-xml-parser@4.5.6: + resolution: {integrity: sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A==} + hasBin: true + fast-xml-parser@5.5.9: resolution: {integrity: sha512-jldvxr1MC6rtiZKgrFnDSvT8xuH+eJqxqOBThUVjYrxssYTo1avZLGql5l0a0BAERR01CadYzZ83kVEkbyDg+g==} hasBin: true @@ -3536,6 +3604,10 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} + fs-fingerprint@0.11.0: + resolution: {integrity: sha512-EpEtmn1T9bLxxf+506gVdpehs6pAIFAM6UCDtT9/J7tfLXg8FPn+3jmuVnMjjRFshJohR2lb2TZGwuZAhIOcKg==} + engines: {node: '>=20.0.0'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -3669,9 +3741,6 @@ packages: hermes-compiler@0.14.1: resolution: {integrity: sha512-+RPPQlayoZ9n6/KXKt5SFILWXCGJ/LV5d24L5smXrvTDrPS4L6dSctPczXauuvzFP3QEJbD1YO7Z3Ra4a+4IhA==} - hermes-compiler@250829098.0.2: - resolution: {integrity: sha512-9+la7TeGGZg5Cj0UV5MbqhqyT/Hd/PUlQZ3Uhggy0jiaiG2qxFJbi/uGWALTqa7GwETyQa4A7ngus1A1aXA8QQ==} - hermes-eslint@0.33.3: resolution: {integrity: sha512-eGY0l6T5U9LDdC+uN88NrSOrvPPtXGPxN7EaD38hytWuBEVXypq0eQ1SNVsnQPBZLWi+b1jkF4F5aVtTCQC6wg==} @@ -3961,6 +4030,10 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -4696,6 +4769,10 @@ packages: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} + engines: {node: '>= 18'} + mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -4718,6 +4795,10 @@ packages: multitars@0.2.4: resolution: {integrity: sha512-XgLbg1HHchFauMCQPRwMj6MSyDd5koPlTA1hM3rUFkeXzGpjU/I9fP3to7yrObE9jcN8ChIOQGrM0tV0kUZaKg==} + nano-spawn@0.2.1: + resolution: {integrity: sha512-/pULofvsF8mOVcl/nUeVXL/GYOEvc7eJWSIxa+K4OYUolvXa5zwSgevsn4eoHs1xvh/BO3vx/PZiD9+Ow2ZVuw==} + engines: {node: '>=18.19'} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4894,6 +4975,10 @@ packages: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-limit@7.3.0: + resolution: {integrity: sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==} + engines: {node: '>=20'} + p-locate@3.0.0: resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} engines: {node: '>=6'} @@ -5143,16 +5228,6 @@ packages: peerDependencies: react-native: '>=0.47.0' - react-native-config@1.6.1: - resolution: {integrity: sha512-HvKtxr6/Tq3iMdFx5REYZsjCtPi0RxQOMCs15+DqrUPTNFtWHuEuh+zw7fJp+dmuO79YMfdtlsPWIGTHtaXwjg==} - peerDependencies: - react: '*' - react-native: '*' - react-native-windows: '>=0.61' - peerDependenciesMeta: - react-native-windows: - optional: true - react-native-device-info@15.0.2: resolution: {integrity: sha512-dd71eXG2l3Cwp66IvKNadMTB8fhU3PEjyVddI97sYan+D4bgIAUmgGDhbSOFvHcGavksb2U17kiQYaDiK2WK2g==} peerDependencies: @@ -5294,6 +5369,12 @@ packages: react-native: '*' react-native-pager-view: '>= 6.0.0' + react-native-theme-switch-animation@0.8.0: + resolution: {integrity: sha512-z4f3QGSuUP4tagycls2mekng/7uxAbr75Gn0GGm7JRkrviyao++V2CtJ8VUDx+hSOsgfjEhD9D5JubsGbbHB5w==} + peerDependencies: + react: '*' + react-native: '*' + react-native-url-polyfill@3.0.0: resolution: {integrity: sha512-aA5CiuUCUb/lbrliVCJ6lZ17/RpNJzvTO/C7gC/YmDQhTUoRD5q5HlJfwLWcxz4VgAhHwXKzhxH+wUN24tAdqg==} peerDependencies: @@ -5463,6 +5544,10 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + rock@0.12.12: + resolution: {integrity: sha512-wyTwi52tFvM9MFKwwAaz6mgKTF7Djkhg1cqG8r8x9zl4SZGgsDDG/NwSHXUgER7GNZYm1Zx+u6zDFMnRNvvceg==} + hasBin: true + rtl-detect@1.1.2: resolution: {integrity: sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==} @@ -5780,6 +5865,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strnum@1.1.2: + resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==} + strnum@2.2.2: resolution: {integrity: sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA==} @@ -5820,6 +5908,10 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} + tar@7.5.13: + resolution: {integrity: sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==} + engines: {node: '>=18'} + tarn@3.0.2: resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} engines: {node: '>=8.0.0'} @@ -5886,6 +5978,10 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-regex-builder@1.8.2: + resolution: {integrity: sha512-Y8HovHFheDKm/jgLIWSO8o81xA/I9O5AGc3/vNG1sVSskatOifr3SQzAsatBXGLjL3nYhQif1MpwQRS5GF8ADg==} + engines: {node: '>= 18.0.0'} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -6010,10 +6106,12 @@ packages: uuid@7.0.3: resolution: {integrity: sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true v8-to-istanbul@9.3.0: @@ -6193,6 +6291,10 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + yaml@1.10.3: resolution: {integrity: sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==} engines: {node: '>= 6'} @@ -6238,6 +6340,24 @@ packages: zod@4.3.6: resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zustand@5.0.12: + resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + snapshots: '@azure-rest/core-client@2.5.1': @@ -7272,6 +7392,17 @@ snapshots: react-native-saf-x: 2.2.3(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) react-native-zip-archive: 6.1.2(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) + '@clack/core@0.5.0': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@clack/prompts@0.11.0': + dependencies: + '@clack/core': 0.5.0 + picocolors: 1.1.1 + sisteransi: 1.0.5 + '@drizzle-team/brocli@0.11.0': {} '@egjs/hammerjs@2.0.17': @@ -7737,6 +7868,10 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.3 + '@isaacs/ttlcache@1.4.1': {} '@istanbuljs/load-nyc-config@1.1.0': @@ -8016,6 +8151,7 @@ snapshots: execa: 5.1.1 fast-glob: 3.3.3 picocolors: 1.1.1 + optional: true '@react-native-community/cli-config-android@20.1.3': dependencies: @@ -8061,6 +8197,7 @@ snapshots: yaml: 2.8.3 transitivePeerDependencies: - typescript + optional: true '@react-native-community/cli-platform-android@20.1.3': dependencies: @@ -8069,6 +8206,7 @@ snapshots: execa: 5.1.1 logkitty: 0.7.1 picocolors: 1.1.1 + optional: true '@react-native-community/cli-platform-apple@20.1.3': dependencies: @@ -8077,10 +8215,12 @@ snapshots: execa: 5.1.1 fast-xml-parser: 5.5.9 picocolors: 1.1.1 + optional: true '@react-native-community/cli-platform-ios@20.1.3': dependencies: '@react-native-community/cli-platform-apple': 20.1.3 + optional: true '@react-native-community/cli-server-api@20.1.3': dependencies: @@ -8139,6 +8279,7 @@ snapshots: - supports-color - typescript - utf-8-validate + optional: true '@react-native-community/slider@5.1.2': {} @@ -8424,6 +8565,80 @@ snapshots: transitivePeerDependencies: - '@react-native-masked-view/masked-view' + '@rock-js/config@0.12.12': + dependencies: + '@babel/code-frame': 7.29.0 + '@rock-js/provider-github': 0.12.12 + '@rock-js/tools': 0.12.12 + joi: 17.13.3 + tslib: 2.8.1 + + '@rock-js/platform-android@0.12.12': + dependencies: + '@react-native-community/cli-config-android': 20.1.3 + '@rock-js/tools': 0.12.12 + tslib: 2.8.1 + + '@rock-js/platform-apple-helpers@0.12.12(typescript@5.9.3)': + dependencies: + '@react-native-community/cli-config': 20.1.3(typescript@5.9.3) + '@react-native-community/cli-config-apple': 20.1.3 + '@rock-js/tools': 0.12.12 + adm-zip: 0.5.17 + fast-xml-parser: 4.5.6 + tslib: 2.8.1 + transitivePeerDependencies: + - typescript + + '@rock-js/platform-ios@0.12.12(typescript@5.9.3)': + dependencies: + '@react-native-community/cli-config-apple': 20.1.3 + '@react-native-community/cli-types': 20.1.3 + '@rock-js/platform-apple-helpers': 0.12.12(typescript@5.9.3) + '@rock-js/tools': 0.12.12 + tslib: 2.8.1 + transitivePeerDependencies: + - typescript + + '@rock-js/plugin-metro@0.12.12(patch_hash=fb21d963fa0452524ca33673321a4a405c81e09817a628b64e4c72eee6c39747)': + dependencies: + '@react-native-community/cli-server-api': 20.1.3 + '@rock-js/tools': 0.12.12 + metro: 0.83.5 + metro-config: 0.83.5 + metro-core: 0.83.5 + metro-resolver: 0.83.5 + tslib: 2.8.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@rock-js/provider-github@0.12.12': + dependencies: + '@rock-js/tools': 0.12.12 + ts-regex-builder: 1.8.2 + tslib: 2.8.1 + + '@rock-js/tools@0.12.12': + dependencies: + '@clack/prompts': 0.11.0 + adm-zip: 0.5.17 + appdirsjs: 1.2.7 + fs-fingerprint: 0.11.0 + is-unicode-supported: 2.1.0 + nano-spawn: 0.2.1 + picocolors: 1.1.1 + string-argv: 0.3.2 + tar: 7.5.13 + tslib: 2.8.1 + + '@shopify/flash-list@2.3.1(@babel/runtime@7.29.2)(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + react: 19.2.4 + react-native: 0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4) + '@sideway/address@4.1.5': dependencies: '@hapi/hoek': 9.3.0 @@ -8699,6 +8914,8 @@ snapshots: acorn@8.16.0: {} + adm-zip@0.5.17: {} + agent-base@6.0.2: dependencies: debug: 4.4.3(supports-color@9.4.0) @@ -8732,6 +8949,7 @@ snapshots: colorette: 1.4.0 slice-ansi: 2.1.0 strip-ansi: 5.2.0 + optional: true ansi-regex@4.1.1: {} @@ -8825,7 +9043,8 @@ snapshots: asap@2.0.6: {} - astral-regex@1.0.0: {} + astral-regex@1.0.0: + optional: true astral-regex@2.0.0: {} @@ -9008,7 +9227,7 @@ snapshots: dependencies: open: 8.4.2 - better-sqlite3@12.8.0: + better-sqlite3@12.9.0: dependencies: bindings: 1.5.0 prebuild-install: 7.1.3 @@ -9177,6 +9396,8 @@ snapshots: chownr@1.1.4: {} + chownr@3.0.0: {} + chrome-launcher@0.15.2: dependencies: '@types/node': 25.5.0 @@ -9230,6 +9451,7 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 6.2.0 + optional: true cliui@8.0.1: dependencies: @@ -9285,7 +9507,8 @@ snapshots: color-convert: 3.1.3 color-string: 2.1.4 - colorette@1.4.0: {} + colorette@1.4.0: + optional: true colorette@2.0.20: {} @@ -9293,7 +9516,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 - command-exists@1.2.9: {} + command-exists@1.2.9: + optional: true commander@11.1.0: {} @@ -9430,7 +9654,8 @@ snapshots: optionalDependencies: supports-color: 9.4.0 - decamelize@1.2.0: {} + decamelize@1.2.0: + optional: true decimal.js@10.6.0: {} @@ -9549,7 +9774,7 @@ snapshots: get-tsconfig: 4.13.7 jiti: 2.6.1 - drizzle-orm@1.0.0-beta.20(@op-engineering/op-sqlite@15.2.9(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@sinclair/typebox@0.34.49)(@types/better-sqlite3@7.6.13)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(better-sqlite3@12.8.0)(expo-sqlite@16.0.10(expo@55.0.9)(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(mssql@11.0.1(@azure/core-client@1.10.1))(zod@4.3.6): + drizzle-orm@1.0.0-beta.20(@op-engineering/op-sqlite@15.2.9(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(@sinclair/typebox@0.34.49)(@types/better-sqlite3@7.6.13)(@types/mssql@9.1.9(@azure/core-client@1.10.1))(better-sqlite3@12.9.0)(expo-sqlite@16.0.10(expo@55.0.9)(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4))(mssql@11.0.1(@azure/core-client@1.10.1))(zod@4.3.6): dependencies: '@types/mssql': 9.1.9(@azure/core-client@1.10.1) mssql: 11.0.1(@azure/core-client@1.10.1) @@ -9557,7 +9782,7 @@ snapshots: '@op-engineering/op-sqlite': 15.2.9(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) '@sinclair/typebox': 0.34.49 '@types/better-sqlite3': 7.6.13 - better-sqlite3: 12.8.0 + better-sqlite3: 12.9.0 expo-sqlite: 16.0.10(expo@55.0.9)(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) zod: 4.3.6 @@ -9601,7 +9826,8 @@ snapshots: env-paths@2.2.1: {} - envinfo@7.21.0: {} + envinfo@7.21.0: + optional: true error-ex@1.3.4: dependencies: @@ -10166,6 +10392,10 @@ snapshots: dependencies: path-expression-matcher: 1.2.0 + fast-xml-parser@4.5.6: + dependencies: + strnum: 1.1.2 + fast-xml-parser@5.5.9: dependencies: fast-xml-builder: 1.1.4 @@ -10269,6 +10499,12 @@ snapshots: graceful-fs: 4.2.11 jsonfile: 4.0.0 universalify: 0.1.2 + optional: true + + fs-fingerprint@0.11.0: + dependencies: + p-limit: 7.3.0 + tinyglobby: 0.2.15 fs.realpath@1.0.0: {} @@ -10401,8 +10637,6 @@ snapshots: hermes-compiler@0.14.1: {} - hermes-compiler@250829098.0.2: {} - hermes-eslint@0.33.3: dependencies: esrecurse: 4.3.0 @@ -10620,7 +10854,8 @@ snapshots: dependencies: call-bound: 1.0.4 - is-fullwidth-code-point@2.0.0: {} + is-fullwidth-code-point@2.0.0: + optional: true is-fullwidth-code-point@3.0.0: {} @@ -10695,6 +10930,8 @@ snapshots: is-unicode-supported@0.1.0: {} + is-unicode-supported@2.1.0: {} + is-weakmap@2.0.2: {} is-weakref@1.1.1: @@ -11229,6 +11466,7 @@ snapshots: jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 + optional: true jsonwebtoken@9.0.3: dependencies: @@ -11433,6 +11671,7 @@ snapshots: ansi-fragments: 0.2.1 dayjs: 1.11.20 yargs: 15.4.1 + optional: true long@5.3.2: {} @@ -11886,6 +12125,10 @@ snapshots: minipass@7.1.3: {} + minizlib@3.1.0: + dependencies: + minipass: 7.1.3 + mkdirp-classic@0.5.3: {} mkdirp@1.0.4: {} @@ -11908,6 +12151,8 @@ snapshots: multitars@0.2.4: {} + nano-spawn@0.2.1: {} + nanoid@3.3.11: {} napi-build-utils@2.0.0: {} @@ -11941,7 +12186,8 @@ snapshots: node-releases@2.0.36: {} - node-stream-zip@1.15.0: {} + node-stream-zip@1.15.0: + optional: true normalize-path@3.0.0: {} @@ -12100,6 +12346,10 @@ snapshots: dependencies: yocto-queue: 1.2.2 + p-limit@7.3.0: + dependencies: + yocto-queue: 1.2.2 + p-locate@3.0.0: dependencies: p-limit: 2.3.0 @@ -12354,11 +12604,6 @@ snapshots: eventemitter3: 4.0.7 react-native: 0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4) - react-native-config@1.6.1(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-native: 0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4) - react-native-device-info@15.0.2(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4)): dependencies: react-native: 0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4) @@ -12497,6 +12742,11 @@ snapshots: react-native-pager-view: 8.0.0(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4) use-latest-callback: 0.2.6(react@19.2.4) + react-native-theme-switch-animation@0.8.0(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4))(react@19.2.4): + dependencies: + react: 19.2.4 + react-native: 0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4) + react-native-url-polyfill@3.0.0(react-native@0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4)): dependencies: react-native: 0.83.4(@babel/core@7.29.0)(@react-native-community/cli@20.1.3(typescript@5.9.3))(@react-native/metro-config@0.83.4(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.4) @@ -12667,7 +12917,8 @@ snapshots: require-directory@2.1.1: {} - require-main-filename@2.0.0: {} + require-main-filename@2.0.0: + optional: true require-resolve@0.0.2: dependencies: @@ -12724,6 +12975,18 @@ snapshots: dependencies: glob: 7.2.3 + rock@0.12.12(typescript@5.9.3): + dependencies: + '@react-native-community/cli-config': 20.1.3(typescript@5.9.3) + '@rock-js/config': 0.12.12 + '@rock-js/tools': 0.12.12 + adm-zip: 0.5.17 + commander: 12.1.0 + tar: 7.5.13 + tslib: 2.8.1 + transitivePeerDependencies: + - typescript + rtl-detect@1.1.2: {} run-applescript@7.1.0: {} @@ -12811,7 +13074,8 @@ snapshots: server-only@0.0.1: {} - set-blocking@2.0.0: {} + set-blocking@2.0.0: + optional: true set-function-length@1.2.2: dependencies: @@ -12906,6 +13170,7 @@ snapshots: ansi-styles: 3.2.1 astral-regex: 1.0.0 is-fullwidth-code-point: 2.0.0 + optional: true slice-ansi@3.0.0: dependencies: @@ -13088,6 +13353,8 @@ snapshots: strip-json-comments@3.1.1: {} + strnum@1.1.2: {} + strnum@2.2.2: {} structured-headers@0.4.1: {} @@ -13130,6 +13397,14 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + tar@7.5.13: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.3 + minizlib: 3.1.0 + yallist: 5.0.0 + tarn@3.0.2: {} tedious@18.6.2(@azure/core-client@1.10.1): @@ -13218,6 +13493,8 @@ snapshots: dependencies: typescript: 5.9.3 + ts-regex-builder@1.8.2: {} + tslib@2.8.1: {} tunnel-agent@0.6.0: @@ -13299,7 +13576,8 @@ snapshots: unicorn-magic@0.1.0: {} - universalify@0.1.2: {} + universalify@0.1.2: + optional: true universalify@0.2.0: {} @@ -13422,7 +13700,8 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-module@2.0.1: {} + which-module@2.0.1: + optional: true which-typed-array@1.1.20: dependencies: @@ -13493,12 +13772,15 @@ snapshots: xmlchars@2.2.0: {} - y18n@4.0.3: {} + y18n@4.0.3: + optional: true y18n@5.0.8: {} yallist@3.1.1: {} + yallist@5.0.0: {} + yaml@1.10.3: {} yaml@2.8.3: {} @@ -13507,6 +13789,7 @@ snapshots: dependencies: camelcase: 5.3.1 decamelize: 1.2.0 + optional: true yargs-parser@21.1.1: {} @@ -13523,6 +13806,7 @@ snapshots: which-module: 2.0.1 y18n: 4.0.3 yargs-parser: 18.1.3 + optional: true yargs@17.7.2: dependencies: @@ -13545,3 +13829,9 @@ snapshots: zod@3.25.76: {} zod@4.3.6: {} + + zustand@5.0.12(@types/react@19.2.14)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)): + optionalDependencies: + '@types/react': 19.2.14 + react: 19.2.4 + use-sync-external-store: 1.6.0(react@19.2.4) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0900ce43a0..94024e48a4 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,9 @@ +nodeLinker: hoisted + onlyBuiltDependencies: - better-sqlite3 - esbuild - protobufjs + +patchedDependencies: + '@rock-js/plugin-metro@0.12.12': patches/@rock-js__plugin-metro@0.12.12.patch diff --git a/rock.config.mjs b/rock.config.mjs new file mode 100644 index 0000000000..0ef72aec5a --- /dev/null +++ b/rock.config.mjs @@ -0,0 +1,24 @@ +// @ts-check +import { platformIOS } from '@rock-js/platform-ios'; +import { platformAndroid } from '@rock-js/platform-android'; +import { pluginMetro } from '@rock-js/plugin-metro'; +import { providerGitHub } from '@rock-js/provider-github'; +import { loadEnvFile } from 'node:process'; + +// Loads environment variables from the default .env file +loadEnvFile(); + +/** @type {import('rock').Config} */ +export default { + bundler: pluginMetro(), + platforms: { + ios: platformIOS(), + android: platformAndroid(), + }, + remoteCacheProvider: providerGitHub({ + repository: process.env.REPO_NAME || 'lnreader', + owner: process.env.REPO_OWNER || 'lnreader', + //@ts-expect-error + token: process.env.GITHUB_TOKEN, + }), +}; diff --git a/scripts/generate-env-file.cjs b/scripts/generate-env-file.cjs index ff7ee15b2e..f020cd56b9 100644 --- a/scripts/generate-env-file.cjs +++ b/scripts/generate-env-file.cjs @@ -1,59 +1,166 @@ const fs = require('fs'); -const os = require('os'); const path = require('path'); const { execSync } = require('child_process'); -const formattedDate = new Date().getTime(); -const commitHash = execSync('git rev-parse --short HEAD').toString().trim(); -const buildType = process.argv[2] || 'Beta'; +function parseArgs(argv) { + const out = {}; -const newEnvVars = [ - `BUILD_TYPE=${buildType}`, - `GIT_HASH=${commitHash}`, - `RELEASE_DATE=${formattedDate}`, - `NODE_ENV=${buildType === 'Release' ? 'production' : 'development'}`, -].join(os.EOL); + for (let i = 2; i < argv.length; i += 1) { + const token = argv[i]; -const envFilePath = path.join(__dirname, '..', '.env'); -let existingEnvData = ''; + if (!token.startsWith('--')) { + continue; + } -try { - if (fs.existsSync(envFilePath)) { - const existingContent = fs.readFileSync(envFilePath, 'utf8'); - - existingEnvData = existingContent - .split(os.EOL) - .filter(line => { - const trimmedLine = line.trim(); - return ( - trimmedLine && - !trimmedLine.startsWith('BUILD_TYPE=') && - !trimmedLine.startsWith('GIT_HASH=') && - !trimmedLine.startsWith('RELEASE_DATE=') && - !trimmedLine.startsWith('NODE_ENV=') - ); - }) - .join(os.EOL); + const eqIndex = token.indexOf('='); + + if (eqIndex !== -1) { + out[token.slice(2, eqIndex)] = token.slice(eqIndex + 1); + continue; + } + + const key = token.slice(2); + const next = argv[i + 1]; + + if (next && !next.startsWith('--')) { + out[key] = next; + i += 1; + } else { + out[key] = true; + } } -} catch (err) { - console.warn('Warning: Could not read existing .env file:', err.message); + + return out; +} + +function formatUtcDate(date) { + const pad = n => String(n).padStart(2, '0'); + + const day = pad(date.getUTCDate()); + const month = pad(date.getUTCMonth() + 1); + const year = String(date.getUTCFullYear()).slice(-2); + + let hours = date.getUTCHours(); + const minutes = pad(date.getUTCMinutes()); + const ampm = hours >= 12 ? 'PM' : 'AM'; + + hours %= 12; + if (hours === 0) { + hours = 12; + } + + return `${day}/${month}/${year} ${pad(hours)}:${minutes} ${ampm} UTC`; +} + +function getGitHash() { + return execSync('git rev-parse --short HEAD').toString().trim(); +} + +function getHiddenEnvFiles(rootDir) { + return fs + .readdirSync(rootDir, { withFileTypes: true }) + .filter(entry => { + return ( + entry.isFile() && + /^\..*\.env$/.test(entry.name) && + entry.name !== '.env' + ); + }) + .map(entry => path.join(rootDir, entry.name)) + .sort(); } -const finalContent = existingEnvData - ? `${newEnvVars}${os.EOL}${existingEnvData}${os.EOL}` - : `${newEnvVars}${os.EOL}`; +function readHiddenEnvFiles(rootDir) { + const files = getHiddenEnvFiles(rootDir); + + const content = files + .map(filePath => { + const fileName = path.basename(filePath); + const fileContent = fs.readFileSync(filePath, 'utf8').trimEnd(); + + return `# Imported from ${fileName}\n${fileContent}`; + }) + .join('\n\n'); + + return { files, content }; +} + +const args = parseArgs(process.argv); +const projectRoot = path.join(__dirname, '..'); + +const buildType = args['build-type'] || 'Beta'; +const myanimelistClientId = args['myanimelist-client-id']; +const anilistClientId = args['anilist-client-id']; + +const gitHash = args['git-hash'] || getGitHash(); +const releaseDate = args['release-date'] || formatUtcDate(new Date()); +const nodeEnv = + args['node-env'] || + (buildType.toLowerCase().includes('release') ? 'production' : 'development'); + +const generatedEnvContent = [ + `BUILD_TYPE=${JSON.stringify(buildType)}`, + `GIT_HASH=${JSON.stringify(gitHash)}`, + `RELEASE_DATE=${JSON.stringify(releaseDate)}`, + `NODE_ENV=${JSON.stringify(nodeEnv)}`, + `MYANIMELIST_CLIENT_ID=${JSON.stringify(myanimelistClientId)}`, + `ANILIST_CLIENT_ID=${JSON.stringify(anilistClientId)}`, + '', +].join('\n'); + +const { files: hiddenEnvFiles, content: hiddenEnvContent } = + readHiddenEnvFiles(projectRoot); + +const envContent = hiddenEnvContent + ? `${generatedEnvContent}\n# Imported hidden env files\n${hiddenEnvContent}\n` + : generatedEnvContent; + +const envFilePath = path.join(projectRoot, '.env'); +const buildInfoPath = path.join( + projectRoot, + 'src', + 'generated', + 'build-info.ts', +); + +const buildInfoContent = `// This file is generated. Do not edit manually. +export const BUILD_TYPE = ${JSON.stringify(buildType)}; +export const GIT_HASH = ${JSON.stringify(gitHash)}; +export const RELEASE_DATE = ${JSON.stringify(releaseDate)}; +export const NODE_ENV = ${JSON.stringify(nodeEnv)}; +export const MYANIMELIST_CLIENT_ID = ${JSON.stringify(myanimelistClientId)}; +export const ANILIST_CLIENT_ID = ${JSON.stringify(anilistClientId)}; + +export default { + BUILD_TYPE, + GIT_HASH, + RELEASE_DATE, + NODE_ENV, + MYANIMELIST_CLIENT_ID, + ANILIST_CLIENT_ID, +}; +`; try { - fs.writeFileSync(envFilePath, finalContent, 'utf8'); + fs.mkdirSync(path.dirname(buildInfoPath), { recursive: true }); + fs.writeFileSync(buildInfoPath, buildInfoContent, 'utf8'); + fs.writeFileSync(envFilePath, envContent, 'utf8'); + + console.log(`Generated .env for ${buildType} build`); + + if (hiddenEnvFiles.length > 0) { + console.log( + `Imported ${hiddenEnvFiles.length} hidden env file(s):`, + hiddenEnvFiles.map(filePath => path.basename(filePath)), + ); + } - console.log(`Generated .env file for ${buildType} build\n`); console.table({ BUILD_TYPE: buildType, - GIT_HASH: commitHash, - RELEASE_DATE: formattedDate, - NODE_ENV: buildType === 'Release' ? 'production' : 'development', + GIT_HASH: gitHash, + RELEASE_DATE: releaseDate, + NODE_ENV: nodeEnv, }); - console.log('\n'); } catch (err) { console.error('Error: Could not write .env file:', err.message); process.exit(1); diff --git a/src/components/BottomTabBar/index.tsx b/src/components/BottomTabBar/index.tsx index 1cea197898..6a1467ffb9 100644 --- a/src/components/BottomTabBar/index.tsx +++ b/src/components/BottomTabBar/index.tsx @@ -5,6 +5,7 @@ import { Pressable, View, StyleSheet } from 'react-native'; import { Text } from 'react-native-paper'; import { ThemeColors } from '@theme/types'; import Animated from 'react-native-reanimated'; +import Color from 'color'; interface CustomBottomTabBarProps extends BottomTabBarProps { theme: ThemeColors; @@ -27,6 +28,7 @@ function CustomBottomTabBar({ showLabelsInNav, renderIcon, }: CustomBottomTabBarProps) { + const transparentBg = Color(theme.primaryContainer).fade(1).rgb().toString(); const getLabelText = useCallback( (route: any) => { if (!showLabelsInNav && route.name !== state.routeNames[state.index]) { @@ -103,7 +105,7 @@ function CustomBottomTabBar({ width: isFocused ? 64 : 32, backgroundColor: isFocused ? theme.primaryContainer - : 'transparent', + : transparentBg, }, ]} > diff --git a/src/components/ColorPickerModal/ColorPickerModal.tsx b/src/components/ColorPickerModal/ColorPickerModal.tsx index a59c7d1cc5..51723c3441 100644 --- a/src/components/ColorPickerModal/ColorPickerModal.tsx +++ b/src/components/ColorPickerModal/ColorPickerModal.tsx @@ -2,14 +2,16 @@ import React, { useState } from 'react'; import { FlatList, Pressable, StyleSheet, Text, View } from 'react-native'; import { Portal, TextInput } from 'react-native-paper'; -import { Modal } from '@components'; +import { Button, Modal } from '@components'; import { ThemeColors } from '../../theme/types'; +import { Row } from '@components/Common'; +import { getString } from '@strings/translations'; interface ColorPickerModalProps { visible: boolean; title: string; color: string; - onSubmit: (val: string) => void; + onSubmit: (val: string | undefined) => void; closeModal: () => void; theme: ThemeColors; showAccentColors?: boolean; @@ -47,6 +49,10 @@ const ColorPickerModal: React.FC = ({ setError('Enter a valid hex color code'); } }; + const onReset = () => { + onSubmit(undefined); + closeModal(); + }; const accentColors = [ '#EF5350', @@ -112,6 +118,10 @@ const ColorPickerModal: React.FC = ({ error={Boolean(error)} /> {error} + +