Skip to content

Conversation

@harr1424
Copy link
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-22143

📔 Objective

This PR only contains work done to refactor the Send related enums and one export related enum.

Import related enums will be included in a separate PR, per suggestion in the discussion below:

Description

A decision was made to move away from using enums in TS and instead to use const objects.

Task

Refactor all tools enums into const objects.

For easier review it might be good to split Send and Import into separate PRs

When changing SendType, please be careful that it will likely break some navigation on the send-v2.component and maybe even desktop related as it doesn’t share the UI components yet

Remove all associated eslint disable statements

Context/Resources
PR enabling eslint rule

Ticket for enabling eslint rule

PR for contributing docs

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

…nto PM-24105-Tools-Remove-getUserKey-on-the-key-service

merged PM-24099-Tools-Remove-getOrgKey-from-the-key-service to avoid redundant refactor
Functional testing will be completed before review / merge for the following functionality in every applicable app:
• send
• individual and org encrypted export
• individual import
• bitwarden encrypted JSON import
Will have conflicts with PM-24099, wait for PM-24099 review before beginning to resolve
• Wait for non-null UserId emitted by AccountService
• Encapsulate these calls in private local functions
@harr1424 harr1424 requested review from a team as code owners September 12, 2025 14:48
@harr1424 harr1424 requested a review from coroiu September 12, 2025 14:48
@github-actions
Copy link
Contributor

github-actions bot commented Sep 12, 2025

Logo
Checkmarx One – Scan Summary & Details0bd4201b-3467-48b2-9807-66a58f878d15

New Issues (1)

Checkmarx found the following issues in this Pull Request

Severity Issue Source File / Package Checkmarx Insight
MEDIUM Missing_HSTS_Header /apps/web/src/app/dirt/reports/pages/inactive-two-factor-report.component.ts: 143
detailsThe web-application does not define an HSTS header, leaving it vulnerable to attack.
ID: alhjfubOVRYrjEwL%2BQtMJ8mzlvY%3D
Attack Vector

@codecov
Copy link

codecov bot commented Sep 12, 2025

Codecov Report

❌ Patch coverage is 38.59649% with 35 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.39%. Comparing base (81453ed) to head (57a7ba6).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
libs/angular/src/tools/send/add-edit.component.ts 27.27% 24 Missing ⚠️
.../popup/send-v2/add-edit/send-add-edit.component.ts 0.00% 4 Missing ⚠️
.../components/send-details/send-details.component.ts 69.23% 4 Missing ⚠️
...owser/src/tools/popup/send-v2/send-v2.component.ts 66.66% 0 Missing and 1 partial ⚠️
apps/cli/src/tools/send/send.program.ts 0.00% 1 Missing ⚠️
apps/desktop/src/app/tools/send/send.component.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #16399      +/-   ##
==========================================
+ Coverage   41.25%   41.39%   +0.14%     
==========================================
  Files        3546     3546              
  Lines      102040   102049       +9     
  Branches    15308    15317       +9     
==========================================
+ Hits        42099    42246     +147     
+ Misses      58177    58037     -140     
- Partials     1764     1766       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

coroiu
coroiu previously approved these changes Sep 15, 2025
…-Refactor-TS-Enums-to-be-const-objects

merge changes from import related branch
…to PM-22143-Tools-Refactor-TS-Enums-to-be-const-objects

merge changes from PM-24105
…PORT-ONLY' into PM-22143-Tools-Refactor-TS-Enums-to-be-const-objects

merge changes from export related branch
@harr1424 harr1424 changed the title PM-22143 Refactor TS enums to be const objects (Send and export enums only) PM-22143 Refactor TS enums to be const objects Oct 8, 2025
@harr1424 harr1424 marked this pull request as draft October 8, 2025 16:51
@bw-ghapp
Copy link
Contributor

bw-ghapp bot commented Oct 8, 2025

Changes in this PR impact the Autofill experience of the browser client

BIT has tested the core experience with these changes and all feature flags disabled.

✅ Fortunately, these BIT tests have passed! 🎉

@bw-ghapp
Copy link
Contributor

bw-ghapp bot commented Oct 8, 2025

Changes in this PR impact the Autofill experience of the browser client

BIT has tested the core experience with these changes and the feature flag configuration used by vault.bitwarden.com.

✅ Fortunately, these BIT tests have passed! 🎉

harr1424 added a commit that referenced this pull request Oct 15, 2025
@harr1424 harr1424 changed the title PM-22143 Refactor TS enums to be const objects PM-22143 Refactor TS enums to be const objects (Send specific enums) Oct 15, 2025
@sonarqubecloud
Copy link

@harr1424 harr1424 marked this pull request as ready for review October 15, 2025 16:44
this.sendId = params.sendId;
this.type = parseInt(params.type, 10);
const sendTypeValue = parseInt(params.type, 10);
if (sendTypeValue === SendType.Text || sendTypeValue === SendType.File) {

Choose a reason for hiding this comment

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

[SendType.Text, SendType.File].indexOf(sendTypeValue) !== -1

could be

this.sendListFiltersService.filters$,
])
.pipe(takeUntilDestroyed())
.subscribe(([emptyList, noFilteredResults, currentFilter]) => {

Choose a reason for hiding this comment

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

to add types for the args

}
} else {
this.title = "allSends";
}

Choose a reason for hiding this comment

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

could be this to avoid nested if conditions

if (currentFilter?.sendType != null) {
const titleMap: Record<SendType, string> = {
[SendType.File]: 'fileSends',
[SendType.Text]: 'textSends'
};

this.title = titleMap[currentFilter.sendType] ?? 'allSends';
} else {
this.title = 'allSends';
}

* Retrieves the symbolic name for a DatePreset value.
*/
export function nameOfDatePreset(value: DatePreset): keyof typeof DatePreset | undefined {
return namesByDatePreset.get(value);

Choose a reason for hiding this comment

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

consider throwing an error instead of returning undefined

@djsmith85 djsmith85 removed their request for review November 14, 2025 10:57
@claude
Copy link

claude bot commented Nov 20, 2025

Claude finished @harr1424's task —— View job


Code Review Complete

Thanks for your work on refactoring these enums to const objects per ADR-0025. I've reviewed all the changes and have the following feedback:

Summary

The refactoring successfully converts Send-related and export-related enums to const objects. The core pattern is correctly implemented with proper JSDoc documentation and runtime type guards. However, there are several findings that need attention, particularly around error handling, code organization, and addressing reviewer questions.

Findings

Finding 1: Error thrown in QueryParams constructor may not be handled gracefully

  • Location: apps/browser/src/tools/popup/send-v2/add-edit/send-add-edit.component.ts:48
  • As Hinton asked: should this throw or have a graceful fallback?
  • The constructor throws an error for invalid SendType values, but there's no try-catch in the subscription at line 169
  • Recommendation: Either add error handling in the subscription or validate earlier in the routing layer to prevent invalid params from reaching this component

Finding 2: DatePreset inconsistencies between files create maintenance burden

  • Locations:
    • libs/angular/src/tools/send/add-edit.component.ts:40-96
    • libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.ts:33-81
  • The DatePreset const object and utilities are duplicated across files with slight differences:
    • add-edit.component.ts includes Never: "never" (mixed types)
    • send-details.component.ts excludes "never" (numeric only)
  • As Hinton noted, this duplication should be extracted to a shared location
  • Recommendation: Extract DatePreset and utilities to a shared file (e.g., libs/common/src/tools/send/models/domain/date-preset.ts) and import from both locations

Finding 3: Unnecessary string type check in formattedDeletionDate getter

  • Location: libs/tools/send/send-ui/src/send-form/components/send-details/send-details.component.ts:190-192
  • The early return for string values appears unnecessary based on form initialization
  • The form control is initialized with DatePreset.SevenDays (numeric) and only receives DatePreset values
  • Recommendation: Remove the string check unless desktop client integration requires it (as discussed in review thread). If kept, add a comment explaining why.

Finding 4: Action and SendState const objects are exported but only used internally

  • Locations:
    • apps/desktop/src/app/tools/send/send.component.ts:28-37 (Action - already fixed per Hinton's comment)
    • apps/browser/src/tools/popup/send-v2/send-v2.component.ts:42-50 (SendState - still exported)
  • These types are only used within their respective components
  • Recommendation: Remove export keywords for Action and SendState types since they're component-internal

Finding 5: Nested conditionals in title assignment could be simplified

  • Location: apps/browser/src/tools/popup/send-v2/send-v2.component.ts:141-145
  • Multiple reviewers (bmbitwarden, Hinton) suggested using a Record/switch for better type safety
  • Current implementation:
    if (currentFilter?.sendType !== null) {
      this.title = this.sendTypeTitles[currentFilter.sendType] ?? "allSends";
    } else {
      this.title = "allSends";
    }
  • The sendTypeTitles Record already exists (lines 121-124), but the conditional could be cleaner
  • Recommendation: Simplify to: this.title = currentFilter?.sendType != null ? (this.sendTypeTitles[currentFilter.sendType] ?? "allSends") : "allSends";

Finding 6: Getter with side effects needs resolution

  • Location: libs/angular/src/tools/send/add-edit.component.ts:610-614
  • FIXME comment added per audreyality's review, but issue not resolved
  • The formattedDeletionDate getter modifies form state when preset is "never"
  • Recommendation: Either refactor to eliminate side effect (preferred) or document why it's necessary and ensure it's addressed in follow-up work

Finding 7: Unused runtime type guards in send-add-edit-dialog.component

  • Location: libs/tools/send/send-ui/src/add-edit/send-add-edit-dialog.component.ts:39-47
  • SendItemDialogResult const object has accompanying spec tests but no type guard utilities
  • Per Hinton's question and subsequent discussion, these aren't actually needed for short-lived dialog results
  • Recommendation: Current implementation is correct - no change needed

Finding 8: Type assertion in send.program.ts could be typed

  • Location: apps/cli/src/tools/send/send.program.ts:311
  • let type: SendType = SendType.Text; is correctly typed
  • The variable assignment pattern is appropriate for the context
  • Recommendation: No change needed - this is actually correct

Positive Observations

  • Proper JSDoc documentation on all const objects and type aliases
  • Comprehensive test coverage for DatePreset utilities across all implementations
  • Consistent use of Object.freeze() for immutability
  • Good use of type guards (isDatePreset, asDatePreset) for runtime safety
  • SendType and EncryptedExportType follow ADR-0025 pattern correctly

Action Items Summary

  1. Required (❌):

    • Finding 1: Add error handling for QueryParams constructor
    • Finding 2: Extract duplicated DatePreset to shared location
    • Finding 6: Resolve getter side effect or document plan
  2. Recommended (⚠️):

    • Finding 3: Remove or document string type check
    • Finding 4: Remove unnecessary exports for Action/SendState
    • Finding 5: Simplify title assignment logic
  3. Informational (💭):

    • Finding 7: No runtime guards needed (confirmed correct)
    • Finding 8: Type handling is correct (confirmed correct)

Addressed Review Comments

Based on recent review comments from Hinton and your responses:

  • ✅ You've already removed exports from send.component.ts (desktop) per Hinton's feedback
  • ✅ SendItemDialogResult type guards discussion resolved - no changes needed
  • ⏳ Action confirmation still needed on whether add-edit.component.ts DatePreset should remain unmodified if file is deprecated

Please let me know if you'd like me to help implement any of these changes or if you have questions about the recommendations.

Comment on lines 41 to 58
export const DatePreset = Object.freeze({
/** One-hour duration. */
OneHour: 1,
/** One-day duration (24 hours). */
OneDay: 24,
/** Two-day duration (48 hours). */
TwoDays: 48,
/** Three-day duration (72 hours). */
ThreeDays: 72,
/** Seven-day duration (168 hours). */
SevenDays: 168,
/** Thirty-day duration (720 hours). */
ThirtyDays: 720,
/** Custom date/time, provided by the user. */
Custom: 0,
/** No expiration. */
Never: "never",
} as const);
Copy link
Member

Choose a reason for hiding this comment

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

issue: This is duplicated. Can we extract this to a single file and share it in both places. OR if we consider this file to be deprecated, not modify it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Hinton please let me know your preference here, if this file is deprecated my preference would be to not modify it.

Copy link
Member

Choose a reason for hiding this comment

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

Yea that's fine with me. The file is deprecated and will be replaced with the new component so the value of updating it probably only results in additional QA effort.

Comment on lines 28 to 39
/** An action that can be performed in the Send UI. */
export const Action = Object.freeze({
/** No action is currently active. */
None: "",
/** The user is adding a new Send. */
Add: "add",
/** The user is editing an existing Send. */
Edit: "edit",
} as const);

/** An action that can be performed in the Send UI. */
export type Action = (typeof Action)[keyof typeof Action];
Copy link
Member

Choose a reason for hiding this comment

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

question: These are internal to this file, should they be exported?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated this file to not export these.

Never = null,
}
/** A preset duration (in hours) for expiration/deletion. */
export const DatePreset = Object.freeze({
Copy link
Member

Choose a reason for hiding this comment

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

issue: This is internal to the file, should they be exported?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated this file and the related spec file.

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.

7 participants