Skip to content

Feat baa#2898

Open
lohanidamodar wants to merge 12 commits intomainfrom
feat-baa
Open

Feat baa#2898
lohanidamodar wants to merge 12 commits intomainfrom
feat-baa

Conversation

@lohanidamodar
Copy link
Member

@lohanidamodar lohanidamodar commented Mar 1, 2026

What does this PR do?

(Provide a description of what this PR does.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

Summary by CodeRabbit

  • New Features

    • Full BAA addon management UI: enable/disable flows with confirm modals, prorated pricing, status badges (active, pending, scheduled removal), cancel/retry actions, and URL-based validation flow.
    • Billing and settings surfaces now surface addons more broadly and show clearer addon labels.
  • Refactor

    • Removed the old standalone BAA request form and integrated addon management into settings.
  • Chores

    • Updated console dependency.

- Updated the version of @appwrite.io/console in bun.lock and package.json.
- Enhanced BAA settings page to handle missing or invalid addonId gracefully.
- Added functionality to cancel and retry payment for pending BAA addon.
- Improved BAAEnableModal with prorated pricing calculation and updated agreement terms.
@appwrite
Copy link

appwrite bot commented Mar 1, 2026

Console (appwrite/console)

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Function scopes give you fine-grained control over API permissions

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 1, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds addon management for HIPAA BAA: introduces Dependencies.ADDONS and two analytics enum members (Submit.BAAAddonEnable, Submit.BAAAddonDisable). Updates a package dependency reference. Billing and settings load functions now depend on and fetch addons. Replaces the previous BAAModal with a new BAA UI component plus BAAEnableModal and BAADisableModal, including enable/disable flows, prorated pricing, validation via URL, cache invalidation, notifications, and analytics tracking. Adds addon-aware rendering in planSummary and minor import alias adjustments.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Feat baa' is vague and does not clearly convey the specific changes. While it hints at a 'baa' feature, the abbreviation is not self-explanatory without domain knowledge, and the title fails to summarize the main objective for someone scanning PR history. Use a more descriptive title such as 'Add HIPAA BAA addon management and enable/disable flows' to clearly communicate the primary change to reviewers.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-baa

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@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

🧹 Nitpick comments (6)
src/routes/(console)/organization-[organization]/settings/BAADisableModal.svelte (1)

14-14: Type annotation should include null.

The error variable is initialized to null but typed as string. This could cause TypeScript issues in strict mode.

♻️ Suggested fix
-    let error: string = null;
+    let error: string | null = null;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAADisableModal.svelte
at line 14, The variable error is declared as let error: string = null which
conflicts with strict TypeScript nullability rules; update the declaration for
the BAADisableModal component so the type allows null (e.g., change error's type
to string | null or use string | undefined) and ensure any downstream uses
handle the nullable type (adjust checks or non-null assertions where
appropriate).
src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte (3)

86-96: Silent handling of 409 may confuse users.

When a 409 (addon already exists) occurs, the modal silently closes without informing the user. Consider adding a notification to clarify that the addon was already enabled.

♻️ Suggested improvement
             // 409 means addon already exists (pending or active from prior attempt)
             if (e?.code === 409) {
                 await Promise.all([
                     invalidate(Dependencies.ADDONS),
                     invalidate(Dependencies.ORGANIZATION)
                 ]);
+                addNotification({
+                    message: 'BAA addon is already enabled or pending',
+                    type: 'info'
+                });
                 show = false;
             } else {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte
around lines 86 - 96, When handling the 409 branch in the BAA enable flow (the
block checking e?.code === 409), don't silently close the modal — add a
user-facing notification or set a visible message before hiding it so the user
knows the addon was already enabled; update the same branch that currently
invalidates Dependencies.ADDONS and Dependencies.ORGANIZATION and sets show =
false to also call the app's notification method (or set error/toast state) with
a clear message like "BAA addon already enabled" and still call
trackError/metrics as appropriate (refer to e?.code, show, Dependencies.ADDONS,
Dependencies.ORGANIZATION, trackError, and Submit.BAAAddonEnable to locate the
exact spot).

20-20: Type annotation should include null.

Same issue as in BAADisableModal.svelte - the error variable is initialized to null but typed as string.

♻️ Suggested fix
-    let error: string | null = null;
+    let error: string | null = null;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte
at line 20, The variable `error` in BAAEnableModal.svelte is declared as `let
error: string = null;` but allows null; update its type to include null (e.g.,
`string | null`) so the annotation matches the initializer and mirror the fix
applied in BAADisableModal.svelte; change the type annotation on the `error`
variable declaration (`let error`) accordingly throughout the component where
referenced.

60-72: Type assertion could be avoided with better type narrowing.

The as unknown as Models.PaymentAuthentication double cast is a TypeScript workaround. The API response type should ideally be a discriminated union that TypeScript can narrow properly.

♻️ Consider cleaner type handling
             if ('clientSecret' in result) {
-                const paymentAuth = result as unknown as Models.PaymentAuthentication;
+                // Result is PaymentAuthentication when clientSecret is present
+                const paymentAuth = result as Models.PaymentAuthentication;
                 const settingsUrl = resolve(

If TypeScript still complains, the SDK types may need updating to properly represent the union return type.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte
around lines 60 - 72, The double cast to Models.PaymentAuthentication should be
removed and replaced with proper type narrowing: add a type guard function (e.g.
isPaymentAuthentication(obj): obj is Models.PaymentAuthentication) that checks
for the discriminant properties used here (e.g. 'clientSecret' and 'addonId'),
then use that guard in the existing if ('clientSecret' in result) branch so you
can assign paymentAuth = result without the "as unknown as" cast and call
confirmPayment({ clientSecret: paymentAuth.clientSecret, paymentMethodId:
$organization.paymentMethodId, orgId: $organization.$id, route:
`${settingsUrl}?type=validate-addon&addonId=${paymentAuth.addonId}` }); if the
SDK types remain incorrect, update the SDK return type to a proper discriminated
union so TypeScript can narrow automatically.
src/routes/(console)/organization-[organization]/settings/+page.ts (1)

16-27: Minor inconsistency in nullish value handling.

The invoices branch returns undefined for non-cloud (line 20), while addons returns null (line 27). Consider using a consistent approach for both.

♻️ Suggested consistency fix
         isCloud
             ? sdk.forConsole.organizations.listInvoices({
                   organizationId: params.organization
               })
-            : undefined,
+            : null,
         isCloud
             ? sdk.forConsole.organizations
                   .listAddons({
                       organizationId: params.organization
                   })
                   .catch(() => null)
             : null
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/`(console)/organization-[organization]/settings/+page.ts around
lines 16 - 27, The code inconsistency returns undefined for the invoices branch
but null for the addons branch when isCloud is false; update one of them so both
non-cloud branches return the same nullish value (pick either undefined or null)
— modify the expressions around isCloud ?
sdk.forConsole.organizations.listInvoices({ organizationId: params.organization
}) : undefined and isCloud ? sdk.forConsole.organizations.listAddons({
organizationId: params.organization }).catch(() => null) : null so both use the
same fallback (e.g., change the invoices fallback to null or the addons fallback
to undefined and adjust the catch to return the chosen value), keeping
references to listInvoices, listAddons, isCloud, and params.organization intact.
src/routes/(console)/organization-[organization]/settings/BAA.svelte (1)

15-16: Use $routes aliases for these modal imports.

Switching these to route aliases keeps import style consistent with repository conventions.

Proposed refactor
-import BAAEnableModal from './BAAEnableModal.svelte';
-import BAADisableModal from './BAADisableModal.svelte';
+import BAAEnableModal from '$routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte';
+import BAADisableModal from '$routes/(console)/organization-[organization]/settings/BAADisableModal.svelte';

As per coding guidelines **/*.{js,ts,svelte}: Use $lib, $routes, and $themes path aliases for imports.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/`(console)/organization-[organization]/settings/BAA.svelte around
lines 15 - 16, Replace the relative imports for the two modal components with
the repository route alias: change the current relative imports of
BAAEnableModal and BAADisableModal to use the $routes alias so they follow
project conventions (import BAAEnableModal from '$routes/...'; import
BAADisableModal from '$routes/...'), ensuring the module specifiers point to the
same component files and update any import paths accordingly in the BAA.svelte
file where BAAEnableModal and BAADisableModal are referenced.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/routes/`(console)/organization-[organization]/settings/+page.svelte:
- Around line 35-45: The current try/catch around
sdk.forConsole.organizations.listAddons swallows errors and sets addonId = null,
which later causes the UI to show “BAA addon has been enabled” incorrectly;
instead, catch should record the failure (e.g., set an addonLookupError flag or
store the caught error) rather than conflating “no addon” and “lookup failed”,
and update the UI logic that reads addonId/pending to check this failure flag
before rendering the success/fallback branch; specifically, modify the block
using listAddons, pending, and addonId so the catch saves the error (or boolean)
and the downstream rendering avoids reporting success when addonLookupError is
set.

---

Nitpick comments:
In `@src/routes/`(console)/organization-[organization]/settings/+page.ts:
- Around line 16-27: The code inconsistency returns undefined for the invoices
branch but null for the addons branch when isCloud is false; update one of them
so both non-cloud branches return the same nullish value (pick either undefined
or null) — modify the expressions around isCloud ?
sdk.forConsole.organizations.listInvoices({ organizationId: params.organization
}) : undefined and isCloud ? sdk.forConsole.organizations.listAddons({
organizationId: params.organization }).catch(() => null) : null so both use the
same fallback (e.g., change the invoices fallback to null or the addons fallback
to undefined and adjust the catch to return the chosen value), keeping
references to listInvoices, listAddons, isCloud, and params.organization intact.

In `@src/routes/`(console)/organization-[organization]/settings/BAA.svelte:
- Around line 15-16: Replace the relative imports for the two modal components
with the repository route alias: change the current relative imports of
BAAEnableModal and BAADisableModal to use the $routes alias so they follow
project conventions (import BAAEnableModal from '$routes/...'; import
BAADisableModal from '$routes/...'), ensuring the module specifiers point to the
same component files and update any import paths accordingly in the BAA.svelte
file where BAAEnableModal and BAADisableModal are referenced.

In
`@src/routes/`(console)/organization-[organization]/settings/BAADisableModal.svelte:
- Line 14: The variable error is declared as let error: string = null which
conflicts with strict TypeScript nullability rules; update the declaration for
the BAADisableModal component so the type allows null (e.g., change error's type
to string | null or use string | undefined) and ensure any downstream uses
handle the nullable type (adjust checks or non-null assertions where
appropriate).

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte:
- Around line 86-96: When handling the 409 branch in the BAA enable flow (the
block checking e?.code === 409), don't silently close the modal — add a
user-facing notification or set a visible message before hiding it so the user
knows the addon was already enabled; update the same branch that currently
invalidates Dependencies.ADDONS and Dependencies.ORGANIZATION and sets show =
false to also call the app's notification method (or set error/toast state) with
a clear message like "BAA addon already enabled" and still call
trackError/metrics as appropriate (refer to e?.code, show, Dependencies.ADDONS,
Dependencies.ORGANIZATION, trackError, and Submit.BAAAddonEnable to locate the
exact spot).
- Line 20: The variable `error` in BAAEnableModal.svelte is declared as `let
error: string = null;` but allows null; update its type to include null (e.g.,
`string | null`) so the annotation matches the initializer and mirror the fix
applied in BAADisableModal.svelte; change the type annotation on the `error`
variable declaration (`let error`) accordingly throughout the component where
referenced.
- Around line 60-72: The double cast to Models.PaymentAuthentication should be
removed and replaced with proper type narrowing: add a type guard function (e.g.
isPaymentAuthentication(obj): obj is Models.PaymentAuthentication) that checks
for the discriminant properties used here (e.g. 'clientSecret' and 'addonId'),
then use that guard in the existing if ('clientSecret' in result) branch so you
can assign paymentAuth = result without the "as unknown as" cast and call
confirmPayment({ clientSecret: paymentAuth.clientSecret, paymentMethodId:
$organization.paymentMethodId, orgId: $organization.$id, route:
`${settingsUrl}?type=validate-addon&addonId=${paymentAuth.addonId}` }); if the
SDK types remain incorrect, update the SDK return type to a proper discriminated
union so TypeScript can narrow automatically.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec5b6ad and 599ce48.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • package.json
  • src/lib/actions/analytics.ts
  • src/lib/constants.ts
  • src/routes/(console)/organization-[organization]/billing/+page.ts
  • src/routes/(console)/organization-[organization]/billing/planSummary.svelte
  • src/routes/(console)/organization-[organization]/settings/+page.svelte
  • src/routes/(console)/organization-[organization]/settings/+page.ts
  • src/routes/(console)/organization-[organization]/settings/BAA.svelte
  • src/routes/(console)/organization-[organization]/settings/BAADisableModal.svelte
  • src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte
  • src/routes/(console)/organization-[organization]/settings/BAAModal.svelte
💤 Files with no reviewable changes (1)
  • src/routes/(console)/organization-[organization]/settings/BAAModal.svelte

Comment on lines +35 to +45
try {
const addons = await sdk.forConsole.organizations.listAddons({
organizationId: $organization.$id
});
const pending = addons.addons.find(
(a) => a.key === 'baa' && a.status === 'pending'
);
addonId = pending?.$id ?? null;
} catch {
addonId = null;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid reporting success when addon lookup fails.

If listAddons fails (network/5xx/auth), the code sets addonId = null and then shows “BAA addon has been enabled” in the fallback branch. That can hide real failures and mislead users.

Proposed fix
 onMount(async () => {
     name = $organization.name;

     if (page.url.searchParams.get('type') === 'validate-addon') {
         let addonId = page.url.searchParams.get('addonId');
+        let lookupFailed = false;

         // Fall back to listing addons if addonId is missing or invalid
         if (!addonId || addonId === 'undefined') {
             try {
                 const addons = await sdk.forConsole.organizations.listAddons({
                     organizationId: $organization.$id
                 });
                 const pending = addons.addons.find(
                     (a) => a.key === 'baa' && a.status === 'pending'
                 );
                 addonId = pending?.$id ?? null;
-            } catch {
-                addonId = null;
+            } catch (e) {
+                lookupFailed = true;
+                addNotification({
+                    message: e?.message ?? 'Unable to verify BAA addon status. Please retry.',
+                    type: 'error'
+                });
             }
         }
+
+        if (lookupFailed) {
+            const settingsUrl = resolve('/(console)/organization-[organization]/settings', {
+                organization: $organization.$id
+            });
+            await goto(settingsUrl, { replaceState: true });
+            return;
+        }

         if (addonId) {
             // existing logic...

Also applies to: 80-89

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/`(console)/organization-[organization]/settings/+page.svelte
around lines 35 - 45, The current try/catch around
sdk.forConsole.organizations.listAddons swallows errors and sets addonId = null,
which later causes the UI to show “BAA addon has been enabled” incorrectly;
instead, catch should record the failure (e.g., set an addonLookupError flag or
store the caught error) rather than conflating “no addon” and “lookup failed”,
and update the UI logic that reads addonId/pending to check this failure flag
before rendering the success/fallback branch; specifically, modify the block
using listAddons, pending, and addonId so the catch saves the error (or boolean)
and the downstream rendering avoids reporting success when addonLookupError is
set.

Copy link
Contributor

@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

🧹 Nitpick comments (2)
src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte (2)

60-73: Consider refining the type narrowing for payment authentication.

The as unknown as double assertion is a type-safety bypass. Since the API returns a union type, you could use a type guard or rely on the discriminant property check more cleanly.

Suggested approach using type predicate
+    function isPaymentAuth(result: Models.Addon | Models.PaymentAuthentication): result is Models.PaymentAuthentication {
+        return 'clientSecret' in result;
+    }

     async function handleSubmit() {
         // ...
-        if ('clientSecret' in result) {
-            const paymentAuth = result as unknown as Models.PaymentAuthentication;
+        if (isPaymentAuth(result)) {
             const settingsUrl = resolve(
                 '/(console)/organization-[organization]/settings',
                 { organization: $organization.$id }
             );
             await confirmPayment({
-                clientSecret: paymentAuth.clientSecret,
+                clientSecret: result.clientSecret,
                 paymentMethodId: $organization.paymentMethodId,
                 orgId: $organization.$id,
-                route: `${settingsUrl}?type=validate-addon&addonId=${paymentAuth.addonId}`
+                route: `${settingsUrl}?type=validate-addon&addonId=${result.addonId}`
             });
             return;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte
around lines 60 - 73, The code uses an unsafe double cast ("as unknown as
Models.PaymentAuthentication") to treat result as a PaymentAuthentication;
replace this with a proper type guard that narrows the union safely (e.g. add a
function isPaymentAuthentication(obj): obj is Models.PaymentAuthentication that
checks for discriminant properties like 'clientSecret' and 'addonId'), then use
if (isPaymentAuthentication(result)) { const paymentAuth = result; ...
confirmPayment(...) } and remove the "as unknown as" assertion; update the block
around result and the confirmPayment call to rely on the type guard.

85-96: Add type guard for error properties.

Accessing e.message without a type check can fail if the caught value isn't an Error object. Consider narrowing the type.

Proposed fix
         } catch (e) {
             // 409 means addon already exists (pending or active from prior attempt)
-            if (e?.code === 409) {
+            const err = e as { code?: number; message?: string };
+            if (err?.code === 409) {
                 await Promise.all([
                     invalidate(Dependencies.ADDONS),
                     invalidate(Dependencies.ORGANIZATION)
                 ]);
                 show = false;
             } else {
-                error = e.message;
+                error = err?.message ?? 'An unexpected error occurred';
                 trackError(e, Submit.BAAAddonEnable);
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte
around lines 85 - 96, The catch block accesses e?.code and e.message without
narrowing the caught value; add a type guard and normalize the error before
using its properties. Replace direct checks with a safe guard like: determine
isConflict by checking e is an object and has a code property (e && typeof (e as
any).code !== 'undefined' && (e as any).code === 409), and derive error text
with const errMessage = e instanceof Error ? e.message : String(e); then use
isConflict to run invalidate/close modal and otherwise set error = errMessage
and call trackError(e, Submit.BAAAddonEnable). Update references in this block
(the catch, show, error, invalidate calls, and trackError invocation)
accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte:
- Line 20: The variable declaration let error: string = null; has a type
mismatch because null is assigned; change the type to allow null (e.g., update
the declaration of error to let error: string | null = null) and ensure any
assignments in handleSubmit and other places (setting error = null or assigning
strings) are compatible with string | null.

---

Nitpick comments:
In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte:
- Around line 60-73: The code uses an unsafe double cast ("as unknown as
Models.PaymentAuthentication") to treat result as a PaymentAuthentication;
replace this with a proper type guard that narrows the union safely (e.g. add a
function isPaymentAuthentication(obj): obj is Models.PaymentAuthentication that
checks for discriminant properties like 'clientSecret' and 'addonId'), then use
if (isPaymentAuthentication(result)) { const paymentAuth = result; ...
confirmPayment(...) } and remove the "as unknown as" assertion; update the block
around result and the confirmPayment call to rely on the type guard.
- Around line 85-96: The catch block accesses e?.code and e.message without
narrowing the caught value; add a type guard and normalize the error before
using its properties. Replace direct checks with a safe guard like: determine
isConflict by checking e is an object and has a code property (e && typeof (e as
any).code !== 'undefined' && (e as any).code === 409), and derive error text
with const errMessage = e instanceof Error ? e.message : String(e); then use
isConflict to run invalidate/close modal and otherwise set error = errMessage
and call trackError(e, Submit.BAAAddonEnable). Update references in this block
(the catch, show, error, invalidate calls, and trackError invocation)
accordingly.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 599ce48 and 12db4e6.

📒 Files selected for processing (1)
  • src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 1, 2026

Greptile Summary

This PR replaces the old form-based BAA request flow with a complete addon management system. Users can now enable, disable, and re-enable the BAA addon directly through the settings UI with integrated Stripe payment handling and prorated pricing.

Key changes:

  • Replaced BAAModal.svelte (form submission) with BAAEnableModal.svelte and BAADisableModal.svelte for addon lifecycle management
  • Added payment validation flow after Stripe redirect with fallback logic for webhook-processed payments
  • Implemented prorated billing calculation for mid-cycle addon activation
  • Added addon display in billing summary with status badges (active, pending, scheduled for removal)
  • Integrated cancel & retry flow for interrupted payments

Issues found:

  • Spelling error: 'HIPPA' should be 'HIPAA' in billing summary display name

Confidence Score: 4/5

  • Safe to merge after fixing the HIPAA spelling error
  • Well-structured implementation with proper error handling and state management. The only issue is a minor spelling error in the billing display name that should be corrected before merge.
  • src/routes/(console)/organization-[organization]/billing/planSummary.svelte requires a spelling fix

Important Files Changed

Filename Overview
src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte New modal for enabling BAA addon with pricing display and payment flow integration
src/routes/(console)/organization-[organization]/settings/BAADisableModal.svelte New modal for disabling BAA addon with end-of-cycle removal logic
src/routes/(console)/organization-[organization]/settings/BAA.svelte Replaced form-based BAA request with full addon management UI including enable/disable/re-enable flows
src/routes/(console)/organization-[organization]/settings/+page.svelte Added payment validation flow for BAA addon after Stripe redirect
src/routes/(console)/organization-[organization]/billing/planSummary.svelte Added BAA addon display in billing summary with typo in display name

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Start([User clicks Enable BAA]) --> EnableModal[BAAEnableModal opens]
    EnableModal --> Submit[User accepts & submits]
    Submit --> CreateAddon[Call createToggleAddon API]
    CreateAddon --> CheckResponse{Response type?}
    
    CheckResponse -->|Contains clientSecret| PaymentRequired[Payment authentication required]
    CheckResponse -->|Addon object| Success[Show success notification]
    CheckResponse -->|409 error| AlreadyExists[Addon already exists]
    
    PaymentRequired --> StripeRedirect[Redirect to Stripe payment]
    StripeRedirect --> ReturnToSettings[Return to settings with validate-addon]
    
    ReturnToSettings --> GetAddonId{AddonId in URL?}
    GetAddonId -->|Yes| ValidatePayment[Call validateToggleAddonPayment]
    GetAddonId -->|No/undefined| FetchPending[Fetch pending addons]
    
    FetchPending --> FoundPending{Found pending BAA?}
    FoundPending -->|Yes| ValidatePayment
    FoundPending -->|No| AssumeWebhook[Assume webhook activated]
    
    ValidatePayment --> ValidationResult{Validation result?}
    ValidationResult -->|Success| Success
    ValidationResult -->|404/not found| AssumeWebhook
    ValidationResult -->|Other error| ShowError[Show error notification]
    
    Success --> Invalidate[Invalidate ADDONS & ORGANIZATION]
    AlreadyExists --> Invalidate
    AssumeWebhook --> Invalidate
    Invalidate --> End([BAA addon enabled])
    ShowError --> End
Loading

Last reviewed commit: dd159cf

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

12 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +80 to +89
} else {
// No pending addon found — likely already activated by webhook
await Promise.all([
invalidate(Dependencies.ADDONS),
invalidate(Dependencies.ORGANIZATION)
]);
addNotification({
message: 'BAA addon has been enabled',
type: 'success'
});
Copy link
Contributor

Choose a reason for hiding this comment

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

When addonId is null (either missing from URL or not found in pending addons), this shows "BAA addon has been enabled" success message without confirming the addon was actually enabled. Consider showing a different message or checking addon status before displaying success.


// addons (additional members, projects, etc.)
const billingAddonNames: Record<string, string> = {
addon_baa: 'HIPPA BAA'
Copy link
Contributor

Choose a reason for hiding this comment

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

'HIPPA' is misspelled — it should be 'HIPAA' (Health Insurance Portability and Accountability Act)

Suggested change
addon_baa: 'HIPPA BAA'
addon_baa: 'HIPAA BAA'

Copy link
Contributor

@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

♻️ Duplicate comments (2)
src/routes/(console)/organization-[organization]/settings/+page.svelte (1)

34-45: ⚠️ Potential issue | 🟠 Major

Don’t convert addon lookup failures into success UX.

At Line 43-45, lookup errors are swallowed by forcing addonId = null, which then falls into the success path at Line 80-89 and shows “BAA addon has been enabled” even when lookup failed.

Proposed fix
         if (page.url.searchParams.get('type') === 'validate-addon') {
             let addonId = page.url.searchParams.get('addonId');
+            let lookupFailed = false;

             // Fall back to listing addons if addonId is missing or invalid
             if (!addonId || addonId === 'undefined') {
                 try {
                     const addons = await sdk.forConsole.organizations.listAddons({
                         organizationId: $organization.$id
                     });
                     const pending = addons.addons.find(
                         (a) => a.key === 'baa' && a.status === 'pending'
                     );
                     addonId = pending?.$id ?? null;
-                } catch {
-                    addonId = null;
+                } catch (e) {
+                    lookupFailed = true;
+                    addNotification({
+                        message: e?.message ?? 'Unable to verify BAA addon status. Please retry.',
+                        type: 'error'
+                    });
                 }
             }
+
+            if (lookupFailed) {
+                const settingsUrl = resolve('/(console)/organization-[organization]/settings', {
+                    organization: $organization.$id
+                });
+                await goto(settingsUrl, { replaceState: true });
+                return;
+            }

Also applies to: 80-89

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/`(console)/organization-[organization]/settings/+page.svelte
around lines 34 - 45, The try/catch that resolves addonId (using
sdk.forConsole.organizations.listAddons and the pending lookup into
pending?.$id) currently swallows lookup errors by setting addonId = null which
later triggers the success UI that shows "BAA addon has been enabled"; instead,
surface the error so the success path won’t run: in the catch, record an
explicit failure state (e.g., set an error flag or rethrow) and ensure the
downstream rendering logic that displays the "BAA addon has been enabled"
message checks that no lookup error occurred before showing success; update the
code around the addonId resolution and the success-rendering branch to consult
this error flag (or propagate the exception) rather than treating null as "not
enabled."
src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte (1)

20-20: ⚠️ Potential issue | 🟡 Minor

Fix nullable error typing (still unresolved).

At Line 20, error is declared as string but is assigned null. Use string | null.

Proposed fix
-    let error: string = null;
+    let error: string | null = null;
#!/bin/bash
# Verify nullable typing mismatches in Svelte files
rg -nP 'let\s+error:\s*string\s*=\s*null;' --type svelte
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte
at line 20, The variable error in BAAEnableModal.svelte is typed as string but
initialized to null; change its type to allow null by updating the declaration
of error (the let error variable) to use the nullable union type string | null
so the initialization is valid and TypeScript type-checks pass.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/routes/`(console)/organization-[organization]/settings/BAADisableModal.svelte:
- Line 14: The variable error in BAADisableModal.svelte is declared as let
error: string = null but is initialized and later reset to null; change its type
to allow null by declaring it as string | null so TypeScript is type-safe —
update the declaration of error (the let error variable) to use the union type
string | null and ensure any assignments that set it to null remain valid.

---

Duplicate comments:
In `@src/routes/`(console)/organization-[organization]/settings/+page.svelte:
- Around line 34-45: The try/catch that resolves addonId (using
sdk.forConsole.organizations.listAddons and the pending lookup into
pending?.$id) currently swallows lookup errors by setting addonId = null which
later triggers the success UI that shows "BAA addon has been enabled"; instead,
surface the error so the success path won’t run: in the catch, record an
explicit failure state (e.g., set an error flag or rethrow) and ensure the
downstream rendering logic that displays the "BAA addon has been enabled"
message checks that no lookup error occurred before showing success; update the
code around the addonId resolution and the success-rendering branch to consult
this error flag (or propagate the exception) rather than treating null as "not
enabled."

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte:
- Line 20: The variable error in BAAEnableModal.svelte is typed as string but
initialized to null; change its type to allow null by updating the declaration
of error (the let error variable) to use the nullable union type string | null
so the initialization is valid and TypeScript type-checks pass.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 12db4e6 and 214ba5c.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • package.json
  • src/routes/(console)/organization-[organization]/billing/planSummary.svelte
  • src/routes/(console)/organization-[organization]/settings/+page.svelte
  • src/routes/(console)/organization-[organization]/settings/BAA.svelte
  • src/routes/(console)/organization-[organization]/settings/BAADisableModal.svelte
  • src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/routes/(console)/organization-[organization]/billing/planSummary.svelte
  • package.json

export let show = false;
export let addonId: string;

let error: string = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read its content
if [ -f "src/routes/(console)/organization-[organization]/settings/BAADisableModal.svelte" ]; then
  echo "=== File found, reading content ==="
  cat -n "src/routes/(console)/organization-[organization]/settings/BAADisableModal.svelte"
else
  echo "File not found at exact path, trying to find it..."
  find . -name "BAADisableModal.svelte" -type f 2>/dev/null
fi

Repository: appwrite/console

Length of output: 2367


Fix nullable error typing.

At line 14, error is typed as string but initialized to null and can be reset to null (line 19) in the try block. Change the type to string | null to be type-safe.

Proposed fix
-    let error: string = null;
+    let error: string | null = null;
📝 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
let error: string = null;
let error: string | null = null;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAADisableModal.svelte
at line 14, The variable error in BAADisableModal.svelte is declared as let
error: string = null but is initialized and later reset to null; change its type
to allow null by declaring it as string | null so TypeScript is type-safe —
update the declaration of error (the let error variable) to use the union type
string | null and ensure any assignments that set it to null remain valid.

Copy link
Contributor

@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

♻️ Duplicate comments (1)
src/routes/(console)/organization-[organization]/settings/+page.svelte (1)

34-45: ⚠️ Potential issue | 🟠 Major

Don’t silently downgrade addon lookup failures to “no addon found.”

When listAddons fails (Line 43), the code sets addonId = null and continues to redirect (Line 82), so validation is skipped with no user-visible failure signal. Keep lookup failure distinct from “no pending addon” and short-circuit after notifying.

Suggested fix
         if (page.url.searchParams.get('type') === 'validate-addon') {
             let addonId = page.url.searchParams.get('addonId');
+            let addonLookupFailed = false;

             // Fall back to listing addons if addonId is missing or invalid
             if (!addonId || addonId === 'undefined') {
                 try {
                     const addons = await sdk.forConsole.organizations.listAddons({
                         organizationId: $organization.$id
                     });
                     const pending = addons.addons.find(
                         (a) => a.key === 'baa' && a.status === 'pending'
                     );
                     addonId = pending?.$id ?? null;
-                } catch {
-                    addonId = null;
+                } catch (e) {
+                    addonLookupFailed = true;
+                    addNotification({
+                        message: e?.message ?? 'Unable to verify BAA addon status. Please retry.',
+                        type: 'error'
+                    });
+                    trackError(e, Submit.BAAAddonEnable);
                 }
             }
+
+            if (addonLookupFailed) {
+                const settingsUrl = resolve('/(console)/organization-[organization]/settings', {
+                    organization: $organization.$id
+                });
+                await goto(settingsUrl, { replaceState: true });
+                return;
+            }

             if (addonId) {

Also applies to: 82-85

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/routes/`(console)/organization-[organization]/settings/+page.svelte
around lines 34 - 45, The try/catch around
sdk.forConsole.organizations.listAddons silently converts lookup failures into
"no addon" by setting addonId = null; instead, preserve lookup errors by either
rethrowing the error or setting a lookupFailed flag and returning early so the
page doesn't continue to the validation/redirect path. Update the catch block in
the load logic that calls sdk.forConsole.organizations.listAddons (the block
that assigns addonId and inspects pending) to log/report the caught error and
short-circuit (e.g., throw the error or return an error result) rather than
assigning addonId = null, so downstream logic that uses addonId or triggers the
redirect can detect and show an error to the user.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte:
- Around line 34-47: Guard against invalid invoice date strings by validating
parsed dates before doing proration math: after creating cycleStart and cycleEnd
from currentInvoiceDate and nextInvoiceDate, check isNaN(cycleStart.getTime())
or isNaN(cycleEnd.getTime()) and if invalid, fall back to safe defaults (e.g.,
set cycleStart = today or cycleEnd = new Date(today.getTime() +
30*24*60*60*1000)) or return 0 price; then compute totalDays and remainingDays
as before using these validated dates and ensure totalDays is at least 1 to
avoid NaN/divide-by-zero. Reference the variables cycleStart, cycleEnd,
totalDays, remainingDays, currentInvoiceDate, nextInvoiceDate, and
BAA_MONTHLY_PRICE when making the change.

---

Duplicate comments:
In `@src/routes/`(console)/organization-[organization]/settings/+page.svelte:
- Around line 34-45: The try/catch around
sdk.forConsole.organizations.listAddons silently converts lookup failures into
"no addon" by setting addonId = null; instead, preserve lookup errors by either
rethrowing the error or setting a lookupFailed flag and returning early so the
page doesn't continue to the validation/redirect path. Update the catch block in
the load logic that calls sdk.forConsole.organizations.listAddons (the block
that assigns addonId and inspects pending) to log/report the caught error and
short-circuit (e.g., throw the error or return an error result) rather than
assigning addonId = null, so downstream logic that uses addonId or triggers the
redirect can detect and show an error to the user.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 214ba5c and e50b147.

📒 Files selected for processing (3)
  • src/routes/(console)/organization-[organization]/billing/planSummary.svelte
  • src/routes/(console)/organization-[organization]/settings/+page.svelte
  • src/routes/(console)/organization-[organization]/settings/BAAEnableModal.svelte
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/organization-[organization]/billing/planSummary.svelte

Comment on lines +34 to +47
const today = new Date();
const cycleStart = new Date(currentInvoiceDate);
const cycleEnd = new Date(nextInvoiceDate);

const totalDays = Math.max(
1,
Math.ceil((cycleEnd.getTime() - cycleStart.getTime()) / (1000 * 60 * 60 * 24))
);
const remainingDays = Math.max(
0,
Math.ceil((cycleEnd.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
);

return Math.round(((BAA_MONTHLY_PRICE * remainingDays) / totalDays) * 100) / 100;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard against invalid invoice date strings in proration math.

If either parsed date is invalid, arithmetic returns NaN, which can surface as an invalid currency value in the modal. Add a parse-validity fallback.

Suggested fix
         const today = new Date();
         const cycleStart = new Date(currentInvoiceDate);
         const cycleEnd = new Date(nextInvoiceDate);
+
+        if (Number.isNaN(cycleStart.getTime()) || Number.isNaN(cycleEnd.getTime())) {
+            return BAA_MONTHLY_PRICE;
+        }

         const totalDays = Math.max(
             1,
             Math.ceil((cycleEnd.getTime() - cycleStart.getTime()) / (1000 * 60 * 60 * 24))
         );
📝 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 today = new Date();
const cycleStart = new Date(currentInvoiceDate);
const cycleEnd = new Date(nextInvoiceDate);
const totalDays = Math.max(
1,
Math.ceil((cycleEnd.getTime() - cycleStart.getTime()) / (1000 * 60 * 60 * 24))
);
const remainingDays = Math.max(
0,
Math.ceil((cycleEnd.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
);
return Math.round(((BAA_MONTHLY_PRICE * remainingDays) / totalDays) * 100) / 100;
const today = new Date();
const cycleStart = new Date(currentInvoiceDate);
const cycleEnd = new Date(nextInvoiceDate);
if (Number.isNaN(cycleStart.getTime()) || Number.isNaN(cycleEnd.getTime())) {
return BAA_MONTHLY_PRICE;
}
const totalDays = Math.max(
1,
Math.ceil((cycleEnd.getTime() - cycleStart.getTime()) / (1000 * 60 * 60 * 24))
);
const remainingDays = Math.max(
0,
Math.ceil((cycleEnd.getTime() - today.getTime()) / (1000 * 60 * 60 * 24))
);
return Math.round(((BAA_MONTHLY_PRICE * remainingDays) / totalDays) * 100) / 100;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/routes/`(console)/organization-[organization]/settings/BAAEnableModal.svelte
around lines 34 - 47, Guard against invalid invoice date strings by validating
parsed dates before doing proration math: after creating cycleStart and cycleEnd
from currentInvoiceDate and nextInvoiceDate, check isNaN(cycleStart.getTime())
or isNaN(cycleEnd.getTime()) and if invalid, fall back to safe defaults (e.g.,
set cycleStart = today or cycleEnd = new Date(today.getTime() +
30*24*60*60*1000)) or return 0 price; then compute totalDays and remainingDays
as before using these validated dates and ensure totalDays is at least 1 to
avoid NaN/divide-by-zero. Reference the variables cycleStart, cycleEnd,
totalDays, remainingDays, currentInvoiceDate, nextInvoiceDate, and
BAA_MONTHLY_PRICE when making the change.

Copy link
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/stores/migration.ts`:
- Line 2: The current import aliases AppwriteMigrationResource as Resources
which narrows providerResources to Appwrite-only enums and breaks calls to
getSupabaseReport, getFirebaseReport, and getNHostReport from
resource-form.svelte; fix by importing the provider-specific enum types (e.g.,
AppwriteMigrationResource, SupabaseMigrationResource, FirebaseMigrationResource,
NHostMigrationResource) from `@appwrite.io/console` and change the
providerResources type to a mapped/union type keyed by provider (e.g., a
ProviderResourcesMap or a discriminated union) so each provider maps to its own
enum; update any references to Resources in migration.ts and the
resource-form.svelte parameters to use the new mapped type so
getSupabaseReport/getFirebaseReport/getNHostReport receive the correct enum
values.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e50b147 and f63879a.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • package.json
  • src/lib/stores/migration.ts
  • src/routes/(console)/(migration-wizard)/resource-form.svelte
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

@@ -1,5 +1,5 @@
import { writable } from 'svelte/store';
import { Resources } from '@appwrite.io/console';
import { AppwriteMigrationResource as Resources } from '@appwrite.io/console';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check the narrowing introduced in migration store =="
rg -nP 'AppwriteMigrationResource as Resources|providerResources:\s*Record<Provider,\s*Resources\[\]>' src/lib/stores/migration.ts -C3

echo "== Confirm failing call sites and expected provider-specific report methods =="
rg -nP 'get(Supabase|Firebase|NHost)Report\(' src/routes/\(console\)/\(migration-wizard\)/resource-form.svelte -C3

echo "== Discover migration resource enums referenced in repository =="
rg -nP '\b(AppwriteMigrationResource|SupabaseMigrationResource|FirebaseMigrationResource|NHostMigrationResource)\b' -g '!**/node_modules/**'

echo "== Print declared `@appwrite.io/console` dependency version =="
python - <<'PY'
import json, pathlib
p = pathlib.Path("package.json")
if not p.exists():
    print("package.json not found")
    raise SystemExit(0)
data = json.loads(p.read_text())
v = data.get("dependencies", {}).get("@appwrite.io/console") or data.get("devDependencies", {}).get("@appwrite.io/console")
print("@appwrite.io/console:", v)
PY

Repository: appwrite/console

Length of output: 2125


Appwrite-only enum alias breaks provider-specific SDK method calls

Line 2 aliases AppwriteMigrationResource as the shared Resources type, which narrows providerResources to appwrite-only enum values. This causes type incompatibility when getSupabaseReport(), getFirebaseReport(), and getNHostReport() are called with mismatched resource types (lines 56, 67, 74 in resource-form.svelte).

The @todo comment on line 54 confirms this was known to be incomplete.

Import the provider-specific resource enums from @appwrite.io/console and use a mapped type for providerResources:

Proposed fix
-import { AppwriteMigrationResource as Resources } from '@appwrite.io/console';
+import {
+    AppwriteMigrationResource,
+    SupabaseMigrationResource,
+    FirebaseMigrationResource,
+    NHostMigrationResource
+} from '@appwrite.io/console';

+type ProviderResourcesMap = {
+    appwrite: AppwriteMigrationResource[];
+    supabase: SupabaseMigrationResource[];
+    firebase: FirebaseMigrationResource[];
+    nhost: NHostMigrationResource[];
+};

-export const providerResources: Record<Provider, Resources[]> = {
-    appwrite: Object.values(Resources),
+export const providerResources: ProviderResourcesMap = {
+    appwrite: Object.values(AppwriteMigrationResource) as AppwriteMigrationResource[],
     supabase: [
-        Resources.User,
-        Resources.Database,
+        SupabaseMigrationResource.User,
+        SupabaseMigrationResource.Database,
         // ...
     ],
     // firebase/nhost similarly with their own enums
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/stores/migration.ts` at line 2, The current import aliases
AppwriteMigrationResource as Resources which narrows providerResources to
Appwrite-only enums and breaks calls to getSupabaseReport, getFirebaseReport,
and getNHostReport from resource-form.svelte; fix by importing the
provider-specific enum types (e.g., AppwriteMigrationResource,
SupabaseMigrationResource, FirebaseMigrationResource, NHostMigrationResource)
from `@appwrite.io/console` and change the providerResources type to a
mapped/union type keyed by provider (e.g., a ProviderResourcesMap or a
discriminated union) so each provider maps to its own enum; update any
references to Resources in migration.ts and the resource-form.svelte parameters
to use the new mapped type so getSupabaseReport/getFirebaseReport/getNHostReport
receive the correct enum values.

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