Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - protected areas backend #194

Open
wants to merge 30 commits into
base: develop
Choose a base branch
from

Conversation

rupamkairi
Copy link
Contributor

@rupamkairi rupamkairi commented Feb 19, 2025

Caution: Do not Directly Merge -

  1. Too many versional changes is in here.
  2. I'll Post a Different Cherry Picked Commit For this feature

Changes in this pull request:

  1. Migrations related to ProtectedAreas
  2. APIs related to the Features (on the trpc)
  • SiteAlert Creation
  • Notification Generation

@

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced enhanced management for protected sites with improved alert handling and multi-user notifications.
    • Added new API endpoint for migrating site data to site relations.
    • Implemented new procedures for finding, creating, and updating protected sites.
    • Added new optional fields in environment variable schema for API configurations.
    • Introduced a new configuration for Metro in a React Native project to improve module resolution.
    • Added new string resources for application name and authentication domain.
  • Improvements

    • Upgraded the mobile app to version 1.3 with refined startup and display behavior.
    • Streamlined authentication and session management for a smoother, more secure login experience.
    • Updated build configurations and security settings to boost overall stability and performance.
    • Enhanced the Prisma schema to support new site relations and external IDs.
    • Updated dependencies and scripts in the server and mobile app for better performance and compatibility.

These changes deliver a more reliable and responsive experience while ensuring enhanced security and better handling of site-related updates.

sentry upgrade (since older profiling setup has changed recently)

ignored locally added .prettierignore (prevents local file formatting)
Trigger Commit
+ different directUrl & shadowDatabaseUrl.
+ develop_baseline migration added.
+ model UserSiteRelation
+ enum SiteKind, UserSiteRealtionRole
+ columns Site.kind, Site.userId
+ model UserSiteRelation
+ enum SiteKind, UserSiteRealtionRole
+ columns Site.kind, Site.userId
Along goes some queries with it.
Update env.mjs for protected_planet apis envs made optional.
Preventing duplication on joinProtectedSite
Join by (siteId or externalId i.e., WDPA_ID)
Copy link

vercel bot commented Feb 19, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
fire-alert ✅ Ready (Inspect) Visit Preview Feb 27, 2025 2:15am

Copy link

coderabbitai bot commented Feb 19, 2025

Walkthrough

The changes span across multiple parts of the project, including updates to ignore and configuration files, formatting and dependency upgrades in the React Native application, revisions to Android build settings, and significant server-side enhancements. Notable modifications include migration of main activity files from Java to Kotlin, adjustments in module import paths, new authentication hook logic in AppNavigator, updates to Prisma schema and migrations, and revised Sentry and environment configurations on the server.

Changes

File(s) Change Summary
.gitignore (root)
Readme.MD
Added .prettierignore and re-added .idea to ignore; formatting adjustments and newline additions in Readme.
apps/nativeapp/.eslintrc.js
apps/nativeapp/.gitignore
.node-version
.ruby-version
apps/nativeapp/Gemfile
Updated ESLint “extends” property; refined ignore patterns for Xcode, Pods, Yarn, and coverage; removed Node and Ruby version files; updated Ruby version and gem dependencies.
apps/nativeapp/__tests__/App-test.tsx Adjusted import paths for the App component and added explicit Jest globals import.
apps/nativeapp/android/app/build.gradle
.../AndroidManifest.xml
.../MainActivity.java
.../MainActivity.kt
.../MainApplication.java and .kt
apps/nativeapp/android/build.gradle
.../gradle/wrapper/*
.../gradlew*
apps/nativeapp/android/settings.gradle
Integrated Kotlin plugin into Android build; updated version codes, version names, SDK versions, and build tools; removed obsolete architecture and Flipper files; updated Gradle and wrapper properties; revised Mapbox Maven authentication and plugin paths.
apps/nativeapp/app/** (components, screens, routes) Standardized import paths with correct casing; refactored authentication in AppNavigator (added token refresh, error handling using useAuth0 hook); commented out WhatsApp notifications in Settings; various formatting and minor import adjustments across screens and components.
apps/nativeapp/babel.config.js
apps/nativeapp/metro.config.js
apps/nativeapp/jest.config.js
apps/nativeapp/tsconfig.json
apps/nativeapp/index.js
Updated Babel preset and added module-resolver; modified Metro configuration for monorepo support; introduced Jest config; updated TypeScript configuration; fixed case in the App import.
apps/nativeapp/package.json Modified Android run script flags; upgraded React Native from 0.71.1 to 0.74.3; added React dependency; updated authentication and various devDependencies; added engines field for Node.js ≥18.
apps/server/** (instrumentation, package.json, prisma migrations & schema, Sentry configs, API routes, Zod schemas, env files, sample data) Added a new instrumentation function for conditional Sentry configuration; updated server package.json with a new Prisma Studio script and upgraded Sentry packages; introduced several Prisma migration scripts and schema modifications (new enums, relations, optional fields); updated Sentry profiling integration imports; enhanced API routers with new procedures for protected sites and added migration and utility endpoints; expanded environment variable schema with new optional settings.

Sequence Diagram(s)

sequenceDiagram
    participant A as AppNavigator
    participant H as useAuth0 Hook
    participant F as Token Validator
    participant R as refreshUserToken
    participant S as State Manager

    A->>H: Initialize authentication state
    H->>F: Check token expiry via hasTimestampExpiredOrCloseToExpiry
    alt Token valid
      F-->>H: Token is valid
    else Token expired/close to expiry
      F-->>A: Token expired condition
      A->>R: Invoke refreshUserToken (after connectivity check)
      R-->>A: Return new token (or error)
      alt Refresh successful
         A->>S: Update credentials/state with new token
      else Refresh failed
         A->>S: Clear credentials & session
      end
    end
Loading

Poem

I'm a little rabbit, hopping with delight,
Changes are blooming, coding feels light.
New imports and hooks, like carrots so bright,
From Kotlin to schemas, all set just right.
I nibble on bugs, let revisions take flight.
CodeRabbit cheers—let’s hop into the night!
🥕🐇 Happy coding!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

🧹 Nitpick comments (31)
apps/nativeapp/Gemfile (2)

6-7: Grammar Suggestion for Cocoapods Comment.
The comment on Cocoapods contains a minor grammatical issue. Consider revising “which break the build” to “which breaks the build” for clarity.


8-9: Gem Ordering Suggestion.
Based on our RuboCop guidelines, gems should be listed in alphabetical order. Currently, 'cocoapods' appears before 'activesupport', but alphabetically, 'activesupport' should come first.

Apply the following diff to reorder the gems:

-gem 'cocoapods', '>= 1.13', '< 1.15'
-gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
+gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
+gem 'cocoapods', '>= 1.13', '< 1.15'
🧰 Tools
🪛 RuboCop (1.69.1)

[convention] 9-9: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem activesupport should appear before cocoapods.

(Bundler/OrderedGems)

apps/nativeapp/ios/FireAlert.xcodeproj/xcshareddata/xcschemes/FireAlert.xcscheme (1)

44-44: Verify if changing launch configuration to Debug was intentional.

This change switches the launch configuration from Release to Debug mode, which seems unrelated to the PR's objectives of implementing protected areas backend features. While Debug mode is useful during development, it has performance implications and should typically be a temporary local change.

Consider:

  1. Is this change intentional or accidentally committed?
  2. Should this be kept in Release mode for consistency across the team?
apps/server/package.json (1)

28-29: Sentry Dependency Version Upgrade
Upgrading "@sentry/nextjs" and "@sentry/profiling-node" to version "^8.47.0" aligns with the updated Sentry configurations (e.g., using nodeProfilingIntegration in your config files). Ensure that all breaking changes introduced in Sentry v8 are accounted for in the existing error tracking and profiling setup.

apps/nativeapp/.gitignore (2)

71-73: Review the Turbo ignore rules for consistency.
The file now lists both .turbo and /turbo/. While this may be intentional (ignoring a file and a directory separately), consider if a recursive pattern (e.g., **/turbo/) might better cover cases where a Turbo folder appears at various levels.


77-83: Yarn directory ignore with selective tracking.
Ignoring all .yarn/* while explicitly unignoring patches, plugins, releases, sdks, and versions provides a granular approach to managing Yarn files. This configuration seems well thought out; please confirm that these exceptions cover all the necessary artifacts you intend to track.

apps/nativeapp/app/screens/CreatePolygon/CreatePolygon.tsx (1)

30-30: Naming Concern: Potential Shadowing of the Global "Map" Object

The import on line 30 now reads:

import Map from './MapMarking/Map';

This name “Map” might shadow the global JavaScript Map object, which could lead to confusion or unintended behavior in certain contexts. Consider renaming the imported component to something like CustomMap or another descriptive name. Note that if you rename it, you'll need to update all its usages in the component accordingly.

[static_analysis]

🧰 Tools
🪛 Biome (1.9.4)

[error] 30-30: Do not shadow the global "Map" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

apps/nativeapp/ios/Podfile (1)

38-44: Consider enabling ccache for faster builds.

The post_install configuration is well-structured. Consider uncommenting the ccache_enabled option to improve build times, especially in CI/CD pipelines.

  react_native_post_install(
    installer,
    config[:reactNativePath],
    :mac_catalyst_enabled => false,
-   # :ccache_enabled => true
+   :ccache_enabled => true
  )
🧰 Tools
🪛 RuboCop (1.69.1)

[convention] 42-42: Avoid comma after the last parameter of a method call.

(Style/TrailingCommaInArguments)

apps/nativeapp/app/components/layerModal/LayerModal.tsx (1)

16-19: Improve type safety and accessibility.

Consider the following improvements:

  1. Replace any type with proper function type for onRequestClose
  2. Remove unnecessary optional chaining on static array items
  3. Add accessibility properties for better screen reader support

Apply these changes:

 interface ILayerModalProps {
   visible: boolean;
-  onRequestClose?: any;
+  onRequestClose?: () => void;
 }

 // ...

-            <View key={item?.title}>
+            <View key={item.title}>
               <TouchableOpacity
-                onPress={() => selectMapLayer(item?.value)}
+                onPress={() => selectMapLayer(item.value)}
+                accessibilityRole="radio"
+                accessibilityState={{ selected: item.value === state }}
+                accessibilityLabel={`Select ${item.title} map layer`}
                 style={styles.layerTextContainer}>
                 <Text
                   style={[
                     styles.layerText,
-                    item?.value === state && {
+                    item.value === state && {
                       fontFamily: Typography.FONT_FAMILY_BOLD,
                       color: Colors.GRADIENT_PRIMARY,
                     },
                   ]}>
-                  {item?.title}
+                  {item.title}
                 </Text>
-                {item?.value === state && <LayerCheck />}
+                {item.value === state && <LayerCheck />}
               </TouchableOpacity>

Also applies to: 43-59

apps/server/src/server/api/routers/sample.json (1)

1-258: Consider enhancing the test data and adding schema validation.

The test data structure looks good but could benefit from:

  1. Schema validation using JSON Schema
  2. Additional test cases:
    • Invalid geometries
    • Edge cases (e.g., polygons crossing the international date line)
    • Different polygon types (e.g., polygons with holes)
  3. Validation of coordinate ranges:
    • Longitude: -180 to 180
    • Latitude: -90 to 90

Consider adding a JSON Schema file to validate the data structure:

// sample.schema.json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "items": {
    "type": "object",
    "required": ["name", "country", "externalId", "geometry"],
    "properties": {
      "name": { "type": "string", "minLength": 1 },
      "country": { "type": "string", "minLength": 1 },
      "externalId": { "type": "string", "pattern": "^[A-Z]{2}[0-9]+$" },
      "geometry": {
        "type": "object",
        "required": ["coordinates", "type"],
        "properties": {
          "type": { "const": "Polygon" },
          "coordinates": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "array",
                "items": {
                  "type": "number",
                  "minimum": -180,
                  "maximum": 180
                },
                "minItems": 2,
                "maxItems": 2
              },
              "minItems": 4
            },
            "minItems": 1
          }
        }
      }
    }
  }
}
apps/server/src/server/api/routers/site.ts (5)

2-2: Consider removing unused imports.
It appears joinProtectedSiteParams is imported but only used in commented-out code. If it's not needed in the final implementation, removing it helps keep the import list clean.


12-13: Enforce environment variable checks.
Before referencing NEXT_PUBLIC_PROTECTED_PLANET_ENDPOINT or NEXT_PUBLIC_PROTECTED_PLANET_API_KEY, consider verifying that these env variables exist to avoid runtime issues.


112-156: Clarify the DB query vs. placeholder usage.
Currently, findProtectedSites returns results from filterByName(query) while a DB retrieval is commented out. If this is a placeholder, encourage removing or refactoring the commented code to keep the codebase clean.


347-431: Remove or document commented-out procedure.
The entire joinProtectedSite procedure is commented out. Keeping large commented blocks around can confuse future maintainers. If it's no longer needed, remove it; otherwise, add clear documentation explaining its future use.


439-439: Implement or remove TODO.
A TODO remains to test the scenario when the returned array is empty or errors. This can be forgotten over time; consider proactively addressing it or opening an issue.

apps/server/instrumentation.ts (1)

1-9: Provide fallback or error handling for unrecognized runtimes.
Current logic only conditionally imports Sentry configs for "nodejs" or "edge". If process.env.NEXT_RUNTIME is missing or not set to these values, the function will silently do nothing. Consider handling or logging such cases.

apps/server/src/pages/api/migrations/site_userId-to-siterelations.ts (1)

4-5: Consider making batch parameters configurable.

The hard-coded values for BATCH_SIZE and DELAY should be configurable through environment variables to allow tuning based on the deployment environment.

-const BATCH_SIZE = 2;
-const DELAY = 1000;
+const BATCH_SIZE = Number(process.env.MIGRATION_BATCH_SIZE ?? 2);
+const DELAY = Number(process.env.MIGRATION_DELAY ?? 1000);
apps/server/src/server/api/zodSchemas/site.schema.ts (2)

62-62: Remove commented code.

Remove the commented-out schema definition as it's no longer needed and could cause confusion.

-// export const createProtectedSiteSchema = protectedSiteSchema;

41-51: Consider reusing the base site schema.

The protectedSiteSchema largely duplicates the structure of createSiteSchema. Consider creating a base schema and extending it for specific use cases.

+const baseSiteSchema = z.object({
+    type: z.enum(["Point", "Polygon", "MultiPolygon"]),
+    name: nameSchema.optional(),
+    geometry: z.union([PointSchema, PolygonSchema, MultiPolygonSchema]),
+    radius: z.number().optional().default(0),
+}).refine((obj) => obj.type === obj.geometry.type, {
+    message: "geometry type does not match the specified type",
+    path: ["geometry.type", "type"],
+});

-export const protectedSiteSchema = z.object({
-    type: z.enum(["Point", "Polygon", "MultiPolygon"]),
-    name: nameSchema.optional(),
-    geometry: z.union([PointSchema, PolygonSchema, MultiPolygonSchema]),
-    radius: z.number().optional().default(0),
+export const protectedSiteSchema = baseSiteSchema.extend({
     externalId: z.string().optional(),
     isActive: z.boolean().optional(),
-}).refine((obj) => obj.type === obj.geometry.type, {
-    message: "geometry type does not match the specified type",
-    path: ["geometry.type", "type"],
 });
apps/server/prisma/migrations/20250107025619_protected_areas_02/migration.sql (1)

1-2: Consider adding an index for the externalId column.

If this column will be used in queries (e.g., looking up sites by externalId), consider adding an index to improve query performance. Additionally, if the externalId is meant to be unique, consider adding a unique constraint.

-- AlterTable
ALTER TABLE "Site" ADD COLUMN     "externalId" TEXT;
+-- CreateIndex
+CREATE INDEX "Site_externalId_idx" ON "Site"("externalId");
apps/server/src/Services/Notifications/CreateNotifications.ts (1)

211-257: Consider pagination for large result sets.

The query fetches all unprocessed alerts without pagination, which could lead to memory issues with large datasets.

Consider implementing cursor-based pagination:

     const unprocessedAlerts = await prisma.siteAlert.findMany({
       where: {
         isProcessed: false, 
         deletedAt: null,
         eventDate: {
           gte: new Date(new Date().getTime() - 24 * 60 * 60 * 1000),
         },
       },
+      take: 100, // Process in smaller batches
+      cursor: cursor ? { id: cursor } : undefined,
       select: {
         // ... existing select
       },
       orderBy: [{ siteId: 'asc' }, { eventDate: 'asc' }]
     });
apps/nativeapp/ios/FireAlert/PrivacyInfo.xcprivacy (1)

41-44: Consider documenting data collection practices.

While tracking is disabled and no data types are collected, it's good practice to document this decision for future reference.

apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainApplication.kt (1)

13-13: Remove unused import and consider package autolink.

The SplashScreenReactPackage is imported but not used in the package list. Also, the comment about manual package addition could be enhanced with autolink instructions.

-import org.devio.rn.splashscreen.SplashScreenReactPackage;

 override fun getPackages(): List<ReactPackage> =
     PackageList(this).packages.apply {
-      // Packages that cannot be autolinked yet can be added manually here, for example:
+      // Packages that cannot be autolinked should be added here after following
+      // the autolinking guide at: https://rnfirebase.io/
     }

Also applies to: 20-22

apps/nativeapp/app/routes/AppNavigator.tsx (4)

3-3: Remove unused default import.
If you're only using the useAuth0 hook, you could remove the default Auth0 import to keep imports concise.

-import Auth0, { useAuth0 } from 'react-native-auth0';
+import { useAuth0 } from 'react-native-auth0';

60-61: Enhance error handling in callbacks.
Currently, onSuccess and onFail are empty. Consider adding logging or logic to handle success/failure for configuration data calls.


72-84: Make token expiry threshold configurable.
Hardcoding 5 hours in hasTimestampExpiredOrCloseToExpiry may reduce flexibility during testing or in different environments. Extract the 5-hour threshold into a constant or configuration value.


103-160: Improve error messages & unify final steps.
You throw 'error' multiple times when unexpected conditions arise. Using more descriptive error messages would aid debugging. For example:

-throw 'error'
+throw new Error('Missing refreshToken or invalid token details')

Additionally, you may unify SplashScreen.hide() calls and ensure the final state gets set just once to avoid unexpected states if multiple conditions trigger consecutive calls.

apps/nativeapp/app/screens/Login/Login.tsx (1)

18-25: Consistent hook-based approach.
These imports reflect a clear transition to the hooks approach. Ensure any old Auth0 constructor usage is fully removed throughout the app to avoid confusion.

apps/nativeapp/app/screens/Home/Home.tsx (3)

221-230: Error handling in TRPC query.
You display 'something went wrong' as a toast on error. Consider including more details (like error.message) for quicker triage without exposing sensitive data.


257-299: Cache updates are done well.
Manually updating site and alert data after delete avoids a full refetch, improving performance. Just be cautious if the site or alert has untracked side effects in other queries.


483-495: Asynchronous logout approach.
Chaining clearCredentials() and clearSession() is correct, but consider a more descriptive error log message. Also note that console.log("Error ocurred") is misspelled.

-console.log("Error ocurred", error)
+console.log("Error occurred", error)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc1477b and 9a97885.

⛔ Files ignored due to path filters (6)
  • apps/nativeapp/Gemfile.lock is excluded by !**/*.lock
  • apps/nativeapp/android/gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
  • apps/nativeapp/ios/Podfile.lock is excluded by !**/*.lock
  • apps/nativeapp/package-lock.json is excluded by !**/package-lock.json
  • package-lock.json is excluded by !**/package-lock.json
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (70)
  • .gitignore (1 hunks)
  • Readme.MD (2 hunks)
  • apps/nativeapp/.eslintrc.js (1 hunks)
  • apps/nativeapp/.gitignore (3 hunks)
  • apps/nativeapp/.node-version (0 hunks)
  • apps/nativeapp/.ruby-version (0 hunks)
  • apps/nativeapp/Gemfile (1 hunks)
  • apps/nativeapp/__tests__/App-test.tsx (1 hunks)
  • apps/nativeapp/android/app/build.gradle (3 hunks)
  • apps/nativeapp/android/app/src/debug/AndroidManifest.xml (1 hunks)
  • apps/nativeapp/android/app/src/debug/java/eco/pp/firealert/ReactNativeFlipper.java (0 hunks)
  • apps/nativeapp/android/app/src/debug/res/values/strings.xml (1 hunks)
  • apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainActivity.java (0 hunks)
  • apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainActivity.kt (1 hunks)
  • apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainApplication.java (0 hunks)
  • apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainApplication.kt (1 hunks)
  • apps/nativeapp/android/app/src/main/res/drawable/rn_edit_text_material.xml (1 hunks)
  • apps/nativeapp/android/app/src/main/res/values/strings.xml (1 hunks)
  • apps/nativeapp/android/app/src/release/java/eco/pp/firealert/ReactNativeFlipper.java (0 hunks)
  • apps/nativeapp/android/app/src/release/java/eco/pp/firealert/res/values/strings.xml (1 hunks)
  • apps/nativeapp/android/build.gradle (3 hunks)
  • apps/nativeapp/android/gradle.properties (1 hunks)
  • apps/nativeapp/android/gradle/wrapper/gradle-wrapper.properties (1 hunks)
  • apps/nativeapp/android/gradlew (4 hunks)
  • apps/nativeapp/android/gradlew.bat (4 hunks)
  • apps/nativeapp/android/settings.gradle (1 hunks)
  • apps/nativeapp/app/App.tsx (1 hunks)
  • apps/nativeapp/app/components/index.tsx (1 hunks)
  • apps/nativeapp/app/components/layerModal/LayerModal.tsx (1 hunks)
  • apps/nativeapp/app/global/reducers/mapLayers.tsx (1 hunks)
  • apps/nativeapp/app/routes/AppNavigator.tsx (2 hunks)
  • apps/nativeapp/app/routes/stack/CommonStack.tsx (1 hunks)
  • apps/nativeapp/app/routes/stack/index.tsx (1 hunks)
  • apps/nativeapp/app/screens/CreatePolygon/CreatePolygon.tsx (1 hunks)
  • apps/nativeapp/app/screens/CreatePolygon/MapMarking/Map.tsx (1 hunks)
  • apps/nativeapp/app/screens/CreatePolygon/Markers/index.tsx (1 hunks)
  • apps/nativeapp/app/screens/Home/Home.tsx (27 hunks)
  • apps/nativeapp/app/screens/Login/Login.tsx (3 hunks)
  • apps/nativeapp/app/screens/Settings/Settings.tsx (2 hunks)
  • apps/nativeapp/app/screens/index.tsx (1 hunks)
  • apps/nativeapp/app/screens/selectLocation/SelectLocation.tsx (1 hunks)
  • apps/nativeapp/babel.config.js (1 hunks)
  • apps/nativeapp/index.js (1 hunks)
  • apps/nativeapp/ios/FireAlert.xcodeproj/project.pbxproj (27 hunks)
  • apps/nativeapp/ios/FireAlert.xcodeproj/xcshareddata/xcschemes/FireAlert.xcscheme (1 hunks)
  • apps/nativeapp/ios/FireAlert/AppDelegate.mm (1 hunks)
  • apps/nativeapp/ios/FireAlert/Info.plist (3 hunks)
  • apps/nativeapp/ios/FireAlert/PrivacyInfo.xcprivacy (1 hunks)
  • apps/nativeapp/ios/FireAlertTests/Info.plist (1 hunks)
  • apps/nativeapp/ios/Podfile (2 hunks)
  • apps/nativeapp/jest.config.js (1 hunks)
  • apps/nativeapp/metro.config.js (1 hunks)
  • apps/nativeapp/package.json (3 hunks)
  • apps/nativeapp/tsconfig.json (1 hunks)
  • apps/server/instrumentation.ts (1 hunks)
  • apps/server/package.json (1 hunks)
  • apps/server/prisma/migrations/20250103065810_develop_baseline/migration.sql (1 hunks)
  • apps/server/prisma/migrations/20250105034127_protected_areas_01/migration.sql (1 hunks)
  • apps/server/prisma/migrations/20250107025619_protected_areas_02/migration.sql (1 hunks)
  • apps/server/prisma/schema.prisma (5 hunks)
  • apps/server/sentry.edge.config.ts (2 hunks)
  • apps/server/sentry.server.config.ts (2 hunks)
  • apps/server/src/Services/Notifications/CreateNotifications.ts (1 hunks)
  • apps/server/src/env.mjs (1 hunks)
  • apps/server/src/pages/api/migrations/site_userId-to-siterelations.ts (1 hunks)
  • apps/server/src/server/api/routers/sample-utils.ts (1 hunks)
  • apps/server/src/server/api/routers/sample.json (1 hunks)
  • apps/server/src/server/api/routers/site.ts (6 hunks)
  • apps/server/src/server/api/trpc.ts (1 hunks)
  • apps/server/src/server/api/zodSchemas/site.schema.ts (2 hunks)
💤 Files with no reviewable changes (6)
  • apps/nativeapp/.node-version
  • apps/nativeapp/.ruby-version
  • apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainActivity.java
  • apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainApplication.java
  • apps/nativeapp/android/app/src/debug/java/eco/pp/firealert/ReactNativeFlipper.java
  • apps/nativeapp/android/app/src/release/java/eco/pp/firealert/ReactNativeFlipper.java
✅ Files skipped from review due to trivial changes (20)
  • apps/nativeapp/jest.config.js
  • apps/nativeapp/android/app/src/main/res/values/strings.xml
  • apps/nativeapp/tsconfig.json
  • apps/nativeapp/app/screens/selectLocation/SelectLocation.tsx
  • Readme.MD
  • .gitignore
  • apps/nativeapp/app/routes/stack/CommonStack.tsx
  • apps/nativeapp/index.js
  • apps/nativeapp/.eslintrc.js
  • apps/nativeapp/android/app/src/release/java/eco/pp/firealert/res/values/strings.xml
  • apps/nativeapp/app/global/reducers/mapLayers.tsx
  • apps/nativeapp/app/App.tsx
  • apps/nativeapp/android/app/src/main/res/drawable/rn_edit_text_material.xml
  • apps/nativeapp/android/app/src/debug/res/values/strings.xml
  • apps/nativeapp/app/screens/CreatePolygon/Markers/index.tsx
  • apps/nativeapp/app/routes/stack/index.tsx
  • apps/nativeapp/app/screens/CreatePolygon/MapMarking/Map.tsx
  • apps/nativeapp/app/screens/index.tsx
  • apps/nativeapp/app/components/index.tsx
  • apps/nativeapp/app/screens/Settings/Settings.tsx
🧰 Additional context used
🪛 RuboCop (1.69.1)
apps/nativeapp/Gemfile

[convention] 9-9: Gems should be sorted in an alphabetical order within their section of the Gemfile. Gem activesupport should appear before cocoapods.

(Bundler/OrderedGems)

apps/nativeapp/ios/Podfile

[convention] 6-6: Put a comma after the last item of a multiline array.

(Style/TrailingCommaInArrayLiteral)


[convention] 42-42: Avoid comma after the last parameter of a method call.

(Style/TrailingCommaInArguments)

🪛 Biome (1.9.4)
apps/nativeapp/app/screens/Home/Home.tsx

[error] 319-319: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)

apps/nativeapp/app/screens/CreatePolygon/CreatePolygon.tsx

[error] 30-30: Do not shadow the global "Map" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🔇 Additional comments (83)
apps/nativeapp/Gemfile (1)

4-4: Ruby Version Specification Clear.
Specifying the Ruby version directly as ">= 2.6.10" in the Gemfile ensures consistency in development environments.

apps/server/package.json (1)

20-21: New Prisma Studio and DB Generate Scripts
The addition of the "db:generate": "dotenv -e ../../.env npx prisma generate" and "db:studio": "dotenv -e ../../.env npx prisma studio" scripts is a useful enhancement for managing Prisma operations. Please verify that the relative path ../../.env correctly points to your environment file in all deployment environments and doesn’t conflict with other configurations.

apps/nativeapp/.gitignore (3)

23-23: Enhance recursive Xcode env file ignore.
Changing the rule to **/.xcode.env.local broadens the ignore to capture this file in any subdirectory, which is useful if multiple Xcode projects or configurations exist under different folders.


60-60: Apply recursive pattern for Pods directories.
The updated pattern **/Pods/ ensures that Pods folders are ignored regardless of their location in the repository tree. This is especially beneficial in projects where iOS modules may be nested.


74-76: Clarify testing coverage ignore rule.
The addition of the # testing block with /coverage is clear and helps segregate test report files. Just verify that the /coverage path correctly targets the intended coverage reports relative to this directory structure.

apps/nativeapp/app/screens/CreatePolygon/CreatePolygon.tsx (1)

36-38: Import Path Update for Permission Alerts

The import statement now uses updated casing:

import {PermissionBlockedAlert, PermissionDeniedAlert} from '../Home/PermissionAlert/LocationPermissionAlerts';

This change aligns the file structure with standardized naming conventions. Please verify that the new path matches the actual file locations within your project.

apps/nativeapp/ios/Podfile (2)

1-6: LGTM! Improved dependency resolution.

The new Node-based resolution for react_native_pods.rb is a better approach that supports monorepo setups with dependency hoisting.

🧰 Tools
🪛 RuboCop (1.69.1)

[convention] 6-6: Put a comma after the last item of a multiline array.

(Style/TrailingCommaInArrayLiteral)


23-23: LGTM! Robust path resolution.

Using Pod::Config.instance.installation_root provides a more reliable way to resolve the app path.

apps/nativeapp/android/settings.gradle (1)

28-28: Plugin Include Path Update Verification

The update of the React Native Gradle plugin inclusion from react-native-gradle-plugin to @react-native/gradle-plugin aligns with the namespace changes noted in the migration efforts. Please verify that all downstream configurations and dependencies are compatible with this new path.

apps/nativeapp/app/components/layerModal/LayerModal.tsx (1)

13-13:

✅ Verification successful

Verify import path casing change across the codebase.

The change from types to Types in the import path could break imports on case-sensitive systems.

Let's verify the consistency of this change across the codebase:


🏁 Script executed:

#!/bin/bash
# Search for any remaining imports from the old path
rg "from ['\"].*actions/types['\"]"

# Search for imports using the new path to confirm adoption
rg "from ['\"].*actions/Types['\"]"

Length of output: 300


Confirmed import path update across the codebase.

The change from using actions/types to actions/Types has been consistently applied:

  • In apps/nativeapp/app/components/layerModal/LayerModal.tsx, the import now correctly uses ../../global/actions/Types.
  • In apps/nativeapp/app/global/reducers/mapLayers.tsx, the import has been updated to ../actions/Types.

This should prevent issues on case-sensitive systems. No further changes related to the import path are required at this time.

apps/nativeapp/metro.config.js (2)

1-5: LGTM! Well-structured Metro setup for monorepo.

The imports and initial setup follow best practices for configuring Metro in a monorepo environment.


32-32: LGTM! Proper configuration export using recommended pattern.

The configuration is correctly exported using mergeConfig to combine default Metro settings with custom overrides.

apps/nativeapp/babel.config.js (2)

3-20: LGTM! Comprehensive module resolution configuration.

The module-resolver plugin configuration is well-structured with:

  • Appropriate root directory setting for monorepo setup
  • Complete coverage of file extensions including platform-specific files

2-2:

✅ Verification successful

Verify the React Native Babel preset version.

The change to @react-native/babel-preset aligns with React Native's move to scoped packages.


🌐 Web query:

What is the latest recommended Babel preset for React Native? Is @react-native/babel-preset the current standard?

💡 Result:

The latest recommended Babel preset for React Native is @react-native/babel-preset, which has become the standard since React Native v0.76 and later[4][6]. This preset replaces older packages like babel-preset-react-native (deprecated since 2018)[1] and metro-react-native-babel-preset[9].

Key Details:

  • Current Standard:
    @react-native/babel-preset (v0.77.1 as of February 2025)[4]

    • Used by default in React Native projects
    • Handles JSX transformation, Flow/TypeScript syntax stripping, and other React Native-specific optimizations[4][7]
  • Configuration:
    Add to your babel.config.js:

    module.exports = {
      presets: ['module:@react-native/babel-preset'],
    };

    This replaces older formats like .babelrc[4][6].

  • Expo Compatibility:
    Expo projects use babel-preset-expo, which extends @react-native/babel-preset while adding web/tree-shaking support[2].

Deprecated Presets:

Package Replacement Status
babel-preset-react-native @react-native/babel-preset Deprecated[1]
metro-react-native-babel-preset @react-native/babel-preset Merged[4][9]

For new projects, use @react-native/babel-preset unless using Expo (where babel-preset-expo is preferred)[2][4]. Existing projects should migrate to avoid compatibility issues with newer React Native versions[1][8].

Citations:


PRESET Update Verified

The change in apps/nativeapp/babel.config.js on line 2 to use ['module:@react-native/babel-preset'] is correct. This preset is confirmed as the current standard for React Native (adopted since v0.76) and aligns with the latest recommendations.

  • The configuration now aligns with React Native’s move to scoped packages.
  • No further modifications are required based on this update.
apps/server/src/server/api/routers/sample.json (1)

1-258: Verify the coordinate system and projection.

The coordinates appear to be in decimal degrees, but it's important to:

  1. Document the coordinate reference system (CRS) being used
  2. Ensure consistency with the frontend mapping library
  3. Consider adding a crs property to the GeoJSON structure

Run this script to validate coordinate ranges and detect potential issues:

#!/usr/bin/env python3
import json
import sys

def validate_coordinates(coords):
    for ring in coords:
        for point in ring:
            lon, lat = point
            if not (-180 <= lon <= 180):
                print(f"Invalid longitude: {lon}")
            if not (-90 <= lat <= 90):
                print(f"Invalid latitude: {lat}")
            
def main():
    with open('apps/server/src/server/api/routers/sample.json') as f:
        data = json.load(f)
    
    for feature in data:
        coords = feature['geometry']['coordinates']
        print(f"Validating {feature['name']}...")
        validate_coordinates(coords)
        
        # Verify polygon closure
        for ring in coords:
            if ring[0] != ring[-1]:
                print(f"Polygon not closed in {feature['name']}")

if __name__ == '__main__':
    main()
apps/nativeapp/__tests__/App-test.tsx (1)

7-9: LGTM! Import updates align with project restructuring.

The changes improve type safety by explicitly importing Jest's it function and maintain consistency with the project's directory restructuring.

apps/nativeapp/package.json (4)

6-6: Android build command syntax updated.

The change from --variant to --mode reflects updates in React Native CLI. This is the correct syntax for React Native 0.74.x.

Also applies to: 12-12


90-92: Node.js version requirement added.

The addition of the engines field ensures compatibility with React Native 0.74.x which requires Node.js >= 18.


45-47:

❓ Verification inconclusive

Verify compatibility with React Native 0.74.3 upgrade.

Major version upgrade from 0.71.1 to 0.74.3 requires careful testing. Please ensure:

  1. All native modules are compatible
  2. Breaking changes are addressed
  3. Deprecated APIs are updated

Run this script to check for potential compatibility issues:


🏁 Script executed:

#!/bin/bash
# Description: Check for compatibility issues with React Native 0.74.3

# Check for outdated native dependencies
npm outdated | grep "react-native"

# Look for potential breaking changes in native code
rg -l "import.*react.native" | grep -E "\.(java|kt|m|mm|h)$"

Length of output: 97


Manual Compatibility Check Needed for React Native 0.74.3 Upgrade

The automated check returned no output, which might indicate no immediate issues were detected. However, given the major version upgrade from React Native 0.71.1 to 0.74.3, please perform a thorough manual review to ensure:

  • All native modules are confirmed to be compatible.
  • Any breaking changes in native code have been addressed.
  • All deprecated APIs have been updated accordingly.

Please verify these aspects carefully across the codebase before finalizing the upgrade.


71-74:

✅ Verification successful

Migration to new React Native tooling packages.

The switch from @react-native-community to @react-native packages aligns with React Native's new tooling structure.

Please verify the migration by checking the official React Native 0.74 upgrade guide:


🌐 Web query:

What are the breaking changes in React Native 0.74 regarding tooling packages?

💡 Result:

React Native 0.74 introduces several significant breaking changes regarding tooling packages:

1. Removal of Flipper React Native Plugin

  • The native Flipper libraries and setup code have been completely removed from new React Native projects[1][2][3]
  • This eliminates ~4MB of dependencies and simplifies local setup[1][3]
  • Impact: Existing debugging workflows using Flipper will break unless manually re-integrated
  • Migration:
    # To preserve Flipper in existing apps:
    # Ignore relevant diff lines when upgrading via Upgrade Helper
    Developers must follow Flipper's Android and iOS integration guides manually[1]

2. Recommended Debugging Tool Changes

  • New Defaults: Hermes Debugger remains primary recommendation[1]
  • Experimental Debugger: Now default in Expo (early preview)[1]
  • Native Alternatives:
    | Feature          | Android Studio Tools | Xcode Tools       |
    |------------------|----------------------|-------------------|
    | Layout Inspection| Layout Inspector      | Xcode View Debugger |
    | Network          | Profiler             | Instruments       |
    ```[1]
    

3. Yarn 3 as Default Package Manager

  • New projects now use Yarn 3 instead of Yarn Classic[1][2][4]
  • Key Differences:
    • Zero-install architecture
    • Improved workspace management
    • Strict dependency resolution[4]
  • Existing projects remain unaffected unless explicitly migrated[4]

These changes aim to reduce app size (13% smaller initial builds)[1], improve debugging performance, and modernize dependency management. Developers relying on Flipper should plan for manual re-integration or transition to recommended alternatives[1][3].

Citations:


Migration Verified: React Native 0.74 Tooling Packages

The tooling packages in apps/nativeapp/package.json have been correctly updated from the legacy @react-native-community versions to the new @react-native packages, in line with the React Native 0.74 upgrade guide. Note that React Native 0.74 also introduces notable changes—such as the removal of native Flipper integration and a shift to Yarn 3 by default—which may affect debugging or dependency management setups if your project relies on those features. Overall, the migration regarding these packages is correct, but please ensure any additional configurations (e.g., for custom Flipper setups) are verified as needed.

apps/server/src/server/api/routers/site.ts (2)

8-9: Validate the utility functions' behavior.
While importing filterByName and getByExternalId, ensure these functions handle edge cases and large inputs gracefully, especially if they're critical for site lookups.


517-552: Check for soft-deletions and unify naming.
getProtectedSites currently does not filter out sites with deletedAt set. If that is a requirement, update the query accordingly. Also, consider renaming _siteRelation to siteRelations for clarity.

apps/server/sentry.server.config.ts (1)

7-7: Confirm correct profiling integration usage.
Using nodeProfilingIntegration replaces the older ProfilingIntegration. Verify that this integration provides the expected performance metrics in the server-based environment.

Also applies to: 21-21

apps/server/sentry.edge.config.ts (1)

8-8:

✅ Verification successful

Verify Sentry profiling package version compatibility.

The change from ProfilingIntegration class to nodeProfilingIntegration function suggests an API update. Let's verify the compatibility with the current Sentry package version.

Also applies to: 22-22


🌐 Web query:

What is the latest version of @sentry/profiling-node and when was ProfilingIntegration deprecated in favor of nodeProfilingIntegration?

💡 Result:

The latest version of @sentry/profiling-node is 9.1.0 as of February 13, 2025[4][7].

The ProfilingIntegration class was deprecated in Sentry JavaScript SDK v8 and replaced with the functional nodeProfilingIntegration()[3][6]. This change was part of a broader migration from class-based integrations to function-based ones in Sentry's v8 release[3][5][6].

Key details:

  • Deprecation timeline:
    • Class-based integrations like new ProfilingIntegration() were deprecated starting in v7.100.0[5][6]
    • Fully removed in v8 with replacement by nodeProfilingIntegration()[3][4]
  • Migration example:
    // v7
    integrations: [new ProfilingIntegration()]
    
    // v8+
    integrations: [nodeProfilingIntegration()]
  • Compatibility: Requires @sentry/[email protected] or newer[1][9]

The change aligns with Sentry's effort to simplify integration APIs and improve tree-shaking capabilities in modern JavaScript environments[3][5]. Developers using profiling must now use the functional integration format with Sentry v8+[4][10].

Citations:


Sentry Profiling Integration Verified

  • The use of nodeProfilingIntegration in apps/server/sentry.edge.config.ts is consistent with Sentry's migration in SDK v8, where the class-based ProfilingIntegration was replaced by the function-based API.
  • The current implementation aligns with the latest @sentry/profiling-node version (9.1.0 as of February 13, 2025) and its requirements.
  • Ensure that the corresponding @sentry/node dependency is at least version 7.44.1 to maintain overall compatibility.

No further changes are needed in lines 8 or 22.

apps/server/src/Services/Notifications/CreateNotifications.ts (1)

237-252: LGTM: Good addition of siteRelations query.

The inclusion of siteRelations in the query ensures we can access alert methods for protected sites.

apps/server/prisma/migrations/20250105034127_protected_areas_01/migration.sql (5)

1-3: Enum Creation for SiteKind is Correct
The new enum SiteKind is defined with appropriate values. No issues found here.


4-6: Enum Creation for SiteRelationRole is Correct
The new enum SiteRelationRole correctly includes the values 'ROLE_ADMIN' and 'ROLE_VIEWER'.


7-10: Validate Table Alterations on "Site" Table
The alteration correctly adds the "kind" column with a default value and drops the NOT NULL constraint on "userId". Please ensure that the application logic gracefully handles potential nulls for userId now, especially where it might have been assumed to always contain a value.


11-23: New Table "SiteRelation" is Well-Structured
The creation of the SiteRelation table is consistent with the intended data relationships. Note that the updatedAt column relies on application/trigger logic for automatic updates, so verify that such behavior is in place if required.


24-29: Foreign Key Constraints Added Appropriately
The foreign keys linking SiteRelation.siteId to Site.id and SiteRelation.userId to User.id with cascading actions are correctly defined, ensuring referential integrity.

apps/server/prisma/schema.prisma (6)

5-10: Datasource Update for Shadow Database
The new line setting

shadowDatabaseUrl = env("DATABASE_URL_NON_POOLING_SHADOW")

correctly configures the shadow database. Please double-check that the environment variable is defined correctly in all deployment contexts.


12-33: Enhancement in the User Model: Addition of siteRelations
Adding the field

siteRelations SiteRelation[]

in the User model properly reflects the new relationship. This change will enable queries on all site relations associated with a user.


66-92: Modifications in the Site Model for Protected Areas
Several important changes include:

  • Making userId optional (line 80) and updating the corresponding relation (line 87) to be optional.
  • Introducing new fields kind (line 88) with a default of USER_SITE and externalId (line 90).
  • Adding the relation siteRelations (line 91).

These modifications are in line with supporting protected site functionalities. However, ensure that all business logic references are updated to handle cases where a site may not have an associated user, and that the kind field is consistently interpreted across the application.


160-165: Minor Formatting Adjustments in the Stats Model
The changes in the Stats model appear to be formatting-related with no impact on functionality.


167-177: New Model "SiteRelation" is Consistent with the Migration
The SiteRelation model aligns well with the migration script. It defines all necessary fields and relationships between Site and User. Consider verifying if the handling of the updatedAt field (via Prisma’s @updatedAt or external logic) meets your requirements for timestamp updates on modifications.


197-205: New Enums for SiteKind and SiteRelationRole in Prisma Schema
The enums SiteKind and SiteRelationRole are correctly defined in the Prisma schema and match the corresponding SQL definitions.

apps/nativeapp/ios/FireAlert.xcodeproj/project.pbxproj (6)

15-16: New PrivacyInfo.xcprivacy references.

Multiple entries were added to reference PrivacyInfo.xcprivacy. This file typically stores app privacy configuration and usage descriptions. Please ensure:

  1. The file is correctly placed under the project's structure.
  2. The app's Info.plist also references or describes all new privacy usage keys if they are required by Apple guidelines.
  3. You have verified the final build includes the file properly in the resulting bundle.

Also applies to: 75-75, 79-79, 161-162, 384-384


26-26: New or updated framework references.

These references add or update linkage for libPods-FireAlert-FireAlertTests.a, libPods-FireAlert.a, and libPods-OneSignalNotificationServiceExtension.a. Ensure your Pod install process is up to date and that all required frameworks are correctly included in test and app targets. Missing or incorrect linkages can lead to linker errors or runtime crashes.

Also applies to: 30-30, 106-106, 111-111, 119-119, 127-127, 171-173


243-248: New Pod configuration file references.

Several lines reference newly added or updated xcconfig files:

  • Pods-FireAlert.debug.xcconfig
  • Pods-FireAlert.release.xcconfig
  • Pods-FireAlert-FireAlertTests.debug.xcconfig
  • Pods-FireAlert-FireAlertTests.release.xcconfig
  • Pods-OneSignalNotificationServiceExtension.debug.xcconfig
  • Pods-OneSignalNotificationServiceExtension.release.xcconfig

Confirm that these files exist under the specified paths, especially within “Target Support Files/...”. If any are missing or incorrectly named, the build might fail.

Also applies to: 594-594, 621-621, 645-645, 681-681, 713-713


602-602: Raised iOS deployment target to 13.4.

The IPHONEOS_DEPLOYMENT_TARGET was updated to 13.4 in multiple build configurations. This may exclude users on older iOS versions. Verify that dropping support for older iOS devices is intentional, and ensure your app’s user base is prepared.

Also applies to: 626-626, 835-835, 917-917


653-653: Version increments.

CURRENT_PROJECT_VERSION = 7 and MARKETING_VERSION = 1.3 suggest you are introducing a new app version. Ensure corresponding app metadata (App Store Connect release notes, marketing channels) also reflects these changes.

Also applies to: 663-663, 688-688, 697-697


412-412: Pod-related shell script updates.

Lines referencing [CP] Check Pods Manifest.lock, [CP] Copy Pods Resources, and [CP] Embed Pods Frameworks have been updated. Verify these scripts run successfully within your CI/CD environment. If any environment variables (e.g., PODS_ROOT or PODS_PODFILE_DIR_PATH) change, the scripts might fail.

Also applies to: 414-414, 421-424, 427-427, 429-429, 442-442, 446-446, 450-450, 459-459, 463-463, 467-467, 470-470, 495-495, 498-498, 502-502, 506-506, 510-510, 515-515, 519-519, 523-523, 541-541

apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainActivity.kt (2)

1-9: Successful Kotlin migration.

Migrating MainActivity from Java to Kotlin is a good modernization step. The package declaration and imports look fine. Confirm you have the Kotlin Gradle plugin applied in your build.gradle and that your team is aligned on Kotlin usage for future Android development.


14-26: Splash screen and React setup.

  1. The splash screen is shown before the call to super.onCreate(), which is recommended to display the splash instantly.
  2. getMainComponentName() returning "FireAlert" aligns with your JavaScript entry point.
  3. createReactActivityDelegate() uses the Fabric architecture flag. Ensure that your React Native version supports the new architecture for a smooth upgrade experience.
apps/nativeapp/ios/FireAlertTests/Info.plist (2)

11-23: Added Auth0 URL scheme.

The CFBundleURLTypes and associated auth0 scheme indicate an integration with Auth0 or a similar authentication mechanism. Double-check that your AppDelegate or SceneDelegate (if using iOS 13+) properly handles URL callbacks to complete the authentication flow.


31-31: Updated short version string and build number.

CFBundleShortVersionString was bumped to 1.3 and CFBundleVersion to 6. Verify these updates match your app’s overall versioning strategy and that you keep them consistent across Android and iOS builds if needed.

Also applies to: 35-35

apps/nativeapp/android/app/src/main/java/eco/pp/firealert/MainApplication.kt (1)

35-42: LGTM! Proper initialization sequence.

The onCreate implementation correctly initializes SoLoader and conditionally loads the new architecture.

apps/nativeapp/ios/FireAlert/AppDelegate.mm (1)

31-43: LGTM! Clean bundle URL handling.

The implementation properly separates bundle URL logic and handles both debug and release paths correctly.

apps/nativeapp/android/gradlew.bat (2)

44-44: LGTM! Improved error handling.

The changes properly redirect error messages to stderr and use the correct numeric comparison operator.

Also applies to: 46-50


84-87: LGTM! Enhanced exit code handling.

The implementation properly sets and handles exit codes, improving script robustness.

apps/nativeapp/ios/FireAlert/Info.plist (4)

44-50: Security enhancement: Restricted network access.

Good security practice! The changes disable arbitrary loads and local networking, which enhances the app's security posture.


19-20:

❓ Verification inconclusive

Version update requires verification.

The app version has been updated to 1.3 (build 7). Please ensure this aligns with your versioning strategy and release plans.

Also applies to: 36-37


🏁 Script executed:

#!/bin/bash
# Check if version numbers are consistent across the project
echo "Checking version numbers in package.json..."
find . -name "package.json" -type f -exec grep -l "version" {} \;

Length of output: 268


Ensure Consistency of Version Bump and Associated Changes

The Info.plist now shows the version updated to 1.3 (build 7). Please verify that this version bump is consistent across the project by confirming that the version numbers in the various package.json files (e.g., in the project root, apps/nativeapp, and packages/tsconfig) adhere to the intended versioning strategy. Also, double-check that the additional changes—network security adjustments, the shift to arm64 architecture (dropping armv7), and the minimum iOS version bump to 12.0—are in line with the planned release. Note that similar version-related adjustments appear on lines 36–37 in the corresponding configuration.


79-82:

✅ Verification successful

Architecture change impacts device compatibility.

Switching from armv7 to arm64 drops support for 32-bit devices. This aligns with modern iOS development but verify if this matches your device support requirements.


🌐 Web query:

When did Apple stop supporting 32-bit (armv7) apps in iOS?

💡 Result:

Apple officially discontinued support for 32-bit (armv7) apps starting with iOS 11, released in September 2017[1][3][4][6]. This marked a full transition to a 64-bit-only architecture across all iPhones and iPads running iOS/iPadOS versions beyond iOS 10[3][4]. Here’s a breakdown of key milestones:

Key Events Leading to Deprecation

  • June 2015: Apple mandated that all new App Store submissions include 64-bit compatibility alongside existing 32-bit code[6].
  • January 2016: Updates to existing apps also required 64-bit support[6].
  • iOS 10.3 (2017): Introduced warnings for users about incompatible legacy apps[1].
  • iOS 11 (September 2017): Dropped all compatibility for launching or running preinstalled or sideloaded 32-bit apps[3][4][6]. Apps using armv7 architecture would crash immediately upon launch[4].

Impact on Devices

  • Devices older than the iPhone 5s (released in September 2013) became obsolete as they lacked hardware support for a pure 64-bit environment[1][6].
  • Users were directed to check incompatible apps via Settings > General > About > Applications and update or delete them[1].

Developer Requirements

  • By mid-2015, developers were required to include 64-bit code in all App Store submissions[1][6].
  • In June 2022, Xcode 14 removed the ability to build universal binaries containing both armv7 (32-bit) and arm64 (64-bit) code[3]. This aligned with Apple’s long-term goal of eliminating legacy code from development workflows[8].

macOS Parallel

  • macOS phased out 32-bit app support starting with macOS Catalina (October 2019), mirroring iOS’s transition[5].

User Confusion Clarified

Some users mistakenly attributed the discontinuation of legacy app functionality to newer iOS versions like iOS/iPadOS 17, but this was due to developers dropping updates for outdated apps rather than OS-level changes[4][7].

Citations:


Architecture Change – Confirm Device Support Requirements

The updated Info.plist now restricts the app to devices supporting arm64. Note that Apple officially dropped support for 32‑bit (armv7) apps with iOS 11 (released September 2017). This change is in line with modern iOS development, but please ensure that your minimum deployment target is iOS 11 or later. If you need to support legacy devices, you may need to revisit this configuration.

  • File: apps/nativeapp/ios/FireAlert/Info.plist (lines 79–82)
  • Snippet:
    	<key>UIRequiredDeviceCapabilities</key>
    	<array>
    		<string>arm64</string>
    	</array>

40-41:

✅ Verification successful

Verify minimum iOS version requirement.

Setting minimum iOS version to 12.0 will drop support for devices that can't upgrade beyond iOS 11. Please confirm this aligns with your user base requirements.


🌐 Web query:

What percentage of iOS devices are running iOS 12 or later in 2024?

💡 Result:

As of late December 2024, over 99% of active Apple mobile devices were running iOS 12 or later based on aggregated data from multiple sources:

1. Cumulative adoption trends
The latest available data shows:

  • 98–99% compatibility with iOS 13 and later due to Apple’s strong update ecosystem [1][3][5].
  • Older operating systems like iOS 11 accounted for <0.8% globally by October 2024 [5].

Key Data Points:

Source Date % Running iOS 13+ Notes
Statcounter Oct 2024 96–97% Includes minor updates beyond base versions [5].
TelemetryDeck Apr 2024 ~97–99% Combined 83–85% for iOS 17, 14–16% for iOS 16, residual <3–5% [6].
Apple Developer Jan 2025 >95–96% Focused on active App Store users [10].

Context:

Apple’s consistent update push ensures rapid adoption:

  • Devices unsupported by newer updates phase out naturally over time.
  • By late 2024, only legacy hardware like iPhone 5s (last updated in 2019) remained limited to iOS 15, representing a negligible share [1][3][6].

Citations:


Minimum iOS Version Confirmation

The web data confirms that over 99% of active devices are running iOS 12 or later. Setting the minimum system version to 12.0 is therefore appropriate. Please double-check that there are no critical requirements for supporting legacy devices (iOS 11) in your user base.

  • File: apps/nativeapp/ios/FireAlert/Info.plist (Lines 40-41)
  • Current Code:
    	<key>LSMinimumSystemVersion</key>
    	<string>12.0</string>
apps/nativeapp/android/gradlew (3)

83-88: Improved error handling and output suppression.

Good improvements:

  • Added shellcheck directive for better script validation
  • Suppressed cd output to handle CDPATH issues

134-142: Enhanced Java command verification.

Improved error handling for Java command verification using command -v instead of which. This is more POSIX-compliant.


217-221: Added xargs availability check.

Good defensive programming by verifying xargs availability before use.

apps/nativeapp/android/app/src/debug/AndroidManifest.xml (1)

6-9:

❓ Verification inconclusive

Verify debug configuration removal.

The removal of debug-specific configurations (SYSTEM_ALERT_WINDOW permission and DevSettingsActivity) appears intentional. Please confirm this won't impact development workflows.


🏁 Script executed:

#!/bin/bash
# Check if there are any remaining references to removed debug features
echo "Checking for SYSTEM_ALERT_WINDOW usage..."
rg "SYSTEM_ALERT_WINDOW" -l

echo "Checking for DevSettingsActivity references..."
rg "DevSettingsActivity" -l

Length of output: 251


Verify removal of debug-specific configurations.

The removal of the SYSTEM_ALERT_WINDOW permission and DevSettingsActivity from the debug AndroidManifest (apps/nativeapp/android/app/src/debug/AndroidManifest.xml) appears intentional, and the updated application tag (showing only android:usesCleartextTraffic="true", tools:targetApi="28", and tools:ignore="GoogleAppIndexingWarning") aligns with this change. However, since the automated search produced no output while checking for references to these removed features, please manually verify that no lingering references exist in the repository to ensure this change won’t inadvertently affect development workflows.

apps/nativeapp/android/build.gradle (3)

5-10: Update of Android SDK and Toolchain Versions
The updates to buildToolsVersion, minSdkVersion, compileSdkVersion, targetSdkVersion, and the addition of kotlinVersion are clear and help bring the project up-to-date with newer Android standards.


21-23: Gradle Plugin Dependency Configuration
Switching the classpath for the Android Gradle plugin to a generalized declaration ("com.android.tools.build:gradle") and adding the Kotlin Gradle plugin are acceptable, but make sure that the resolution of the Android Gradle plugin version is well-controlled elsewhere (for example, via a consistent dependency constraint).


36-36: Application of React Native Root Project Plugin
The addition of apply plugin: "com.facebook.react.rootproject" at the end of the file integrates the React Native project structure. Please confirm that this plugin’s version and compatibility align with your current React Native setup.

apps/nativeapp/android/app/build.gradle (2)

2-2: Kotlin Support Integration
The addition of apply plugin: "org.jetbrains.kotlin.android" is a positive step toward modernizing the codebase by enabling Kotlin for Android development. Ensure that the rest of the Kotlin migration (including dependency versions and project configuration) is consistent across the app.


96-97: Version Update in Default Configuration
Updating versionCode from 4 to 6 and versionName from "1.2" to "1.3" reflects an important release version bump. Confirm that these changes align with your release management and store versioning strategy, and that no downstream integrations are adversely affected.

apps/nativeapp/app/routes/AppNavigator.tsx (3)

69-70: Verify dependencies for token refresh logic.
You are calling handleRefreshToken in a useEffect with [dispatch, queryClient] as dependencies. Make sure you include any other state or variable dependencies used within handleRefreshToken so that re-renders do not skip necessary updates.


86-95: Validate returned credentials.
In refreshUserToken, the result might not always include valid properties (e.g., a new refresh token). Consider adding more robust null or shape checks to ensure you only proceed with valid credentials.


97-100: LGTM for connectivity check.
The checkInternetConnectivity function is straightforward and readable.

apps/nativeapp/app/screens/Login/Login.tsx (5)

10-10: Imports look good.
The useState and useEffect imports are standard and align with your usage.


32-33: Slight caution for error state.
Double-check if error from useAuth0 might contain fields other than code, ensuring you handle all relevant error properties.


38-44: Robust unauthorized flow.
Your useEffect triggers showVerifyAccModal on unauthorized. This approach is correct but verify if other error codes might need unique handling, such as “login_required” or “consent_required”.


49-79: Approve the async login flow.
Using async/await for authorize and handling the toast notifications is significantly more readable. Nice enhancement to user experience and error feedback.


109-114: No issues with updated text.
Your updated text content and styling are clear.

apps/nativeapp/app/screens/Home/Home.tsx (12)

20-20: Hook-based Auth0 usage recognized.
Transitioning to useAuth0 is consistent with the rest of the refactor; looks good.


108-115: Ensure consistent context usage.
You're pulling state from useMapLayers and also using BottomBarContext plus Redux state. Double-check these contexts remain in sync for complex updates (e.g., changes to selectedSiteBar or passMapInfo).


169-169: Tidy passMapInfo usage.
Collecting centerCoordinates and currZoom upon user action is neat. Confirm the downstream usage is updated correctly if these values can change frequently.


219-219: Query usage looks fine.
useFetchSites with enabled: true is straightforward for controlling request triggers.


237-254: User update mutation approach is clear.
Your success and error callbacks are properly handled, and the function dispatches getUserDetails again. All good.


301-330: Site update mutation coverage.
Similarly, your cache manipulation on update merges changes neatly. Good approach to keep the UI in sync without reloading all data.

🧰 Tools
🪛 Biome (1.9.4)

[error] 319-319: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)


332-343: User deletion flow is straightforward.
softDeleteUser approach plus clearing the cache is logically consistent.


947-947: Spacing changes are minor.
Styling adjustments at line 947 appear consistent with your design approach.


1006-1006: Conditional rendering is fine.
Rendering ( selectedSite?.site?.project?.id && (...) ) is an acceptable pattern for optional site attributes.


1108-1108: Minor styling change.
Your new textTransform: 'lowercase' is consistent with the required design.


1189-1189: No issues with absolute positioning.
Maintaining consistent UI placement is presumably intentional.


1287-1287: Consistent color usage.
The updated border color keeps your UI consistent with the brand style.

Comment on lines +7 to +30
const config = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
watchFolders: [
// Include monorepo root and node_modules
path.resolve(__dirname, '../..'),
path.resolve(__dirname, '../../node_modules'),
],
resolver: {
nodeModulesPaths: [
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, '../../node_modules'),
],
extraNodeModules: {
...monorepoMetroTools.extraNodeModules,
},
};
})();
},
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

LGTM! Comprehensive Metro configuration for monorepo.

The configuration is well-structured with appropriate settings for transformer, watch folders, and module resolution. The use of inlineRequires: true will help with performance.

Verify that the node_modules paths exist and are correctly configured:


🏁 Script executed:

#!/bin/bash
# Check if the specified node_modules directories exist
echo "Checking node_modules paths..."
[ -d "apps/nativeapp/node_modules" ] && echo "✓ Local node_modules exists" || echo "✗ Local node_modules missing"
[ -d "node_modules" ] && echo "✓ Root node_modules exists" || echo "✗ Root node_modules missing"

Length of output: 269


Action Required: Verify Node Modules Directory Configuration

The Metro configuration is well-structured regarding transformer, watch folders, and resolver settings. However, our verification script shows that neither the local (apps/nativeapp/node_modules) nor the root (node_modules) directories are present. Please confirm whether this is expected due to a hoisted dependency setup common in monorepos, or if the configuration needs adjustments to account for the actual directory structure.

  • File: apps/nativeapp/metro.config.js (Lines 7-30)
  • Action: Double-check the physical presence of the node_modules directories or update the configuration if the dependency management strategy differs from the expected layout.

Comment on lines +3 to +7
export function filterByName(text: string) {
return data.filter(item => {
return item.name.toLowerCase().includes(text.toLowerCase());
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation and error handling to filterByName.

The function should handle edge cases and invalid inputs:

  • Empty/null text parameter
  • Non-string inputs
  • Performance considerations for large datasets

Consider this implementation:

 export function filterByName(text: string) {
+  if (!text) return [];
+  if (typeof text !== 'string') throw new Error('Input must be a string');
+
   return data.filter(item => {
+    if (!item.name) return false;
     return item.name.toLowerCase().includes(text.toLowerCase());
   });
 }

Comment on lines +9 to +11
export function getByExternalId(externalId: string) {
return data.find(item => item.externalId === externalId);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation and error handling to getByExternalId.

The function should handle edge cases and invalid inputs:

  • Empty/null externalId parameter
  • Non-string inputs
  • Case where no item is found

Consider this implementation:

 export function getByExternalId(externalId: string) {
+  if (!externalId) throw new Error('External ID is required');
+  if (typeof externalId !== 'string') throw new Error('External ID must be a string');
+
   return data.find(item => item.externalId === externalId);
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +158 to +345

const foundSite = await ctx.prisma.site.findFirst({
where: {externalId: externalId},
})

let site: Partial<Site>, siteRelation: Partial<SiteRelation>;
if(foundSite) {
const _foundSiteRelation = await ctx.prisma.siteRelation.findFirst({
where: { userId: userId, siteId: foundSite.id },
})
if (_foundSiteRelation) {
site = foundSite;
siteRelation = _foundSiteRelation
} else {
const _siteRelation = await ctx.prisma.siteRelation.create({
data: {
role: "ROLE_VIEWER",
userId: userId,
siteId: foundSite.id,
isActive: true
},
select: {
siteId: true, userId: true, role: true,
site: {
select: {
id: true,
type: true,
name: true,
radius: true,
geometry: true,
externalId: true,
}
}
}
})
const _site = await ctx.prisma.site.update({
where: {id: foundSite.id},
data: {isMonitored: true},
})
site = _site;
siteRelation = _siteRelation
}
} else {
const _site = await ctx.prisma.site.create({
data: {
origin: origin,
type: 'Polygon',
name: ppSite.name,
radius: 0,
kind: 'PROTECTED_SITE',
geometry: ppSite.geometry as unknown as Prisma.JsonObject,
externalId: ppSite.externalId,
lastUpdated: new Date(),
siteRelations: {
create: {
user: { connect: { id: userId, } },
role: 'ROLE_VIEWER',
}
},
},
select: {
id: true,
type: true,
name: true,
radius: true,
geometry: true,
externalId: true,
lastUpdated: true,
project: {
select: { id: true, name: true }
},
siteRelations: {
select: { siteId: true, userId: true, role: true }
}
},
});
site = _site;
siteRelation = _site.siteRelations
}

return {
status: "success",
data: {
site,
siteRelation
},
};
} catch (error) {
console.log(error);
if (error instanceof TRPCError) {
// if the error is already a TRPCError, just re-throw it
throw error;
}
// if it's a different type of error, throw a new TRPCError
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `Something Went Wrong`,
});
}
}),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Handle concurrency and remove large commented sections.
This procedure creates or attaches a user to a protected site. Possible concurrency issues can arise if multiple users create the same externalId simultaneously. Consider using transactions or unique constraints to avoid duplicates. Large commented-out code blocks also make the code harder to read; consider removing them or moving them to documentation.

Comment on lines +5 to +40
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
<string>3B52.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>85F4.1</string>
</array>
</dict>
</array>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify privacy reason codes with Apple's documentation.

The privacy manifest includes API access types with specific reason codes (CA92.1, C617.1, 3B52.1, 85F4.1). These codes should match Apple's documented privacy reasons.


🌐 Web query:

What are the valid reason codes for NSPrivacyAccessedAPITypes in iOS privacy manifest?

💡 Result:

To resolve errors related to NSPrivacyAccessedAPITypes in your iOS app's privacy manifest, you must use valid reason codes corresponding to specific API categories as mandated by Apple[1][3][4]. Below are the required categories and their approved reason codes:


Valid Reason Codes by API Category

API Category Reason Code Approved Use Case
User Defaults 1C8F.1 Accessing data within the same App Group[3][4].
(NSPrivacyAccessedAPICategoryUserDefaults) CA92.1 General read/write operations (e.g., via .NET MAUI's Preferences API)[4][6].
File Timestamp C617.1 Accessing file timestamps (required for .NET runtime/BCL)[4][7].
(NSPrivacyAccessedAPICategoryFileTimestamp)
System Boot Time 35F9.1 Retrieving system boot time (common in diagnostics frameworks)[3][4][5].
(NSPrivacyAccessedAPICategorySystemBootTime)
Disk Space E174.1 Checking available disk space[4][5].
(NSPrivacyAccessedAPICategoryDiskSpace)

Implementation Steps

  1. Add a Privacy Manifest File:
    Create PrivacyInfo.xcprivacy in Xcode (File → New → App Privacy File)[3][4].

  2. Declare API Categories and Reasons:
    For each API category used, specify its NSPrivacyAccessedAPIType and corresponding NSPrivacyAccessedAPITypeReasons in XML format:

    <key>NSPrivacyAccessedAPITypes</key>
    <array>
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array>
                <string>CA92.1</string> <!-- Example for UserDefaults -->
            </array>
        </dict>
    </array>
  3. Third-Party Libraries:
    Ensure dependencies include their own PrivacyInfo.xcprivacy files with valid reasons[3][6]. If they don’t, add required entries to your app’s manifest[6].


Common Pitfalls

  • Using generic descriptions like "App Functionality" instead of approved codes[1].
  • Omitting mandatory categories (e.g., .NET MAUI apps require FileTimestamp, SystemBootTime, and DiskSpace declarations)[4].
  • Failing to update manifests for app extensions or SDKs[3][6].

For full details, refer to Apple’s Required Reason API Documentation[9].

Citations:


Action Required: Update Invalid Privacy Reason Codes

  • For NSPrivacyAccessedAPICategoryFileTimestamp: Remove the extra reason code "3B52.1" so that only "C617.1" remains.
  • For NSPrivacyAccessedAPICategoryDiskSpace: Change the reason code from "85F4.1" to "E174.1" per Apple’s approved mapping.

Please update these entries in apps/nativeapp/ios/FireAlert/PrivacyInfo.xcprivacy to ensure full compliance with Apple's documentation.

zipStoreBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
networkTimeout=10000
validateDistributionUrl=truezipStoreBase=GRADLE_USER_HOME
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix property formatting issue.

The line validateDistributionUrl=truezipStoreBase=GRADLE_USER_HOME appears to be incorrectly merged. It should be split into separate properties.

-validateDistributionUrl=truezipStoreBase=GRADLE_USER_HOME
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
validateDistributionUrl=truezipStoreBase=GRADLE_USER_HOME
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

@@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
zipStoreBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify Gradle version compatibility.

Upgrading to Gradle 8.6 is a major version jump. Please ensure compatibility with your Android build configuration and dependencies.


🌐 Web query:

What are the major changes and potential breaking changes in Gradle 8.6?

💡 Result:

Gradle 8.6 introduced several enhancements while maintaining backward compatibility, though one binary-breaking change was identified post-release:

Major Changes

  • Custom Configuration Cache Encryption: Added support for custom encryption keys to secure cached configuration data[4][5][6].
  • Build Init Improvements:
    • Default package generation for new projects
    • Non-interactive mode support
    • Kotlin DSL assignment syntax adoption[4][5][6]
  • Enhanced Dependency Management:
    • Provider types can now be used with dependency capability declarations[6]
  • Error Reporting:
    • Improved clarity for dependency-locking failures
    • Better circular reference detection in providers[6]
  • IDE Integration: Enhanced Problems API reporting and stability fixes for IntelliJ/Android Studio[4][6].

Potential Breaking Change

  • Binary Incompatibility: The DependencyAdder class was renamed to DependencyCollector, causing compatibility issues for plugins using this API[10]. This affects builds relying on:
    dependencies { 
        implementation(project(":lib")) 
    }

While the official release notes state no intentional breaking changes[4][5], developers using affected plugins should check for updates or adjust their dependency declarations[10].

Citations:


Attention: Gradle 8.6 Upgrade & Formatting Correction Required

Your update to Gradle 8.6 introduces several new enhancements—such as improved configuration cache security and better dependency management—but note that a known binary incompatibility (the renaming of the DependencyAdder class to DependencyCollector) may affect plugins dependent on that API. Please verify that your Android build configuration, dependencies, and any custom plugins fully support Gradle 8.6.

Additionally, there is a formatting issue detected on line 5 of apps/nativeapp/android/gradle/wrapper/gradle-wrapper.properties that needs correction.

  • Confirm compatibility of all plugins (especially those interacting with dependency management APIs).
  • Address the formatting issue on line 5.

Comment on lines +39 to +42
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=fire-alert
MYAPP_RELEASE_KEY_PASSWORD=fire-alert
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Introduction of Signing Properties and Removal of Flipper Configuration
The added keystore and signing properties (MYAPP_RELEASE_STORE_FILE, MYAPP_RELEASE_KEY_ALIAS, MYAPP_RELEASE_STORE_PASSWORD, and MYAPP_RELEASE_KEY_PASSWORD) properly configure the release signing. However, hardcoding these credentials might expose sensitive data if committed to version control. Consider using environment variables or a secure secret management approach for production builds.

item.id === res?.json?.data?.id ? res?.json?.data : item,
),
},
}
: null,
);
if (req?.json?.body.hasOwnProperty('isMonitored')) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid prototype pollution vulnerabilities.
Replace .hasOwnProperty('isMonitored') with a safer check:

-if (req?.json?.body.hasOwnProperty('isMonitored')) {
+if (Object.hasOwn(req?.json?.body, 'isMonitored')) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (req?.json?.body.hasOwnProperty('isMonitored')) {
if (Object.hasOwn(req?.json?.body, 'isMonitored')) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 319-319: Do not access Object.prototype method 'hasOwnProperty' from target object.

It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty().
See MDN web docs for more details.

(lint/suspicious/noPrototypeBuiltins)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a97885 and 5d0e990.

📒 Files selected for processing (1)
  • apps/nativeapp/android/settings.gradle (1 hunks)
🔇 Additional comments (1)
apps/nativeapp/android/settings.gradle (1)

28-28: Approved: Updated Gradle Plugin Inclusion Path

The change from react-native-gradle-plugin to @react-native/gradle-plugin is correctly updating the plugin inclusion path and aligns with the recent updates in the React Native ecosystem.

@@ -17,12 +17,12 @@ dependencyResolutionManagement {
// This should always be `mapbox` (not your username).
username = "mapbox"
// Use the secret token you stored in gradle.properties as the password
password = properties.getProperty('MAPBOX_DOWNLOADS_TOKEN')
password = password = System.getenv("MAPBOXGL_ACCCESS_TOKEN") ?: properties.getProperty("mapboxgl_access_token")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical Issue: Duplicate Assignment and Typo in Environment Variable

The assignment on line 20 contains an inadvertent duplicate (password = password =) and a likely typo in the environment variable name. The environment variable appears as MAPBOXGL_ACCCESS_TOKEN (with an extra 'C') but should probably be MAPBOXGL_ACCESS_TOKEN. Please remove the duplicate assignment and correct the variable name.

-            password = password = System.getenv("MAPBOXGL_ACCCESS_TOKEN") ?: properties.getProperty("mapboxgl_access_token")
+            password = System.getenv("MAPBOXGL_ACCESS_TOKEN") ?: properties.getProperty("mapboxgl_access_token")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
password = password = System.getenv("MAPBOXGL_ACCCESS_TOKEN") ?: properties.getProperty("mapboxgl_access_token")
password = System.getenv("MAPBOXGL_ACCESS_TOKEN") ?: properties.getProperty("mapboxgl_access_token")

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (2)
apps/server/src/server/api/routers/site.ts (2)

158-345: 🛠️ Refactor suggestion

Handle concurrency and remove large commented sections.

This procedure creates or attaches a user to a protected site. Possible concurrency issues can arise if multiple users create the same externalId simultaneously. Consider using transactions or unique constraints to avoid duplicates. Large commented-out code blocks also make the code harder to read; consider removing them or moving them to documentation.

createProtectedSite: protectedProcedure
    .input(createProtectedSiteSchema)
    .mutation(async ({ctx, input}) => {
        const userId = ctx.user!.id;
        try {
            const {externalId} = input
            const origin = 'firealert';
-            // radius 0 on Point would generally not return any results
-            // So monitor 1km around the point by default
-            // if (input.type === 'Point' && input.radius === 0) {
-            //     radius = 1000;
-            // } else { radius = input.radius; }

            const ppSite = getByExternalId(externalId)

-            // Any check by externalId?
-            // const protectedArea: {name: string, wdpa_id: string, geometry?: GeoJSON.Geometry} = {
-            //     name: "", wdpa_id: ""
-            // };
-            // [... many more commented lines removed ...]

            if(!ppSite) {
                throw new TRPCError({
                    code: "NOT_FOUND",
                    message: `No protected area found with WDPA ID ${externalId}.`
                })
            } 
                
            // Use a transaction to ensure database consistency
            return await ctx.prisma.$transaction(async (tx) => {
                const foundSite = await tx.site.findFirst({
                    where: {externalId: externalId},
                })

                let site: Partial<Site>, siteRelation: Partial<SiteRelation>;
                if(foundSite) {
                    const _foundSiteRelation = await tx.siteRelation.findFirst({
                        where: { userId: userId, siteId: foundSite.id },
                    })
                    if (_foundSiteRelation) {
                        site = foundSite;
                        siteRelation = _foundSiteRelation
                    } else {
                        const _siteRelation = await tx.siteRelation.create({
                            data: {
                                    role: "ROLE_VIEWER",
                                    userId: userId,
                                    siteId: foundSite.id,
                                isActive: true
                            },
                            select: {
                                siteId: true, userId: true, role: true,
                                site: {
                                    select: {
                                        id: true,
                                        type: true,
                                        name: true,
                                        radius: true,
                                        geometry: true,
                                        externalId: true,
                                    }
                                }
                            }
                        })
                        const _site = await tx.site.update({
                            where: {id: foundSite.id},
                            data: {isMonitored: true},
                        })
                        site = _site;
                        siteRelation = _siteRelation
                    }
                } else {
                    const _site = await tx.site.create({
                        data: {
                            origin: origin,
                            type: 'Polygon',
                            name: ppSite.name,
                            radius: 0,
                            kind: 'PROTECTED_SITE',
                            geometry: ppSite.geometry as unknown as Prisma.JsonObject,
                            externalId: ppSite.externalId,
                            lastUpdated: new Date(),
                            siteRelations: {
                                create: {
                                    user: { connect: { id: userId, } },
                                    role: 'ROLE_VIEWER',
                                }
                            },
                        },
                        select: {
                            id: true,
                            type: true,
                            name: true,
                            radius: true,
                            geometry: true,
                            externalId: true,
                            lastUpdated: true,
                            project: {
                                select: { id: true, name: true }
                            },
                            siteRelations: {
                                select: { siteId: true, userId: true, role: true }
                            }
                        },
                    });
                    site = _site;
                    siteRelation = _site.siteRelations
                }

                return {
                    status: "success",
                    data: {
                        site,
                        siteRelation
                    },
                };
            });
        } catch (error) {
            console.log(error);
            if (error instanceof TRPCError) {
                // if the error is already a TRPCError, just re-throw it
                throw error;
            }
            // if it's a different type of error, throw a new TRPCError
            throw new TRPCError({
                code: "INTERNAL_SERVER_ERROR",
                message: `Something Went Wrong`,
            });
        }
    }),

678-736: 🛠️ Refactor suggestion

Consider transaction for multi-step logic.

updateProtectedSite updates siteRelation and then queries and possibly updates the site. Wrap these steps in a single database transaction to avoid partial updates if a failure occurs in between.

updateProtectedSite: protectedProcedure
    .input(updateProtectedSiteSchema)
    .mutation(async ({ctx, input}) => {
        const userId = ctx.user!.id;
        const siteId = input.params.siteId;
        try {
+           return await ctx.prisma.$transaction(async (tx) => {
                const updatedSiteRelation = await ctx.prisma.siteRelation.updateMany({
                    where: { siteId: siteId, userId: userId },
                    data: {
                        isActive: input.body.isActive
                    },
                })

                if(updatedSiteRelation.count != 1) { return { status: 'failed' }; }

                const activeSiteRelations = await ctx.prisma.siteRelation.findMany({
                    where: { siteId: input.params.siteId, isActive:true }
                })
                if(activeSiteRelations.length === 0) {
                    await ctx.prisma.site.update({
                        where: {id: siteId}, data: {isMonitored: false}
                    })
                }

                const _siteRelation = await ctx.prisma.siteRelation.findFirst({
                    where: { siteId: siteId, userId: userId },
                    select: { siteId: true, isActive:true, site: { 
                        select: {
                            id: true,
                            name: true,
                            type: true,
                            isMonitored: true,
                            userId: true,
                            remoteId: true,
                            project: true,
                            geometry: true,
                        }
                    }}
                })

                const updatedSite = {
                    ..._siteRelation?.site,
                    isActive: _siteRelation?.isActive,
                }

                return { status: 'success', data: updatedSite};
+           });
        } catch (error) {
            console.log(error);
            if (error instanceof TRPCError) {
                // if the error is already a TRPCError, just re-throw it
                throw error;
            }
            // if it's a different type of error, throw a new TRPCError
            throw new TRPCError({
                code: "CONFLICT",
                message: `Error Updating Site.`,
            });
        }
    }),
🧹 Nitpick comments (4)
apps/server/src/server/api/routers/site.ts (4)

517-552: Improve error handling in getProtectedSites.

The current error handling uses a generic "NOT_FOUND" code for all errors, which isn't always appropriate. Also, proper type definitions would help with type safety.

getProtectedSites: protectedProcedure.query(async ({ctx}) => {
    const userId = ctx.user!.id;
    try {
-       // console.log(userId)
        const _siteRelation = await ctx.prisma.siteRelation.findMany({
            where: { userId: userId, },
            select: { siteId: true, isActive:true, site: { 
                select: {
                    id: true,
                    name: true,
                    type: true,
                    isMonitored: true,
                    userId: true,
                    remoteId: true,
                    project: true,
                    geometry: true,
                }
            } }
        })
  
        const sites = _siteRelation.map(el => ({
            ...el.site,
            isActive: el.isActive,
        }))
        return {
            status: 'success',
            data: sites,
        };
    } catch (error) {
        console.log(error)
        throw new TRPCError({
-           code: "NOT_FOUND",
+           code: "INTERNAL_SERVER_ERROR",
            message: `${error}`,
        });
    }
}),

347-430: Cleanup commented code.

Large blocks of commented code make the file harder to read and maintain. Consider removing this code or moving it to a separate file if it will be needed later.


251-251: Improve type safety with non-partial types.

Using Partial<Site> and Partial<SiteRelation> allows for unexpected null or undefined values. Consider using more specific types or interfaces that match exactly what you need.

-let site: Partial<Site>, siteRelation: Partial<SiteRelation>;
+interface SiteData {
+  id: string;
+  name: string;
+  type: string;
+  // Add other required fields
+}
+
+interface SiteRelationData {
+  siteId: string;
+  userId: string;
+  role: string;
+  // Add other required fields
+}
+
+let site: SiteData, siteRelation: SiteRelationData;

691-691: Improve error handling pattern.

The code returns { status: 'failed' } when the update doesn't affect exactly one row. This pattern is inconsistent with the rest of the codebase where errors are thrown using TRPCError.

-if(updatedSiteRelation.count != 1) { return { status: 'failed' }; }
+if(updatedSiteRelation.count != 1) { 
+    throw new TRPCError({
+        code: "NOT_FOUND",
+        message: "Site relation not found or multiple relations updated",
+    });
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23b29ba and 9697313.

📒 Files selected for processing (1)
  • apps/server/src/server/api/routers/site.ts (6 hunks)
🔇 Additional comments (2)
apps/server/src/server/api/routers/site.ts (2)

439-439: Address TODO comment.

There's a TODO comment that needs to be addressed about testing error cases with the getSitesForProject procedure.


8-9:

❓ Verification inconclusive

Verify the imported utility functions.

The imported utility functions filterByName and getByExternalId from "./sample-utils" appear to be placeholder implementations rather than production-ready code. These functions likely return mock data rather than performing actual database or API operations.


🏁 Script executed:

#!/bin/bash
# Check if these are sample/mock implementations
cat apps/server/src/server/api/routers/sample-utils.ts || fd sample-utils

Length of output: 357


Action Required: Confirm the Implementation Approach for Utility Functions

The utility functions in apps/server/src/server/api/routers/sample-utils.ts have been verified to use data from ./sample.json. Both filterByName() and getByExternalId() operate on this sample data, acting as mock implementations rather than performing real database or API operations.

  • Location: apps/server/src/server/api/routers/sample-utils.ts
  • Finding: The functions filter or search on static JSON data, confirming that they serve as placeholder implementations.

Please confirm whether these implementations are intentionally set as mocks for a demonstration environment or if production-ready implementations need to be provided.

const userId = ctx.user!.id;
try {
const {query} = input;
const results = filterByName(query)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace mock implementation with real database queries.

The filterByName function is likely a mock implementation. For production, this should be replaced with actual database queries that filter protected sites by name.

-const results = filterByName(query)
+const results = await ctx.prisma.site.findMany({
+    where: {
+        name: {
+            contains: query,
+            mode: 'insensitive'
+        },
+        kind: 'PROTECTED_SITE',
+        deletedAt: null,
+    },
+    select: {
+        id: true,
+        name: true,
+        type: true,
+        radius: true,
+        isMonitored: true,
+        lastUpdated: true,
+        externalId: true,
+        geometry: true,
+    }
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const results = filterByName(query)
const results = await ctx.prisma.site.findMany({
where: {
name: {
contains: query,
mode: 'insensitive'
},
kind: 'PROTECTED_SITE',
deletedAt: null,
},
select: {
id: true,
name: true,
type: true,
radius: true,
isMonitored: true,
lastUpdated: true,
externalId: true,
geometry: true,
}
});

Comment on lines +12 to +13
const pp_api = process.env.NEXT_PUBLIC_PROTECTED_PLANET_ENDPOINT as string;
const pp_api_key = process.env.NEXT_PUBLIC_PROTECTED_PLANET_API_KEY as string;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Environment variables aren't being properly validated.

These environment variables are cast as string without proper checks. If they're missing, your application could silently fail with unexpected behavior.

-const pp_api = process.env.NEXT_PUBLIC_PROTECTED_PLANET_ENDPOINT as string;
-const pp_api_key = process.env.NEXT_PUBLIC_PROTECTED_PLANET_API_KEY as string;
+const pp_api = process.env.NEXT_PUBLIC_PROTECTED_PLANET_ENDPOINT;
+const pp_api_key = process.env.NEXT_PUBLIC_PROTECTED_PLANET_API_KEY;
+
+if (!pp_api || !pp_api_key) {
+  console.error('Missing required Protected Planet API configuration');
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const pp_api = process.env.NEXT_PUBLIC_PROTECTED_PLANET_ENDPOINT as string;
const pp_api_key = process.env.NEXT_PUBLIC_PROTECTED_PLANET_API_KEY as string;
const pp_api = process.env.NEXT_PUBLIC_PROTECTED_PLANET_ENDPOINT;
const pp_api_key = process.env.NEXT_PUBLIC_PROTECTED_PLANET_API_KEY;
if (!pp_api || !pp_api_key) {
console.error('Missing required Protected Planet API configuration');
}

Comment on lines +112 to +156
findProtectedSites: protectedProcedure
.input(findProtectedSiteParams)
.mutation(async ({ctx, input}) => {
const userId = ctx.user!.id;
try {
const {query} = input;
const results = filterByName(query)

// const sites = await ctx.prisma.site.findMany({
// where: {
// userId: userId,
// deletedAt: null,
// kind: 'PROTECTED_SITE',
// },
// select: {
// id: true,
// name: true,
// type: true,
// radius: true,
// isMonitored: true,
// lastUpdated: true,
// userId: true,
// remoteId: true,
// project: {
// select: {
// id: true,
// name: true
// }
// },
// geometry: true,
// }
// })

return {
status: 'success',
data: results,
};
} catch (error) {
console.log(error)
throw new TRPCError({
code: "NOT_FOUND",
message: `${error}`,
});
}
}),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove commented code and use proper error handling.

The current implementation relies on a sample function but includes a large commented-out block. Additionally, the error handling uses a generic "NOT_FOUND" code for all errors, regardless of their nature.

findProtectedSites: protectedProcedure
    .input(findProtectedSiteParams)
    .mutation(async ({ctx, input}) => {
        const userId = ctx.user!.id;
        try {
            const {query} = input;
            const results = filterByName(query)
            
-            // const sites = await ctx.prisma.site.findMany({
-            //     where: {
-            //         userId: userId,
-            //         deletedAt: null,
-            //         kind: 'PROTECTED_SITE',
-            //     },
-            //     select: {
-            //         id: true,
-            //         name: true,
-            //         type: true,
-            //         radius: true,
-            //         isMonitored: true,
-            //         lastUpdated: true,
-            //         userId: true,
-            //         remoteId: true,
-            //         project: {
-            //             select: {
-            //                 id: true,
-            //                 name: true
-            //             }
-            //         },
-            //         geometry: true,
-            //     }
-            // })

            return {
                status: 'success',
                data: results,
            };
        } catch (error) {
            console.log(error)
            throw new TRPCError({
-                code: "NOT_FOUND",
+                code: "INTERNAL_SERVER_ERROR",
                message: `${error}`,
            });
        }
    }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
findProtectedSites: protectedProcedure
.input(findProtectedSiteParams)
.mutation(async ({ctx, input}) => {
const userId = ctx.user!.id;
try {
const {query} = input;
const results = filterByName(query)
// const sites = await ctx.prisma.site.findMany({
// where: {
// userId: userId,
// deletedAt: null,
// kind: 'PROTECTED_SITE',
// },
// select: {
// id: true,
// name: true,
// type: true,
// radius: true,
// isMonitored: true,
// lastUpdated: true,
// userId: true,
// remoteId: true,
// project: {
// select: {
// id: true,
// name: true
// }
// },
// geometry: true,
// }
// })
return {
status: 'success',
data: results,
};
} catch (error) {
console.log(error)
throw new TRPCError({
code: "NOT_FOUND",
message: `${error}`,
});
}
}),
findProtectedSites: protectedProcedure
.input(findProtectedSiteParams)
.mutation(async ({ctx, input}) => {
const userId = ctx.user!.id;
try {
const {query} = input;
const results = filterByName(query)
return {
status: 'success',
data: results,
};
} catch (error) {
console.log(error)
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: `${error}`,
});
}
}),

// radius = 1000;
// } else { radius = input.radius; }

const ppSite = getByExternalId(externalId)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace mock implementation with real API calls.

The getByExternalId function is likely a mock implementation. For production, this should be replaced with actual API calls to the Protected Planet API.

-const ppSite = getByExternalId(externalId)
+// Fetch the protected area data from the Protected Planet API
+const qs = new URLSearchParams();
+qs.append("token", pp_api_key);
+qs.append("with_geometry", "true");
+const pp_url = `${pp_api}/protected_areas/${externalId}?${qs.toString()}`;
+
+const res = await fetch(pp_url);
+if (!res.ok) {
+    throw new TRPCError({
+        code: 'INTERNAL_SERVER_ERROR',
+        message: `Failed to fetch protected area data: ${res.statusText}`,
+    });
+}
+
+const data = await res.json();
+const protectedArea = data?.protected_area;
+
+if (!protectedArea) {
+    throw new TRPCError({
+        code: "NOT_FOUND",
+        message: `No protected area found with WDPA ID ${externalId}.`
+    });
+}
+
+const ppSite = {
+    name: protectedArea.name,
+    externalId: protectedArea.wdpa_id.toString(),
+    geometry: protectedArea.geojson.geometry
+};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const ppSite = getByExternalId(externalId)
// Fetch the protected area data from the Protected Planet API
const qs = new URLSearchParams();
qs.append("token", pp_api_key);
qs.append("with_geometry", "true");
const pp_url = `${pp_api}/protected_areas/${externalId}?${qs.toString()}`;
const res = await fetch(pp_url);
if (!res.ok) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: `Failed to fetch protected area data: ${res.statusText}`,
});
}
const data = await res.json();
const protectedArea = data?.protected_area;
if (!protectedArea) {
throw new TRPCError({
code: "NOT_FOUND",
message: `No protected area found with WDPA ID ${externalId}.`
});
}
const ppSite = {
name: protectedArea.name,
externalId: protectedArea.wdpa_id.toString(),
geometry: protectedArea.geojson.geometry
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant