Full Code of maybe-finance/maybe-archive for AI

main 04bf3d135bdb cached
1004 files
2.6 MB
729.4k tokens
1573 symbols
1 requests
Download .txt
Showing preview only (2,905K chars total). Download the full file or copy to clipboard to get everything.
Repository: maybe-finance/maybe-archive
Branch: main
Commit: 04bf3d135bdb
Files: 1004
Total size: 2.6 MB

Directory structure:
gitextract_0nt4pr3f/

├── .dockerignore
├── .editorconfig
├── .eslintrc.json
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature-request-or-improvement.md
│   └── workflows/
│       └── docker-publish.yml
├── .gitignore
├── .husky/
│   └── pre-commit
├── .prettierignore
├── .prettierrc
├── .storybook/
│   ├── main.js
│   └── tsconfig.json
├── .vscode/
│   ├── extensions.json
│   ├── launch.json
│   └── settings.json
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps/
│   ├── .gitkeep
│   ├── client/
│   │   ├── .babelrc.json
│   │   ├── .eslintrc.json
│   │   ├── .storybook/
│   │   │   ├── main.js
│   │   │   ├── manager.js
│   │   │   ├── preview.js
│   │   │   ├── theme.js
│   │   │   └── tsconfig.json
│   │   ├── Dockerfile
│   │   ├── components/
│   │   │   ├── APM.tsx
│   │   │   ├── Maintenance.stories.tsx
│   │   │   ├── Maintenance.tsx
│   │   │   ├── Meta.tsx
│   │   │   └── account-views/
│   │   │       ├── DefaultView.tsx
│   │   │       ├── InvestmentView.tsx
│   │   │       ├── LoanView.tsx
│   │   │       └── index.ts
│   │   ├── env.sh
│   │   ├── env.ts
│   │   ├── jest.config.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── pages/
│   │   │   ├── 404.tsx
│   │   │   ├── _app.tsx
│   │   │   ├── _document.tsx
│   │   │   ├── accounts/
│   │   │   │   ├── [accountId].tsx
│   │   │   │   └── index.tsx
│   │   │   ├── api/
│   │   │   │   ├── auth/
│   │   │   │   │   └── [...nextauth].ts
│   │   │   │   └── card.tsx
│   │   │   ├── card/
│   │   │   │   └── [id].tsx
│   │   │   ├── data-editor.tsx
│   │   │   ├── index.tsx
│   │   │   ├── login.tsx
│   │   │   ├── onboarding.tsx
│   │   │   ├── plans/
│   │   │   │   ├── [planId].tsx
│   │   │   │   ├── create.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── register.tsx
│   │   │   ├── settings.tsx
│   │   │   └── upgrade.tsx
│   │   ├── postcss.config.js
│   │   ├── public/
│   │   │   ├── .gitkeep
│   │   │   ├── __appenv.js
│   │   │   └── assets/
│   │   │       ├── browserconfig.xml
│   │   │       └── site.webmanifest
│   │   ├── stories/
│   │   │   └── 404.stories.tsx
│   │   ├── styles.css
│   │   ├── tailwind.config.js
│   │   ├── tsconfig.json
│   │   └── tsconfig.spec.json
│   ├── e2e/
│   │   ├── .eslintrc.json
│   │   ├── cypress.config.ts
│   │   ├── src/
│   │   │   ├── e2e/
│   │   │   │   ├── accounts.cy.ts
│   │   │   │   ├── auth.cy.ts
│   │   │   │   └── subscription.cy.ts
│   │   │   ├── fixtures/
│   │   │   │   └── stripe/
│   │   │   │       ├── checkoutSessionCompleted.ts
│   │   │   │       ├── customerSubscriptionCreated.ts
│   │   │   │       ├── customerSubscriptionDeleted.ts
│   │   │   │       └── index.ts
│   │   │   └── support/
│   │   │       ├── commands.ts
│   │   │       ├── e2e.ts
│   │   │       └── index.ts
│   │   └── tsconfig.json
│   ├── server/
│   │   ├── .eslintrc.json
│   │   ├── Dockerfile
│   │   ├── jest.config.ts
│   │   ├── src/
│   │   │   ├── app/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── account.integration.spec.ts
│   │   │   │   │   ├── balance-sync.integration.spec.ts
│   │   │   │   │   ├── connection.integration.spec.ts
│   │   │   │   │   ├── insights.integration.spec.ts
│   │   │   │   │   ├── net-worth.integration.spec.ts
│   │   │   │   │   ├── prisma.integration.spec.ts
│   │   │   │   │   ├── stripe.integration.spec.ts
│   │   │   │   │   ├── test-data/
│   │   │   │   │   │   ├── portfolio-1/
│   │   │   │   │   │   │   ├── holdings.csv
│   │   │   │   │   │   │   ├── securities.csv
│   │   │   │   │   │   │   └── transactions.csv
│   │   │   │   │   │   └── portfolio-2/
│   │   │   │   │   │       ├── holdings.csv
│   │   │   │   │   │       ├── securities.csv
│   │   │   │   │   │       └── transactions.csv
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── account.ts
│   │   │   │   │       ├── axios.ts
│   │   │   │   │       ├── csv.ts
│   │   │   │   │       ├── server.ts
│   │   │   │   │       └── user.ts
│   │   │   │   ├── admin/
│   │   │   │   │   └── views/
│   │   │   │   │       ├── pages/
│   │   │   │   │       │   ├── dashboard.ejs
│   │   │   │   │       │   └── index.ejs
│   │   │   │   │       └── partials/
│   │   │   │   │           └── head.ejs
│   │   │   │   ├── app.ts
│   │   │   │   ├── lib/
│   │   │   │   │   ├── ability.ts
│   │   │   │   │   ├── email.ts
│   │   │   │   │   ├── endpoint.ts
│   │   │   │   │   ├── logger.ts
│   │   │   │   │   ├── prisma.ts
│   │   │   │   │   ├── stripe.ts
│   │   │   │   │   ├── teller.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── webhook.ts
│   │   │   │   ├── middleware/
│   │   │   │   │   ├── auth-error-handler.ts
│   │   │   │   │   ├── dev-only.ts
│   │   │   │   │   ├── error-handler.ts
│   │   │   │   │   ├── identify-user.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── maintenance.ts
│   │   │   │   │   ├── superjson.ts
│   │   │   │   │   ├── validate-auth-jwt.ts
│   │   │   │   │   └── validate-teller-signature.ts
│   │   │   │   ├── routes/
│   │   │   │   │   ├── account-rollup.router.ts
│   │   │   │   │   ├── accounts.router.ts
│   │   │   │   │   ├── admin.router.ts
│   │   │   │   │   ├── connections.router.ts
│   │   │   │   │   ├── e2e.router.ts
│   │   │   │   │   ├── holdings.router.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── institutions.router.ts
│   │   │   │   │   ├── plans.router.ts
│   │   │   │   │   ├── public.router.ts
│   │   │   │   │   ├── securities.router.ts
│   │   │   │   │   ├── teller.router.ts
│   │   │   │   │   ├── tools.router.ts
│   │   │   │   │   ├── transactions.router.ts
│   │   │   │   │   ├── users.router.ts
│   │   │   │   │   ├── valuations.router.ts
│   │   │   │   │   └── webhooks.router.ts
│   │   │   │   └── trpc.ts
│   │   │   ├── assets/
│   │   │   │   ├── script.js
│   │   │   │   └── styles.css
│   │   │   ├── env.ts
│   │   │   ├── environments/
│   │   │   │   ├── environment.prod.ts
│   │   │   │   └── environment.ts
│   │   │   └── main.ts
│   │   ├── tsconfig.app.json
│   │   ├── tsconfig.json
│   │   └── tsconfig.spec.json
│   └── workers/
│       ├── .eslintrc.json
│       ├── Dockerfile
│       ├── jest.config.ts
│       ├── src/
│       │   ├── app/
│       │   │   ├── __tests__/
│       │   │   │   ├── helpers/
│       │   │   │   │   └── user.test-helper.ts
│       │   │   │   ├── queue.integration.spec.ts
│       │   │   │   ├── security-sync.integration.spec.ts
│       │   │   │   └── teller.integration.spec.ts
│       │   │   ├── lib/
│       │   │   │   ├── di.ts
│       │   │   │   ├── email.ts
│       │   │   │   ├── logger.ts
│       │   │   │   ├── prisma.ts
│       │   │   │   ├── stripe.ts
│       │   │   │   └── teller.ts
│       │   │   └── services/
│       │   │       ├── bull-queue-event-handler.ts
│       │   │       ├── index.ts
│       │   │       └── worker-error.service.ts
│       │   ├── assets/
│       │   │   └── .gitkeep
│       │   ├── env.ts
│       │   ├── environments/
│       │   │   ├── environment.prod.ts
│       │   │   └── environment.ts
│       │   ├── main.ts
│       │   └── utils.ts
│       ├── tsconfig.app.json
│       ├── tsconfig.json
│       └── tsconfig.spec.json
├── babel.config.json
├── custom-express.d.ts
├── docker-compose.test.yml
├── docker-compose.yml
├── jest.config.ts
├── jest.preset.js
├── libs/
│   ├── .gitkeep
│   ├── client/
│   │   ├── features/
│   │   │   ├── .babelrc
│   │   │   ├── .eslintrc.json
│   │   │   ├── jest.config.ts
│   │   │   ├── src/
│   │   │   │   ├── account/
│   │   │   │   │   ├── AccountMenu.tsx
│   │   │   │   │   ├── AccountsSidebar.tsx
│   │   │   │   │   ├── PageTitle.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── accounts-list/
│   │   │   │   │   ├── Account.tsx
│   │   │   │   │   ├── AccountDevTools.tsx
│   │   │   │   │   ├── AccountGroup.tsx
│   │   │   │   │   ├── AccountGroupContainer.tsx
│   │   │   │   │   ├── ConnectedAccountGroup.tsx
│   │   │   │   │   ├── DeleteConnectionDialog.tsx
│   │   │   │   │   ├── DisconnectedAccountGroup.tsx
│   │   │   │   │   ├── ManualAccountGroup.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── accounts-manager/
│   │   │   │   │   ├── AccountTypeGrid.tsx
│   │   │   │   │   ├── AccountTypeSelector.tsx
│   │   │   │   │   ├── AccountValuationFormFields.tsx
│   │   │   │   │   ├── AccountsManager.tsx
│   │   │   │   │   ├── DeleteAccount.tsx
│   │   │   │   │   ├── EditAccount.tsx
│   │   │   │   │   ├── InstitutionGrid.tsx
│   │   │   │   │   ├── InstitutionList.tsx
│   │   │   │   │   ├── asset/
│   │   │   │   │   │   ├── AddAsset.tsx
│   │   │   │   │   │   ├── AssetForm.tsx
│   │   │   │   │   │   ├── EditAsset.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── connected/
│   │   │   │   │   │   ├── ConnectedAccountForm.tsx
│   │   │   │   │   │   ├── EditConnectedAccount.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── liability/
│   │   │   │   │   │   ├── AddLiability.tsx
│   │   │   │   │   │   ├── EditLiability.tsx
│   │   │   │   │   │   ├── LiabilityForm.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── property/
│   │   │   │   │   │   ├── AddProperty.tsx
│   │   │   │   │   │   ├── EditProperty.tsx
│   │   │   │   │   │   ├── PropertyForm.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── stock/
│   │   │   │   │   │   ├── AddStock.tsx
│   │   │   │   │   │   ├── CreateStockAccount.tsx
│   │   │   │   │   │   ├── StockForm.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── vehicle/
│   │   │   │   │       ├── AddVehicle.tsx
│   │   │   │   │       ├── EditVehicle.tsx
│   │   │   │   │       ├── VehicleForm.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── data-editor/
│   │   │   │   │   ├── account/
│   │   │   │   │   │   ├── AccountEditor.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── transaction/
│   │   │   │   │       ├── TransactionEditor.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── holdings-list/
│   │   │   │   │   ├── CostBasisForm.tsx
│   │   │   │   │   ├── HoldingList.tsx
│   │   │   │   │   ├── HoldingPopout.tsx
│   │   │   │   │   ├── HoldingsTable.tsx
│   │   │   │   │   ├── SecurityPriceChart.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── insights/
│   │   │   │   │   ├── explainers/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── investments/
│   │   │   │   │   │   │   ├── AverageReturn.tsx
│   │   │   │   │   │   │   ├── Contributions.tsx
│   │   │   │   │   │   │   ├── PotentialGainLoss.tsx
│   │   │   │   │   │   │   ├── SectorAllocation.tsx
│   │   │   │   │   │   │   ├── TotalFees.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── net-worth/
│   │   │   │   │   │       ├── BadDebt.tsx
│   │   │   │   │   │       ├── GoodDebt.tsx
│   │   │   │   │   │       ├── IlliquidAssets.tsx
│   │   │   │   │   │       ├── IncomePayingDebt.tsx
│   │   │   │   │   │       ├── LiquidAssets.tsx
│   │   │   │   │   │       ├── NetWorthTrend.tsx
│   │   │   │   │   │       ├── SafetyNet.tsx
│   │   │   │   │   │       ├── TotalDebtRatio.tsx
│   │   │   │   │   │       ├── YieldingAssets.tsx
│   │   │   │   │   │       └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── insight-states.ts
│   │   │   │   ├── investment-transactions-list/
│   │   │   │   │   ├── InvestmentTransactionList.tsx
│   │   │   │   │   ├── InvestmentTransactionListItem.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── layout/
│   │   │   │   │   ├── DesktopLayout.tsx
│   │   │   │   │   ├── FullPageLayout.tsx
│   │   │   │   │   ├── MenuPopover.tsx
│   │   │   │   │   ├── MobileLayout.tsx
│   │   │   │   │   ├── NotFound.tsx
│   │   │   │   │   ├── SidebarNav.tsx
│   │   │   │   │   ├── WithOnboardingLayout.tsx
│   │   │   │   │   ├── WithSidebarLayout.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── loan-details/
│   │   │   │   │   ├── LoanCard.tsx
│   │   │   │   │   ├── LoanDetail.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── net-worth-insights/
│   │   │   │   │   ├── NetWorthInsightBadge.tsx
│   │   │   │   │   ├── NetWorthInsightCard.tsx
│   │   │   │   │   ├── NetWorthInsightDetail.tsx
│   │   │   │   │   ├── NetWorthInsightStateAxis.tsx
│   │   │   │   │   ├── NetWorthPrimaryCardGroup.tsx
│   │   │   │   │   ├── breakdown-slider/
│   │   │   │   │   │   ├── NetWorthBreakdownSlider.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── breakdown-table/
│   │   │   │   │   │   ├── BreakdownTableIcon.tsx
│   │   │   │   │   │   ├── NetWorthBreakdownTable.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── income-debt/
│   │   │   │   │   │   ├── IncomeDebtBlock.tsx
│   │   │   │   │   │   ├── IncomeDebtDialog.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── safety-net/
│   │   │   │   │       ├── SafetyNetDialog.tsx
│   │   │   │   │       ├── SafetyNetOpportunityCost.tsx
│   │   │   │   │       ├── SliderBlock.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── onboarding/
│   │   │   │   │   ├── ExampleApp.tsx
│   │   │   │   │   ├── OnboardingBackground.tsx
│   │   │   │   │   ├── OnboardingGuard.tsx
│   │   │   │   │   ├── OnboardingNavbar.tsx
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── sidebar/
│   │   │   │   │   │   ├── SidebarOnboarding.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── steps/
│   │   │   │   │       ├── Intro.tsx
│   │   │   │   │       ├── Profile.tsx
│   │   │   │   │       ├── StepProps.ts
│   │   │   │   │       ├── Welcome.tsx
│   │   │   │   │       ├── YourMaybe.tsx
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── setup/
│   │   │   │   │           ├── AddFirstAccount.tsx
│   │   │   │   │           ├── EmailVerification.tsx
│   │   │   │   │           ├── OtherAccounts.tsx
│   │   │   │   │           └── index.ts
│   │   │   │   ├── plans/
│   │   │   │   │   ├── AddPlanScenario.tsx
│   │   │   │   │   ├── NewPlanForm.tsx
│   │   │   │   │   ├── PlanContext.ts
│   │   │   │   │   ├── PlanEventCard.tsx
│   │   │   │   │   ├── PlanEventForm.tsx
│   │   │   │   │   ├── PlanEventList.tsx
│   │   │   │   │   ├── PlanEventPopout.tsx
│   │   │   │   │   ├── PlanExplainer.tsx
│   │   │   │   │   ├── PlanMenu.tsx
│   │   │   │   │   ├── PlanMilestones.tsx
│   │   │   │   │   ├── PlanParameterCard.tsx
│   │   │   │   │   ├── PlanRangeInput.tsx
│   │   │   │   │   ├── PlanRangeSelector.tsx
│   │   │   │   │   ├── RetirementMilestoneForm.tsx
│   │   │   │   │   ├── RetirementPlanChart.tsx
│   │   │   │   │   ├── icon-utils.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── transactions-list/
│   │   │   │   │   ├── ExcludeTransactionDialog.tsx
│   │   │   │   │   ├── TransactionList.tsx
│   │   │   │   │   ├── TransactionListItem.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── user-billing/
│   │   │   │   │   ├── BillingPreferences.tsx
│   │   │   │   │   ├── PlanSelector.tsx
│   │   │   │   │   ├── PremiumIcon.tsx
│   │   │   │   │   ├── SubscriberGuard.tsx
│   │   │   │   │   ├── UpgradePrompt.tsx
│   │   │   │   │   ├── UpgradeTakeover.tsx
│   │   │   │   │   ├── graphics/
│   │   │   │   │   │   ├── FeaturesGlow.tsx
│   │   │   │   │   │   ├── SideGrid.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── user-details/
│   │   │   │   │   ├── DeleteUserButton.tsx
│   │   │   │   │   ├── DeleteUserModal.tsx
│   │   │   │   │   ├── UserDetails.tsx
│   │   │   │   │   ├── UserDevTools.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── user-security/
│   │   │   │   │   ├── PasswordReset.tsx
│   │   │   │   │   ├── SecurityPreferences.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   └── valuations-list/
│   │   │   │       ├── PerformanceMetric.tsx
│   │   │   │       ├── ValuationList.tsx
│   │   │   │       ├── ValuationsDateCell.tsx
│   │   │   │       ├── ValuationsTable.tsx
│   │   │   │       ├── ValuationsTableForm.tsx
│   │   │   │       ├── index.ts
│   │   │   │       └── types.ts
│   │   │   ├── tsconfig.json
│   │   │   ├── tsconfig.lib.json
│   │   │   └── tsconfig.spec.json
│   │   └── shared/
│   │       ├── .babelrc
│   │       ├── .eslintrc.json
│   │       ├── README.md
│   │       ├── jest.config.ts
│   │       ├── src/
│   │       │   ├── api/
│   │       │   │   ├── index.ts
│   │       │   │   ├── useAccountApi.ts
│   │       │   │   ├── useAccountConnectionApi.ts
│   │       │   │   ├── useAuthUserApi.ts
│   │       │   │   ├── useHoldingApi.ts
│   │       │   │   ├── useInstitutionApi.ts
│   │       │   │   ├── usePlanApi.ts
│   │       │   │   ├── useSecurityApi.ts
│   │       │   │   ├── useTellerApi.ts
│   │       │   │   ├── useTransactionApi.ts
│   │       │   │   ├── useUserApi.ts
│   │       │   │   └── useValuationApi.ts
│   │       │   ├── components/
│   │       │   │   ├── cards/
│   │       │   │   │   ├── MaybeCard.tsx
│   │       │   │   │   ├── MaybeCardShareModal.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── charts/
│   │       │   │   │   ├── index.ts
│   │       │   │   │   └── time-series/
│   │       │   │   │       ├── AxisBottom.tsx
│   │       │   │   │       ├── AxisLeft.tsx
│   │       │   │   │       ├── BaseChart.tsx
│   │       │   │   │       ├── Chart.tsx
│   │       │   │   │       ├── DefaultTooltip.tsx
│   │       │   │   │       ├── FloatingIcon.tsx
│   │       │   │   │       ├── Line.tsx
│   │       │   │   │       ├── LineRange.tsx
│   │       │   │   │       ├── LoadingChart.tsx
│   │       │   │   │       ├── MultiColorGradient.tsx
│   │       │   │   │       ├── PlusCircleGlyph.tsx
│   │       │   │   │       ├── ZeroPointGradient.tsx
│   │       │   │   │       ├── colorScales.ts
│   │       │   │   │       ├── index.ts
│   │       │   │   │       ├── types.ts
│   │       │   │   │       ├── useSeries.ts
│   │       │   │   │       └── useTooltip.ts
│   │       │   │   ├── dialogs/
│   │       │   │   │   ├── NonUSDDialog.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── explainers/
│   │       │   │   │   ├── ExplainerExternalLink.tsx
│   │       │   │   │   ├── ExplainerInfoBlock.tsx
│   │       │   │   │   ├── ExplainerPerformanceBlock.tsx
│   │       │   │   │   ├── ExplainerSection.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── generic/
│   │       │   │   │   ├── BoxIcon.tsx
│   │       │   │   │   ├── Confetti.tsx
│   │       │   │   │   ├── InfiniteScroll.tsx
│   │       │   │   │   ├── InsightGroup.tsx
│   │       │   │   │   ├── InsightPopout.tsx
│   │       │   │   │   ├── ProfileCircle.tsx
│   │       │   │   │   ├── RelativeTime.tsx
│   │       │   │   │   ├── TakeoverBackground.tsx
│   │       │   │   │   ├── Toaster.tsx
│   │       │   │   │   ├── TrendBadge.tsx
│   │       │   │   │   ├── index.ts
│   │       │   │   │   └── small-decimals/
│   │       │   │   │       ├── SmallDecimals.test.tsx
│   │       │   │   │       ├── SmallDecimals.tsx
│   │       │   │   │       └── index.ts
│   │       │   │   ├── index.ts
│   │       │   │   ├── loaders/
│   │       │   │   │   ├── MainContentLoader.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── overlays/
│   │       │   │   │   ├── BlurredContentOverlay.tsx
│   │       │   │   │   ├── ErrorFallbackOverlay.tsx
│   │       │   │   │   ├── MainContentOverlay.tsx
│   │       │   │   │   ├── Overlay.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   └── tables/
│   │       │   │       ├── data-table/
│   │       │   │       │   ├── DataTable.tsx
│   │       │   │       │   ├── DefaultCell.tsx
│   │       │   │       │   ├── EditableBooleanCell.tsx
│   │       │   │       │   ├── EditableCell.tsx
│   │       │   │       │   ├── EditableDateCell.tsx
│   │       │   │       │   ├── EditableDropdownCell.tsx
│   │       │   │       │   ├── EditableStringCell.tsx
│   │       │   │       │   ├── index.ts
│   │       │   │       │   └── types.ts
│   │       │   │       └── index.ts
│   │       │   ├── hooks/
│   │       │   │   ├── index.ts
│   │       │   │   ├── useAccountNotifications.ts
│   │       │   │   ├── useAxiosWithAuth.ts
│   │       │   │   ├── useDebounce.ts
│   │       │   │   ├── useFrame.ts
│   │       │   │   ├── useInterval.ts
│   │       │   │   ├── useLastUpdated.ts
│   │       │   │   ├── useLocalStorage.ts
│   │       │   │   ├── useLogger.ts
│   │       │   │   ├── useModalManager.ts
│   │       │   │   ├── useProviderStatus.ts
│   │       │   │   ├── useQueryParam.ts
│   │       │   │   ├── useScreenSize.ts
│   │       │   │   └── useTeller.ts
│   │       │   ├── index.ts
│   │       │   ├── providers/
│   │       │   │   ├── AccountContextProvider.tsx
│   │       │   │   ├── AxiosProvider.tsx
│   │       │   │   ├── LayoutContextProvider.tsx
│   │       │   │   ├── LogProvider.tsx
│   │       │   │   ├── PopoutProvider.tsx
│   │       │   │   ├── QueryProvider.tsx
│   │       │   │   ├── UserAccountContextProvider.tsx
│   │       │   │   └── index.ts
│   │       │   ├── types/
│   │       │   │   ├── client-side-feature-flags.ts
│   │       │   │   ├── index.ts
│   │       │   │   └── react-types.ts
│   │       │   └── utils/
│   │       │       ├── account-utils.ts
│   │       │       ├── browser-utils.ts
│   │       │       ├── form-utils.ts
│   │       │       ├── image-loaders.ts
│   │       │       └── index.ts
│   │       ├── tsconfig.json
│   │       ├── tsconfig.lib.json
│   │       └── tsconfig.spec.json
│   ├── design-system/
│   │   ├── .babelrc
│   │   ├── .eslintrc.json
│   │   ├── .storybook/
│   │   │   ├── main.js
│   │   │   ├── manager.js
│   │   │   ├── preview.js
│   │   │   ├── theme.js
│   │   │   └── tsconfig.json
│   │   ├── README.md
│   │   ├── assets/
│   │   │   └── styles.css
│   │   ├── docs/
│   │   │   ├── Getting Started/
│   │   │   │   ├── About.stories.mdx
│   │   │   │   ├── Colors.stories.mdx
│   │   │   │   └── Typography.stories.mdx
│   │   │   └── util/
│   │   │       ├── Swatch.tsx
│   │   │       └── SwatchGroup.tsx
│   │   ├── jest.config.ts
│   │   ├── jest.setup.js
│   │   ├── package.json
│   │   ├── postcss.config.js
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   └── lib/
│   │   │       ├── AccordionRow/
│   │   │       │   ├── AccordionRow.spec.tsx
│   │   │       │   ├── AccordionRow.stories.tsx
│   │   │       │   ├── AccordionRow.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── AccordionRow.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Alert/
│   │   │       │   ├── Alert.stories.tsx
│   │   │       │   ├── Alert.tsx
│   │   │       │   └── index.ts
│   │   │       ├── Badge/
│   │   │       │   ├── Badge.spec.tsx
│   │   │       │   ├── Badge.stories.tsx
│   │   │       │   ├── Badge.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Badge.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Breadcrumb/
│   │   │       │   ├── Breadcrumb.spec.tsx
│   │   │       │   ├── Breadcrumb.stories.tsx
│   │   │       │   ├── Breadcrumb.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Breadcrumb.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Button/
│   │   │       │   ├── Button.spec.tsx
│   │   │       │   ├── Button.stories.tsx
│   │   │       │   ├── Button.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Button.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Checkbox/
│   │   │       │   ├── Checkbox.spec.tsx
│   │   │       │   ├── Checkbox.stories.tsx
│   │   │       │   ├── Checkbox.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Checkbox.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── DatePicker/
│   │   │       │   ├── DatePicker.spec.tsx
│   │   │       │   ├── DatePicker.stories.tsx
│   │   │       │   ├── DatePicker.tsx
│   │   │       │   ├── DatePickerCalendar.tsx
│   │   │       │   ├── DatePickerInput.tsx
│   │   │       │   ├── DatePickerMonth.tsx
│   │   │       │   ├── DatePickerQuickSelect.tsx
│   │   │       │   ├── DatePickerRange/
│   │   │       │   │   ├── DatePickerRange.spec.tsx
│   │   │       │   │   ├── DatePickerRange.stories.tsx
│   │   │       │   │   ├── DatePickerRange.tsx
│   │   │       │   │   ├── DatePickerRangeButton.tsx
│   │   │       │   │   ├── DatePickerRangeCalendar.tsx
│   │   │       │   │   ├── DatePickerRangeTabs.tsx
│   │   │       │   │   ├── __snapshots__/
│   │   │       │   │   │   └── DatePickerRange.spec.tsx.snap
│   │   │       │   │   └── index.ts
│   │   │       │   ├── DatePickerYear.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── DatePicker.spec.tsx.snap
│   │   │       │   ├── index.ts
│   │   │       │   ├── selectableRanges.ts
│   │   │       │   ├── utils.spec.tsx
│   │   │       │   └── utils.tsx
│   │   │       ├── Dialog/
│   │   │       │   ├── Dialog.spec.tsx
│   │   │       │   ├── Dialog.stories.tsx
│   │   │       │   ├── Dialog.tsx
│   │   │       │   ├── DialogV2.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Dialog.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── FormGroup/
│   │   │       │   ├── FormGroup.spec.tsx
│   │   │       │   ├── FormGroup.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── FormGroup.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── FractionalCircle/
│   │   │       │   ├── FractionalCircle.stories.tsx
│   │   │       │   ├── FractionalCircle.tsx
│   │   │       │   └── index.ts
│   │   │       ├── IndexTabs/
│   │   │       │   ├── IndexTabs.spec.tsx
│   │   │       │   ├── IndexTabs.stories.tsx
│   │   │       │   ├── IndexTabs.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── IndexTabs.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Listbox/
│   │   │       │   ├── Listbox.spec.tsx
│   │   │       │   ├── Listbox.stories.tsx
│   │   │       │   ├── Listbox.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Listbox.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── LoadingPlaceholder/
│   │   │       │   ├── LoadingPlaceholder.spec.tsx
│   │   │       │   ├── LoadingPlaceholder.stories.tsx
│   │   │       │   ├── LoadingPlaceholder.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── LoadingPlaceholder.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── LoadingSpinner/
│   │   │       │   ├── LoadingSpinner.spec.tsx
│   │   │       │   ├── LoadingSpinner.stories.tsx
│   │   │       │   ├── LoadingSpinner.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── LoadingSpinner.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Menu/
│   │   │       │   ├── Menu.spec.tsx
│   │   │       │   ├── Menu.stories.tsx
│   │   │       │   ├── Menu.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Menu.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Popover/
│   │   │       │   ├── Popover.spec.tsx
│   │   │       │   ├── Popover.stories.tsx
│   │   │       │   ├── Popover.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Popover.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── RTEditor/
│   │   │       │   ├── RTEditor.tsx
│   │   │       │   └── index.ts
│   │   │       ├── RadioGroup/
│   │   │       │   ├── RadioGroup.stories.tsx
│   │   │       │   ├── RadioGroup.tsx
│   │   │       │   └── index.ts
│   │   │       ├── Slider/
│   │   │       │   ├── Slider.spec.tsx
│   │   │       │   ├── Slider.stories.tsx
│   │   │       │   ├── Slider.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Slider.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Step/
│   │   │       │   ├── Step.spec.tsx
│   │   │       │   ├── Step.stories.tsx
│   │   │       │   ├── Step.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Step.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Tab/
│   │   │       │   ├── Tab.spec.tsx
│   │   │       │   ├── Tab.stories.tsx
│   │   │       │   ├── Tab.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Tab.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Takeover/
│   │   │       │   ├── Takeover.spec.tsx
│   │   │       │   ├── Takeover.stories.tsx
│   │   │       │   ├── Takeover.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Takeover.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Toast/
│   │   │       │   ├── Toast.spec.tsx
│   │   │       │   ├── Toast.stories.tsx
│   │   │       │   ├── Toast.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Toast.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Toggle/
│   │   │       │   ├── Toggle.spec.tsx
│   │   │       │   ├── Toggle.stories.tsx
│   │   │       │   ├── Toggle.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Toggle.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Tooltip/
│   │   │       │   ├── Tooltip.spec.tsx
│   │   │       │   ├── Tooltip.stories.tsx
│   │   │       │   ├── Tooltip.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Tooltip.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── TrendLine/
│   │   │       │   ├── TrendLine.stories.tsx
│   │   │       │   ├── TrendLine.tsx
│   │   │       │   ├── Trendline.spec.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Trendline.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       └── inputs/
│   │   │           ├── Input/
│   │   │           │   ├── Input.spec.tsx
│   │   │           │   ├── Input.stories.tsx
│   │   │           │   ├── Input.tsx
│   │   │           │   ├── __snapshots__/
│   │   │           │   │   └── Input.spec.tsx.snap
│   │   │           │   └── index.ts
│   │   │           ├── InputColorHint/
│   │   │           │   ├── InputColorHint.tsx
│   │   │           │   └── index.ts
│   │   │           ├── InputCurrency/
│   │   │           │   ├── InputCurrency.spec.tsx
│   │   │           │   ├── InputCurrency.stories.tsx
│   │   │           │   ├── InputCurrency.tsx
│   │   │           │   ├── __snapshots__/
│   │   │           │   │   └── InputCurrency.spec.tsx.snap
│   │   │           │   └── index.ts
│   │   │           ├── InputHint/
│   │   │           │   ├── InputHint.tsx
│   │   │           │   └── index.ts
│   │   │           ├── InputPassword/
│   │   │           │   ├── InputPassword.spec.tsx
│   │   │           │   ├── InputPassword.stories.tsx
│   │   │           │   ├── InputPassword.tsx
│   │   │           │   ├── __snapshots__/
│   │   │           │   │   └── InputPassword.spec.tsx.snap
│   │   │           │   └── index.ts
│   │   │           └── index.ts
│   │   ├── tailwind.config.js
│   │   ├── tsconfig.json
│   │   ├── tsconfig.lib.json
│   │   └── tsconfig.spec.json
│   ├── server/
│   │   ├── features/
│   │   │   ├── .babelrc
│   │   │   ├── .eslintrc.json
│   │   │   ├── README.md
│   │   │   ├── jest.config.ts
│   │   │   ├── src/
│   │   │   │   ├── account/
│   │   │   │   │   ├── account-query.service.ts
│   │   │   │   │   ├── account.processor.ts
│   │   │   │   │   ├── account.provider.ts
│   │   │   │   │   ├── account.schema.ts
│   │   │   │   │   ├── account.service.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── insight.service.ts
│   │   │   │   ├── account-balance/
│   │   │   │   │   ├── balance-sync.strategy.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── investment-transaction-balance-sync.strategy.ts
│   │   │   │   │   ├── loan-balance-sync.strategy.ts
│   │   │   │   │   ├── transaction-balance-sync.strategy.ts
│   │   │   │   │   └── valuation-balance-sync.strategy.ts
│   │   │   │   ├── account-connection/
│   │   │   │   │   ├── account-connection.processor.ts
│   │   │   │   │   ├── account-connection.provider.ts
│   │   │   │   │   ├── account-connection.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── auth-user/
│   │   │   │   │   ├── auth-user.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── email/
│   │   │   │   │   ├── email.processor.ts
│   │   │   │   │   ├── email.schema.ts
│   │   │   │   │   ├── email.service.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── providers/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── postmark.provider.ts
│   │   │   │   │       └── smtp.provider.ts
│   │   │   │   ├── holding/
│   │   │   │   │   ├── holding.schema.ts
│   │   │   │   │   ├── holding.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── institution/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── institution.provider.ts
│   │   │   │   │   └── institution.service.ts
│   │   │   │   ├── investment-transaction/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── investment-transaction.schema.ts
│   │   │   │   ├── plan/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── plan.schema.ts
│   │   │   │   │   ├── plan.service.ts
│   │   │   │   │   └── projection/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── monte-carlo.spec.ts
│   │   │   │   │       ├── monte-carlo.ts
│   │   │   │   │       ├── projection-calculator.spec.ts
│   │   │   │   │       ├── projection-calculator.ts
│   │   │   │   │       ├── projection-value.spec.ts
│   │   │   │   │       └── projection-value.ts
│   │   │   │   ├── providers/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── property/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── property.service.ts
│   │   │   │   │   ├── teller/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── teller.etl.ts
│   │   │   │   │   │   ├── teller.service.ts
│   │   │   │   │   │   └── teller.webhook.ts
│   │   │   │   │   └── vehicle/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── vehicle.service.ts
│   │   │   │   ├── security-pricing/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── security-pricing.processor.ts
│   │   │   │   │   └── security-pricing.service.ts
│   │   │   │   ├── stripe/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── stripe.webhook.ts
│   │   │   │   ├── transaction/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── transaction.schema.ts
│   │   │   │   │   └── transaction.service.ts
│   │   │   │   ├── user/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── onboarding.schema.ts
│   │   │   │   │   ├── onboarding.service.ts
│   │   │   │   │   ├── user.processor.ts
│   │   │   │   │   └── user.service.ts
│   │   │   │   └── valuation/
│   │   │   │       ├── index.ts
│   │   │   │       └── valuation.service.ts
│   │   │   ├── tsconfig.json
│   │   │   ├── tsconfig.lib.json
│   │   │   └── tsconfig.spec.json
│   │   └── shared/
│   │       ├── .babelrc
│   │       ├── .eslintrc.json
│   │       ├── README.md
│   │       ├── jest.config.ts
│   │       ├── src/
│   │       │   ├── endpoint.ts
│   │       │   ├── etl.ts
│   │       │   ├── index.ts
│   │       │   ├── logger.ts
│   │       │   ├── services/
│   │       │   │   ├── cache.service.ts
│   │       │   │   ├── crypto.service.ts
│   │       │   │   ├── index.ts
│   │       │   │   ├── market-data.service.spec.ts
│   │       │   │   ├── market-data.service.ts
│   │       │   │   ├── pg.service.ts
│   │       │   │   ├── queue/
│   │       │   │   │   ├── bull-queue.ts
│   │       │   │   │   ├── in-memory-queue.ts
│   │       │   │   │   └── index.ts
│   │       │   │   └── queue.service.ts
│   │       │   ├── sql-template-tag.ts
│   │       │   └── utils/
│   │       │       ├── db-utils.ts
│   │       │       ├── error-utils.ts
│   │       │       ├── index.ts
│   │       │       ├── server-utils.ts
│   │       │       └── teller-utils.ts
│   │       ├── tsconfig.json
│   │       ├── tsconfig.lib.json
│   │       └── tsconfig.spec.json
│   ├── shared/
│   │   ├── .babelrc
│   │   ├── .eslintrc.json
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── superjson.spec.ts
│   │   │   ├── superjson.ts
│   │   │   ├── types/
│   │   │   │   ├── account-types.ts
│   │   │   │   ├── api-types.ts
│   │   │   │   ├── email-types.ts
│   │   │   │   ├── general-types.ts
│   │   │   │   ├── holding-types.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── institution-types.ts
│   │   │   │   ├── investment-transaction-types.ts
│   │   │   │   ├── plan-types.ts
│   │   │   │   ├── security-types.ts
│   │   │   │   ├── transaction-types.ts
│   │   │   │   └── user-types.ts
│   │   │   └── utils/
│   │   │       ├── account-utils.ts
│   │   │       ├── date-utils.spec.ts
│   │   │       ├── date-utils.ts
│   │   │       ├── geo-utils.ts
│   │   │       ├── index.ts
│   │   │       ├── market-utils.ts
│   │   │       ├── number-utils.spec.ts
│   │   │       ├── number-utils.ts
│   │   │       ├── plan-utils.ts
│   │   │       ├── shared-utils.spec.ts
│   │   │       ├── shared-utils.ts
│   │   │       ├── stats-utils.spec.ts
│   │   │       ├── stats-utils.ts
│   │   │       ├── test-utils.ts
│   │   │       ├── transaction-utils.ts
│   │   │       └── user-utils.ts
│   │   ├── tsconfig.json
│   │   ├── tsconfig.lib.json
│   │   └── tsconfig.spec.json
│   └── teller-api/
│       ├── .eslintrc.json
│       ├── jest.config.ts
│       ├── src/
│       │   ├── index.ts
│       │   ├── teller-api.ts
│       │   └── types/
│       │       ├── account-balance.ts
│       │       ├── account-details.ts
│       │       ├── accounts.ts
│       │       ├── authentication.ts
│       │       ├── enrollment.ts
│       │       ├── error.ts
│       │       ├── identity.ts
│       │       ├── index.ts
│       │       ├── institutions.ts
│       │       ├── transactions.ts
│       │       └── webhooks.ts
│       ├── tsconfig.json
│       ├── tsconfig.lib.json
│       └── tsconfig.spec.json
├── nx.json
├── package.json
├── prisma/
│   ├── migrations/
│   │   ├── 20211005200319_init/
│   │   │   └── migration.sql
│   │   ├── 20211019194924_unique_constraint_on_account_balances/
│   │   │   └── migration.sql
│   │   ├── 20211019214200_default_values/
│   │   │   └── migration.sql
│   │   ├── 20211025200206_account_balance_schema_update/
│   │   │   └── migration.sql
│   │   ├── 20211026174357_default_text_type/
│   │   │   └── migration.sql
│   │   ├── 20211026175641_default_values/
│   │   │   └── migration.sql
│   │   ├── 20211102165759_account_status/
│   │   │   └── migration.sql
│   │   ├── 20211102183151_add_account_types_and_subtypes/
│   │   │   └── migration.sql
│   │   ├── 20211104155259_account_uniqueness/
│   │   │   └── migration.sql
│   │   ├── 20211105234550_posted_date_type/
│   │   │   └── migration.sql
│   │   ├── 20211109151750_account_type_seed/
│   │   │   └── migration.sql
│   │   ├── 20211110044559_manual_accounts_rename_fk/
│   │   │   └── migration.sql
│   │   ├── 20211116235652_investment_data/
│   │   │   └── migration.sql
│   │   ├── 20211117190140_add_manual_account_types/
│   │   │   └── migration.sql
│   │   ├── 20211117190719_updated_at_default/
│   │   │   └── migration.sql
│   │   ├── 20211117210112_valuation_date/
│   │   │   └── migration.sql
│   │   ├── 20211117233026_add_date_indices/
│   │   │   └── migration.sql
│   │   ├── 20211118160716_account_balance_update/
│   │   │   └── migration.sql
│   │   ├── 20211118191000_account_balance_timestamps/
│   │   │   └── migration.sql
│   │   ├── 20211118194940_account_functions/
│   │   │   └── migration.sql
│   │   ├── 20211118214727_txn_date_naming/
│   │   │   └── migration.sql
│   │   ├── 20211129155121_connection_status_codes/
│   │   │   └── migration.sql
│   │   ├── 20211130184227_new_accounts_available_flag/
│   │   │   └── migration.sql
│   │   ├── 20211201023540_account_single_table_inheritance/
│   │   │   └── migration.sql
│   │   ├── 20211203180216_security_pricing/
│   │   │   └── migration.sql
│   │   ├── 20211204053810_account_balance_hypertable/
│   │   │   └── migration.sql
│   │   ├── 20211207192726_add_valuation_generated_cols/
│   │   │   └── migration.sql
│   │   ├── 20211208162929_transaction_date/
│   │   │   └── migration.sql
│   │   ├── 20211209041710_remove_initial_txn/
│   │   │   └── migration.sql
│   │   ├── 20211209050532_update_fns/
│   │   │   └── migration.sql
│   │   ├── 20211211140103_add_institution_id_to_connection/
│   │   │   └── migration.sql
│   │   ├── 20211213211517_account_user_index/
│   │   │   └── migration.sql
│   │   ├── 20211214162659_security_pricing_source/
│   │   │   └── migration.sql
│   │   ├── 20211215195518_add_account_start_date/
│   │   │   └── migration.sql
│   │   ├── 20211230035441_account_sync_status/
│   │   │   └── migration.sql
│   │   ├── 20220106215040_add_mask_to_account/
│   │   │   └── migration.sql
│   │   ├── 20220107170334_hypertable_chunk_size_tuning/
│   │   │   └── migration.sql
│   │   ├── 20220112171128_update_fn/
│   │   │   └── migration.sql
│   │   ├── 20220121175453_account_liability_json/
│   │   │   └── migration.sql
│   │   ├── 20220124193549_add_plaid_valuation_valuation_type/
│   │   │   └── migration.sql
│   │   ├── 20220124211317_update_valuation_types_and_sources/
│   │   │   └── migration.sql
│   │   ├── 20220125211038_add_unique_constraint_to_valuations/
│   │   │   └── migration.sql
│   │   ├── 20220202184342_account_balances_gapfilled_fn/
│   │   │   └── migration.sql
│   │   ├── 20220203234737_update_fn/
│   │   │   └── migration.sql
│   │   ├── 20220214175713_narrow_transaction_category/
│   │   │   └── migration.sql
│   │   ├── 20220215201534_transaction_remove_subcategory_add_plaid_category/
│   │   │   └── migration.sql
│   │   ├── 20220215212216_add_transaction_indexes/
│   │   │   └── migration.sql
│   │   ├── 20220217040807_add_merchant_name_to_transactions/
│   │   │   └── migration.sql
│   │   ├── 20220228233043_change_money_type/
│   │   │   └── migration.sql
│   │   ├── 20220302181536_add_price_as_of_to_security_pricing/
│   │   │   └── migration.sql
│   │   ├── 20220307200633_remove_price_from_holding/
│   │   │   └── migration.sql
│   │   ├── 20220307211701_valuation_trigger/
│   │   │   └── migration.sql
│   │   ├── 20220311165323_add_shares_per_contract_to_security/
│   │   │   └── migration.sql
│   │   ├── 20220315172110_institution/
│   │   │   └── migration.sql
│   │   ├── 20220316200652_reset_plaid_derivative_prices/
│   │   │   └── migration.sql
│   │   ├── 20220317191949_reset_plaid_derivative_prices_again/
│   │   │   └── migration.sql
│   │   ├── 20220323203441_multi_provider_updates/
│   │   │   └── migration.sql
│   │   ├── 20220323212807_fix_function/
│   │   │   └── migration.sql
│   │   ├── 20220411193518_stop_generating_and_enumize_account_category/
│   │   │   └── migration.sql
│   │   ├── 20220426190758_add_url_and_logo_url_to_institution/
│   │   │   └── migration.sql
│   │   ├── 20220504231954_finicity_updates/
│   │   │   └── migration.sql
│   │   ├── 20220518005502_finicity_customer_id_uniqueness/
│   │   │   └── migration.sql
│   │   ├── 20220519192445_institution_refactor/
│   │   │   └── migration.sql
│   │   ├── 20220520161223_institution_search_algo/
│   │   │   └── migration.sql
│   │   ├── 20220606160203_add_finicity_username_to_user/
│   │   │   └── migration.sql
│   │   ├── 20220607162542_add_crisp_session_token_to_user/
│   │   │   └── migration.sql
│   │   ├── 20220608171009_add_success_rate_and_oauth_to_provider_institutions/
│   │   │   └── migration.sql
│   │   ├── 20220608190342_add_unique_constraint_to_institution/
│   │   │   └── migration.sql
│   │   ├── 20220608202739_add_success_rate_updated_to_provider_institution/
│   │   │   └── migration.sql
│   │   ├── 20220609195136_remove_success_rate_from_provider_institution/
│   │   │   └── migration.sql
│   │   ├── 20220622160129_add_finicity_error/
│   │   │   └── migration.sql
│   │   ├── 20220623171212_remove_holding_unique_constraint/
│   │   │   └── migration.sql
│   │   ├── 20220630005107_category_overrides/
│   │   │   └── migration.sql
│   │   ├── 20220701013813_merge_updates/
│   │   │   └── migration.sql
│   │   ├── 20220707195013_user_overrides/
│   │   │   └── migration.sql
│   │   ├── 20220708191740_txn_excluded_flag/
│   │   │   └── migration.sql
│   │   ├── 20220713134742_add_provider_field/
│   │   │   └── migration.sql
│   │   ├── 20220714180514_update_account_start_date_fn/
│   │   │   └── migration.sql
│   │   ├── 20220714180819_account_category_consolidation/
│   │   │   └── migration.sql
│   │   ├── 20220714181018_update_account_type_model/
│   │   │   └── migration.sql
│   │   ├── 20220715191415_add_liability_fields/
│   │   │   └── migration.sql
│   │   ├── 20220719200317_plaid_txn_category/
│   │   │   └── migration.sql
│   │   ├── 20220720191551_generated_loan_credit_fields/
│   │   │   └── migration.sql
│   │   ├── 20220725143246_map_credit_loan_data/
│   │   │   └── migration.sql
│   │   ├── 20220726003918_reset_loan_account_balances/
│   │   │   └── migration.sql
│   │   ├── 20220727145316_loan_credit_json_nullable/
│   │   │   └── migration.sql
│   │   ├── 20220727202956_loan_account_start_date/
│   │   │   └── migration.sql
│   │   ├── 20220729012630_security_fields/
│   │   │   └── migration.sql
│   │   ├── 20220729202323_txn_updates/
│   │   │   └── migration.sql
│   │   ├── 20220804180126_holdings_view/
│   │   │   └── migration.sql
│   │   ├── 20220804191558_add_excluded_to_holding/
│   │   │   └── migration.sql
│   │   ├── 20220808171116_investment_txn_fees/
│   │   │   └── migration.sql
│   │   ├── 20220808174032_update_holdings_view/
│   │   │   └── migration.sql
│   │   ├── 20220810190306_transaction_category_update/
│   │   │   └── migration.sql
│   │   ├── 20220817180833_dietz/
│   │   │   └── migration.sql
│   │   ├── 20220819151658_add_investment_transaction_category/
│   │   │   └── migration.sql
│   │   ├── 20220915200544_add_plans/
│   │   │   └── migration.sql
│   │   ├── 20220919203059_make_dob_optional/
│   │   │   └── migration.sql
│   │   ├── 20220929161359_remove_crisp_session_token/
│   │   │   └── migration.sql
│   │   ├── 20221004193621_security_brokerage_cash_flag/
│   │   │   └── migration.sql
│   │   ├── 20221007143103_dietz_div0_fix/
│   │   │   └── migration.sql
│   │   ├── 20221017145454_plan_events_milestones/
│   │   │   └── migration.sql
│   │   ├── 20221021162836_remove_dob_from_plan/
│   │   │   └── migration.sql
│   │   ├── 20221024203133_plan_event_milestone_category/
│   │   │   └── migration.sql
│   │   ├── 20221027180912_cascade_plan_milestone_deletion/
│   │   │   └── migration.sql
│   │   ├── 20221109192536_add_stripe_fields/
│   │   │   └── migration.sql
│   │   ├── 20221111192223_ata/
│   │   │   └── migration.sql
│   │   ├── 20221115201138_advisor_approval_status/
│   │   │   └── migration.sql
│   │   ├── 20221117150434_update_advisor_profile/
│   │   │   └── migration.sql
│   │   ├── 20221117213140_add_stripe_trial_reminder_sent/
│   │   │   └── migration.sql
│   │   ├── 20221121214349_add_user_goals/
│   │   │   └── migration.sql
│   │   ├── 20221129201601_conversation_advisor_unique_key/
│   │   │   └── migration.sql
│   │   ├── 20221202213727_notification_preferences/
│   │   │   └── migration.sql
│   │   ├── 20221206153642_conversation_user_required/
│   │   │   └── migration.sql
│   │   ├── 20221207235557_expiry_email_sent/
│   │   │   └── migration.sql
│   │   ├── 20221209041210_user_advisor_notes/
│   │   │   └── migration.sql
│   │   ├── 20221212164355_update_risk_data_type/
│   │   │   └── migration.sql
│   │   ├── 20221214145140_add_audit_table_and_trigger/
│   │   │   └── migration.sql
│   │   ├── 20221222200240_add_onboarding_profile_fields/
│   │   │   └── migration.sql
│   │   ├── 20230105203751_add_maybe_and_title/
│   │   │   └── migration.sql
│   │   ├── 20230105210810_add_member_number/
│   │   │   └── migration.sql
│   │   ├── 20230105221446_user_audit/
│   │   │   └── migration.sql
│   │   ├── 20230106172727_add_user_residence/
│   │   │   └── migration.sql
│   │   ├── 20230106221847_user_profile/
│   │   │   └── migration.sql
│   │   ├── 20230110173017_add_user_member_id/
│   │   │   └── migration.sql
│   │   ├── 20230112163100_add_agreements_table/
│   │   │   └── migration.sql
│   │   ├── 20230113230312_user_email_required/
│   │   │   └── migration.sql
│   │   ├── 20230117131125_update_ama_onboarding/
│   │   │   └── migration.sql
│   │   ├── 20230117150048_user_name/
│   │   │   └── migration.sql
│   │   ├── 20230117192734_update_agreement_types/
│   │   │   └── migration.sql
│   │   ├── 20230119114411_add_onboarding_steps/
│   │   │   └── migration.sql
│   │   ├── 20230123121401_separate_onboarding_flows/
│   │   │   └── migration.sql
│   │   ├── 20230123192138_user_country_state/
│   │   │   └── migration.sql
│   │   ├── 20230126230520_user_deletion/
│   │   │   └── migration.sql
│   │   ├── 20230127003359_store_link_tokens/
│   │   │   └── migration.sql
│   │   ├── 20230130161915_account_value_start_date/
│   │   │   └── migration.sql
│   │   ├── 20230207111117_user_account_linking/
│   │   │   └── migration.sql
│   │   ├── 20230207181233_add_conversation_relations/
│   │   │   └── migration.sql
│   │   ├── 20230207230108_account_balance_strategy/
│   │   │   └── migration.sql
│   │   ├── 20230210163006_add_user_trial_end/
│   │   │   └── migration.sql
│   │   ├── 20230211134603_advisor_crm/
│   │   │   └── migration.sql
│   │   ├── 20230220194746_remove_stripe_trials/
│   │   │   └── migration.sql
│   │   ├── 20230223020847_txn_view/
│   │   │   └── migration.sql
│   │   ├── 20240111031553_remove_advisor_and_related_data/
│   │   │   └── migration.sql
│   │   ├── 20240111213125_next_auth_models/
│   │   │   └── migration.sql
│   │   ├── 20240111213725_add_password_to_auth_user/
│   │   │   └── migration.sql
│   │   ├── 20240112000538_remove_agreement_code/
│   │   │   └── migration.sql
│   │   ├── 20240112001215_remove_convert_kit_usage/
│   │   │   └── migration.sql
│   │   ├── 20240112201750_remove_auth0id_from_user/
│   │   │   └── migration.sql
│   │   ├── 20240112204004_add_first_last_to_authuser/
│   │   │   └── migration.sql
│   │   ├── 20240115222631_add_fields_for_teller/
│   │   │   └── migration.sql
│   │   ├── 20240116023100_add_additional_teller_fields/
│   │   │   └── migration.sql
│   │   ├── 20240116185600_add_teller_provider/
│   │   │   └── migration.sql
│   │   ├── 20240116224800_add_enrollment_id_for_teller/
│   │   │   └── migration.sql
│   │   ├── 20240117191553_categories_for_teller/
│   │   │   └── migration.sql
│   │   ├── 20240118234302_remove_finicity_investment_transaction_categories/
│   │   │   └── migration.sql
│   │   ├── 20240118234302_remove_finicity_transaction_categories/
│   │   │   └── migration.sql
│   │   ├── 20240118234303_remove_finicity_usage/
│   │   │   └── migration.sql
│   │   ├── 20240120213022_remove_transaction_category_generation/
│   │   │   └── migration.sql
│   │   ├── 20240120215821_remove_investment_transaction_category_generation/
│   │   │   └── migration.sql
│   │   ├── 20240121003016_add_asset_class_to_security/
│   │   │   └── migration.sql
│   │   ├── 20240121011219_add_provider_name_to_security/
│   │   │   └── migration.sql
│   │   ├── 20240121013630_add_exchange_info_to_security/
│   │   │   └── migration.sql
│   │   ├── 20240121084645_create_unique_fields_for_security/
│   │   │   └── migration.sql
│   │   ├── 20240121204146_add_auth_user_role/
│   │   │   └── migration.sql
│   │   ├── 20240124090855_add_options_asset_class/
│   │   │   └── migration.sql
│   │   ├── 20240124102931_remove_plaid_usage/
│   │   │   └── migration.sql
│   │   └── migration_lock.toml
│   ├── schema.prisma
│   └── seed.ts
├── redis.Dockerfile
├── redis.conf
├── render.yaml
├── tools/
│   ├── generators/
│   │   ├── .gitkeep
│   │   ├── index.ts
│   │   └── tellerGenerator.ts
│   ├── pages/
│   │   └── projections.html
│   ├── scripts/
│   │   ├── gen-cloudfront-signing-keys.sh
│   │   ├── gen-secret.sh
│   │   ├── getAffectedApps.sh
│   │   ├── runStagingE2ETests.sh
│   │   ├── vercelBuildIgnore.js
│   │   └── wait-for-it.sh
│   ├── test-data/
│   │   ├── index.ts
│   │   └── polygon/
│   │       ├── exchanges.ts
│   │       ├── index.ts
│   │       ├── snapshots.ts
│   │       └── tickers.ts
│   └── tsconfig.tools.json
├── tsconfig.base.json
├── vercel.json
└── workspace.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
# Ignores everything except dist/ prisma/ apps/
*
!dist/
!prisma/
!package.json
!apps/client/env.sh

================================================
FILE: .editorconfig
================================================
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off
trim_trailing_whitespace = false


================================================
FILE: .eslintrc.json
================================================
{
    "root": true,
    "ignorePatterns": ["**/*", "**/*.png"],
    "plugins": ["@nrwl/nx", "eslint-plugin-json"],
    "overrides": [
        {
            "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
            "rules": {
                "@nrwl/nx/enforce-module-boundaries": [
                    "error",
                    {
                        "enforceBuildableLibDependency": true,
                        "allow": [],
                        "depConstraints": [
                            {
                                "sourceTag": "scope:shared",
                                "onlyDependOnLibsWithTags": ["scope:shared"]
                            },
                            {
                                "sourceTag": "scope:app",
                                "onlyDependOnLibsWithTags": ["*"]
                            },
                            {
                                "sourceTag": "scope:client-shared",
                                "onlyDependOnLibsWithTags": ["scope:client-shared", "scope:shared"]
                            },
                            {
                                "sourceTag": "scope:server-shared",
                                "onlyDependOnLibsWithTags": ["scope:server-shared", "scope:shared"]
                            },
                            {
                                "sourceTag": "scope:server",
                                "onlyDependOnLibsWithTags": [
                                    "scope:server",
                                    "scope:server-shared",
                                    "scope:shared"
                                ]
                            },
                            {
                                "sourceTag": "scope:client",
                                "onlyDependOnLibsWithTags": [
                                    "scope:client",
                                    "scope:client-shared",
                                    "scope:shared"
                                ]
                            }
                        ]
                    }
                ]
            }
        },
        {
            "files": ["*.ts", "*.tsx"],
            "extends": ["plugin:@nrwl/nx/typescript"],
            "rules": {
                "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
                "@typescript-eslint/no-non-null-assertion": "off",
                "@typescript-eslint/no-explicit-any": "off",
                "@typescript-eslint/ban-types": "off",
                "@typescript-eslint/ban-ts-comment": "off",
                "@typescript-eslint/consistent-type-assertions": "error",
                "@typescript-eslint/consistent-type-imports": [
                    "error",
                    { "fixStyle": "inline-type-imports" }
                ]
            }
        },
        {
            "files": ["*.js", "*.jsx"],
            "extends": ["plugin:@nrwl/nx/javascript"],
            "rules": {}
        },
        {
            "files": ["*.tsx", "*.jsx"],
            "rules": {
                "jsx-a11y/anchor-is-valid": [
                    "error",
                    {
                        "components": ["Link"],
                        "specialLink": ["hrefLeft", "hrefRight"],
                        "aspects": ["invalidHref", "preferButton"]
                    }
                ]
            }
        }
    ]
}


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**

-   OS: [e.g. iOS]
-   Browser [e.g. chrome, safari]
-   Version [e.g. 22]

**Smartphone (please complete the following information):**

-   Device: [e.g. iPhone6]
-   OS: [e.g. iOS8.1]
-   Browser [e.g. stock browser, safari]
-   Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request-or-improvement.md
================================================
---
name: Feature request or improvement
about: Suggest a new feature or improvement
title: ''
labels: ''
assignees: ''

---

**Is your request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/workflows/docker-publish.yml
================================================
name: Docker

on:
  push:
    branches: [ "main" ]
    tags: [ 'v*.*.*' ]
  pull_request:
    branches: [ "main" ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
  NODE_ENV: production

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write
    strategy:
      fail-fast: false
      matrix:
        image: ["ghcr.io/${{ github.repository }}", "ghcr.io/${{ github.repository }}-worker", "ghcr.io/${{ github.repository }}-client"]
        include:
          - image: "ghcr.io/${{ github.repository }}"
            dockerfile: "./apps/server/Dockerfile"
            nx: "server:build"
          - image: "ghcr.io/${{ github.repository }}-worker"
            dockerfile: "./apps/workers/Dockerfile"
            nx: "workers:build"
          - image: "ghcr.io/${{ github.repository }}-client"
            dockerfile: "./apps/client/Dockerfile"
            nx: "client:build"
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Install cosign
        if: github.event_name != 'pull_request'
        uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1
        with:
          cosign-release: 'v2.1.1'

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0

      - name: Log into registry ${{ env.REGISTRY }}
        if: github.event_name != 'pull_request'
        uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract Docker metadata
        id: meta
        uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
        with:
          images: ${{ matrix.image }}

      - name: Setup node
        uses: actions/setup-node@v4
        with:
          node-version: '16'

      - uses: pnpm/action-setup@v2
        name: Install pnpm
        with:
          version: 8
          run_install: false

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

      - uses: actions/cache@v3
        name: Setup pnpm cache
        with:
          path: ${{ env.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-store-

      - name: Install dependencies
        run: pnpm install --frozen-lockfile --production=false

      - name: Run nx target
        run: npx nx run ${{ matrix.nx }}
      
      - name: Build and push Docker image
        id: build-and-push
        uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
        with:
          context: .
          file: ${{ matrix.dockerfile }}
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Sign the published Docker image
        if: ${{ github.event_name != 'pull_request' }}
        env:
          TAGS: ${{ steps.meta.outputs.tags }}
          DIGEST: ${{ steps.build-and-push.outputs.digest }}
        run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}


================================================
FILE: .gitignore
================================================
# See http://help.github.com/ignore-files/ for more about ignoring files.

# compiled output
**/dist
**/tmp
**/out-tsc

# dependencies
**/node_modules

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
exceptions.log
error.log
combined.log
/tools/output

# System Files
.DS_Store
Thumbs.db

# ENV
**/.env
**/.env.local

# Next.js
.next

# nx
migrations.json

# Shouldn't happen, but backup since we have a script that generates these locally
*.pem
certs/


================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

pnpm lint-staged


================================================
FILE: .prettierignore
================================================
# Add files here to ignore them from prettier formatting
/dist
/coverage


================================================
FILE: .prettierrc
================================================
{
    "trailingComma": "es5",
    "printWidth": 100,
    "tabWidth": 4,
    "semi": false,
    "singleQuote": true
}


================================================
FILE: .storybook/main.js
================================================
module.exports = {
    stories: [],
    addons: ['@storybook/addon-essentials'],
    // uncomment the property below if you want to apply some webpack config globally
    // webpackFinal: async (config, { configType }) => {
    //   // Make whatever fine-grained changes you need that should apply to all storybook configs

    //   // Return the altered config
    //   return config;
    // },
}


================================================
FILE: .storybook/tsconfig.json
================================================
{
    "extends": "../tsconfig.base.json",
    "exclude": ["../**/*.spec.js", "../**/*.spec.ts", "../**/*.spec.tsx", "../**/*.spec.jsx"],
    "include": ["../**/*"]
}


================================================
FILE: .vscode/extensions.json
================================================
{
    "recommendations": [
        "nrwl.angular-console",
        "esbenp.prettier-vscode",
        "firsttris.vscode-jest-runner",
        "dbaeumer.vscode-eslint",
        "prisma.prisma"
    ]
}


================================================
FILE: .vscode/launch.json
================================================
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "pwa-node",
            "request": "launch",
            "name": "Jest run current file",
            "program": "${workspaceFolder}/node_modules/.bin/nx",
            "cwd": "${workspaceFolder}",
            "args": [
                "test",
                "--testPathPattern=${fileBasenameNoExtension}",
                "--runInBand",
                "--skip-nx-cache"
            ],
            "skipFiles": ["<node_internals>/**", "${workspaceFolder/node_modules/**/*}"],
            "console": "integratedTerminal",
            "internalConsoleOptions": "neverOpen",
            "env": {
                "IS_VSCODE_DEBUG": "true",
                "NX_DATABASE_URL": "postgresql://maybe:maybe@localhost:5432/maybe_local"
            }
        },
        {
            "name": "server debug",
            "type": "node",
            "request": "attach",
            "restart": false,
            "port": 9228,
            "address": "localhost",
            "localRoot": "${workspaceFolder}",
            "skipFiles": ["<node_internals>/**"],
            "remoteRoot": "/app"
        },
        {
            "name": "workers debug",
            "type": "node",
            "request": "attach",
            "restart": false,
            "port": 9227,
            "address": "localhost",
            "localRoot": "${workspaceFolder}",
            "skipFiles": ["<node_internals>/**"],
            "remoteRoot": "/app"
        }
    ]
}


================================================
FILE: .vscode/settings.json
================================================
{
    "css.customData": [".vscode/css_custom_data.json"],
    "[typescript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[typescriptreact]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[html]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "typescript.enablePromptUseWorkspaceTsdk": true,
    "typescript.tsdk": "node_modules/typescript/lib"
}


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Maybe
It means so much that you're interested in contributing to Maybe! Seriously. Thank you. The entire community benefits from these contributions!

Before submitting a new issue or PR, check if it already exists in [issues](https://github.com/maybe-finance/maybe/issues) or [PRs](https://github.com/maybe-finance/maybe/pulls) so you have an idea of where things stand.

Then, once you're ready to begin work, submit a draft PR with your high-level plan (or the full solution).

Given the speed at which we're moving on the codebase, we don't assign issues or "give" issues to anyone. 

When multiple PRs are submitted for the same issue, we take the one that most succinctly & efficiently solves a given problem and stays within the scope of work.

Priority is also generally given to previous committers as they've proven familiarity with the codebase and product.


================================================
FILE: LICENSE
================================================
                    GNU AFFERO GENERAL PUBLIC LICENSE
                       Version 3, 19 November 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

  A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

  The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

  An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU Affero General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Remote Network Interaction; Use with the GNU General Public License.

  Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.


================================================
FILE: README.md
================================================
**🚨 NOTE: This codebase is no longer being maintained. The repo we're actively working on is located at [maybe-finance/maybe](https://github.com/maybe-finance/maybe).**

---

![](https://github.com/maybe-finance/maybe/assets/35243/79d97b31-7fad-4031-9e83-5005bc1d7fd0)

# Maybe: Open-source personal finance app

<b>Get involved: [Discord](https://link.maybe.co/discord) • [Website](https://maybe.co) • [Issues](https://github.com/maybe-finance/maybe/issues)</b>

## Backstory

We spent the better part of 2021/2022 building a personal finance + wealth management app called, Maybe. Very full-featured, including an "Ask an Advisor" feature which connected users with an actual CFP/CFA to help them with their finances (all included in your subscription).

The business end of things didn't work out, and so we shut things down mid-2023.

We spent the better part of $1,000,000 building the app (employees + contractors, data providers/services, infrastructure, etc.).

We're now reviving the product as a fully open-source project. The goal is to let you run the app yourself, for free, and use it to manage your own finances and eventually offer a hosted version of the app for a small monthly fee.

## End goal

Ultimately we want to rebuild this so that you can self-host, but we also have plans to offer a hosted version for a fee. That means some decisions will be made that don't explicitly make sense for self-hosted but _do_ support the goal of us offering a for-pay hosted version.

## Features

As a personal finance + wealth management app, Maybe has a lot of features. Here's a brief overview of some of the main ones...

-   Net worth tracking
-   Financial account syncing
-   Investment benchmarking
-   Investment portfolio allocation
-   Debt insights
-   Retirement forecasting + planning
-   Investment return simulation
-   Manual account/investment tracking

And dozens upon dozens of smaller features.

## Getting started

This is the current state of building the app. We're actively working to make this process much more streamlined!

_You'll need Docker installed to run the app locally._
[Docker Desktop](https://www.docker.com/products/docker-desktop/) is an easy way to get started.

First, copy the `.env.example` file to `.env`:

```
cp .env.example .env
```

Then, create a new secret using `openssl rand -base64 32` and populate `NEXTAUTH_SECRET` in your `.env` file with it.

To enable transactional emails, you'll need to create a [Postmark](https://postmarkapp.com/) account and add your API key to your `.env` file (`NX_EMAIL_PROVIDER_API_TOKEN`) and set `NX_EMAIL_PROVIDER` to `postmark`. You can also set the from and reply-to email addresses (`NX_EMAIL_FROM_ADDRESS` and `NX_EMAIL_REPLY_TO_ADDRESS`). If you want to run the app without email, you can set `NX_EMAIL_PROVIDER_API_TOKEN` to a dummy value or leave `NX_EMAIL_PROVIDER` blank. We also support SMTP for sending emails, see information about configuring environment variables in the `.env.example` file.

Maybe uses [Teller](https://teller.io/) for connecting financial accounts. To get started with Teller, you'll need to create an account. Once you've created an account:

-   Add your Teller application id to your `.env` file (`NEXT_PUBLIC_TELLER_APP_ID`).
-   Download your authentication certificates from Teller, create a `certs` folder in the root of the project, and place your certs in that directory. You should have both a `certificate.pem` and `private_key.pem`. **NEVER** check these files into source control, the `.gitignore` file will prevent the `certs/` directory from being added, but please double-check.
-   Set your `NEXT_PUBLIC_TELLER_ENV` and `NX_TELLER_ENV` to your desired environment. The default is `sandbox` which allows for testing with mock data. The login credentials for the sandbox environment are `username` and `password`. To connect to real financial accounts, you'll need to use the `development` environment.
-   Webhooks are not implemented yet, but you can populate the `NX_TELLER_SIGNING_SECRET` with the value from your Teller account.
-   We highly recommend checking out the [Teller docs](https://teller.io/docs) for more info.

Then run the following pnpm commands:

```shell
pnpm install
pnpm run dev:services:all
pnpm prisma:migrate:dev
pnpm prisma:seed
pnpm dev
```

## Set Up Ngrok

External data providers require HTTPS/SSL webhook URLs for sending data.

To test this locally/during development, you will need to setup `ngrok`.

1. Visit [ngrok.com](https://ngrok.com/)
2. Create a free account
3. Visit [this page](https://dashboard.ngrok.com/get-started/your-authtoken) to access your auth token
4. Paste it into your `.env` file: `NGROK_AUTH_TOKEN=your_auth_token`

You should claim your free static domain to avoid needing to change the URL each time you start/stop the server.

To do so:

1. Visit the [domains](https://dashboard.ngrok.com/cloud-edge/domains) page
2. Click on Create Domain
3. Copy the domain and paste it into your `.env` file: `NGROK_DOMAIN=your_domain`

That's it! As long as you run the project locally using `docker` with `pnpm dev:services:all` you'll be good to go.

## External data

To pull market data in (for investments), you'll need a Polygon.io API key. You can get one for free [here](https://polygon.io/) and then add it to your `.env` file (`NX_POLYGON_API_KEY`). **Note:** If you're using the free "basic" plan, you'll need to manually sync stock tickers using the dev tools in the app the first time you run it. It will then be re-synced automatically every 24 hours. If you're using a paid tier, be sure to update your `.env` file with the correct tier (`NX_POLYGON_API_TIER`) and tickers and pricing will be synced automatically.

## Tech stack

-   Next.js
-   Tailwind
-   Node.js
-   Express
-   Postgres (w/ Timescale)

## Credits

The original app was built by [Zach Gollwitzer](https://twitter.com/zg_dev), [Nick Arciero](https://www.narciero.com/) and [Tim Wilson](https://twitter.com/actualTimWilson), with design work by [Justin Farrugia](https://twitter.com/justinmfarrugia).

## Copyright & license

Maybe is distributed under an [AGPLv3 license](https://github.com/maybe-finance/maybe-archive/blob/main/LICENSE). "Maybe" is a trademark of Maybe Finance, Inc.


================================================
FILE: apps/.gitkeep
================================================


================================================
FILE: apps/client/.babelrc.json
================================================
{
    "presets": ["next/babel"],
    "plugins": []
}


================================================
FILE: apps/client/.eslintrc.json
================================================
{
    "extends": [
        "plugin:@nrwl/nx/react-typescript",
        "../../.eslintrc.json",
        "next",
        "next/core-web-vitals"
    ],
    "ignorePatterns": [
        "!**/*",
        "styles.css",
        "**/*.csv",
        "**/public/*",
        "**/.next/*",
        "**/*.sh",
        "Dockerfile"
    ],
    "overrides": [
        {
            "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
            "rules": {
                "@next/next/no-img-element": "off",
                "@next/next/no-html-link-for-pages": "off"
            }
        },
        {
            "files": ["*.ts", "*.tsx"],
            "rules": {}
        },
        {
            "files": ["*.js", "*.jsx"],
            "rules": {}
        }
    ],
    "env": {
        "jest": true
    },
    "settings": {
        "next": {
            "rootDir": "apps/advisor"
        }
    }
}


================================================
FILE: apps/client/.storybook/main.js
================================================
const rootMain = require('../../../.storybook/main')

module.exports = {
    ...rootMain,
    core: { ...rootMain.core, builder: 'webpack5' },
    stories: ['../**/*.stories.@(js|jsx|ts|tsx)', '../stories/**/*.stories.@(js|jsx|ts|tsx)'],
    addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
    webpackFinal: async (config, { configType }) => {
        // apply any global webpack configs that might have been specified in .storybook/main.js
        if (rootMain.webpackFinal) {
            config = await rootMain.webpackFinal(config, { configType })
        }

        // add your own webpack tweaks if needed

        return config
    },
}


================================================
FILE: apps/client/.storybook/manager.js
================================================
import { addons } from '@storybook/addons'
import theme from './theme'

addons.setConfig({
    theme,
})


================================================
FILE: apps/client/.storybook/preview.js
================================================
import '../styles.css'

import theme from './theme'

export const parameters = {
    docs: {
        theme,
    },
}


================================================
FILE: apps/client/.storybook/theme.js
================================================
import { create } from '@storybook/theming'
import logo from '../assets/logo.svg'

export default create({
    base: 'dark',

    brandTitle: 'Maybe',
    brandUrl: 'https://maybe.co',
    brandImage: logo,

    fontBase: '"General Sans", sans-serif',

    colorPrimary: '#4361EE',
    colorSecondary: '#F12980',

    appBg: '#1C1C20',
    appContentBg: '#16161A',
})


================================================
FILE: apps/client/.storybook/tsconfig.json
================================================
{
    "extends": "../tsconfig.json",
    "compilerOptions": {
        "allowImportingTsExtensions": true
    },
    "include": ["**/*.ts", "**/*.tsx", "**/**/*.ts", "**/**/*.tsx"]
}


================================================
FILE: apps/client/Dockerfile
================================================
# ------------------------------------------
#                BUILD STAGE              
# ------------------------------------------ 
FROM node:18-alpine3.18 as builder

WORKDIR /app
COPY ./dist/apps/client ./prisma ./package.json ./
# Install dependencies
RUN npm install -g pnpm
# nrwl/nx#20079, generated lockfile is completely broken
RUN rm -f pnpm-lock.yaml
RUN pnpm install --no-frozen-lockfile --production=false

# ------------------------------------------
#                PROD STAGE               
# ------------------------------------------ 
FROM node:18-alpine3.18 as prod

COPY ./apps/client/env.sh /env.sh
RUN chmod +x /env.sh

# Used for container health checks and env handling
RUN apk add --no-cache curl gawk bash
WORKDIR /app
USER node 
COPY --from=builder --chown=node:node /app  .

ENTRYPOINT ["/env.sh"]
CMD ["npx", "next", "start"]


================================================
FILE: apps/client/components/APM.tsx
================================================
import { useEffect } from 'react'
import * as Sentry from '@sentry/react'
import { useSession } from 'next-auth/react'

export default function APM() {
    const { data: session } = useSession()

    // Identify Sentry user
    useEffect(() => {
        if (session && session.user) {
            Sentry.setUser({
                id: session.user['sub'] ?? undefined,
                email: session.user['https://maybe.co'] ?? undefined,
            })
        }
    }, [session])

    return null
}


================================================
FILE: apps/client/components/Maintenance.stories.tsx
================================================
import type { Story, Meta } from '@storybook/react'
import Maintenance from './Maintenance'
import React from 'react'

export default {
    title: 'components/Maintenance.tsx',
    component: Maintenance,
} as Meta

const Template: Story = () => {
    return (
        <>
            <Maintenance />
        </>
    )
}

export const Base = Template.bind({})


================================================
FILE: apps/client/components/Maintenance.tsx
================================================
export default function Maintenance() {
    return (
        <div className="h-screen flex flex-col items-center justify-center p-4">
            <svg
                width="117"
                height="92"
                viewBox="0 0 117 92"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
            >
                <rect x="17.719" width="30.5852" height="19.0308" rx="9.5154" fill="#4CC9F0" />
                <rect x="68.6948" width="30.5852" height="19.0308" rx="9.5154" fill="#4CC9F0" />
                <rect
                    x="44.2266"
                    y="24.4677"
                    width="28.5462"
                    height="19.0308"
                    rx="9.5154"
                    fill="#4361EE"
                />
                <rect
                    x="44.2266"
                    y="48.9364"
                    width="28.5462"
                    height="19.0308"
                    rx="9.5154"
                    fill="#7209B7"
                />
                <rect
                    x="10.2429"
                    y="48.9364"
                    width="28.5462"
                    height="19.0308"
                    rx="9.5154"
                    fill="#7209B7"
                />
                <rect
                    x="78.2104"
                    y="48.9364"
                    width="28.5462"
                    height="19.0308"
                    rx="9.5154"
                    fill="#7209B7"
                />
                <rect
                    x="44.9065"
                    y="73.4041"
                    width="27.119"
                    height="18.5959"
                    rx="9.29794"
                    fill="#F72585"
                />
                <rect
                    x="0.727783"
                    y="24.4677"
                    width="38.0616"
                    height="19.0308"
                    rx="9.5154"
                    fill="#4361EE"
                />
                <rect
                    x="78.2104"
                    y="24.4677"
                    width="38.0616"
                    height="19.0308"
                    rx="9.5154"
                    fill="#4361EE"
                />
            </svg>

            <h1 className="mb-2 mt-10 font-extrabold text-base md:text-2xl text-white">
                We&apos;ll be back soon!
            </h1>

            <p className="mb-10 text-base text-center text-gray-50 max-w-md">
                We are currently doing some site maintenance and will be back up shortly.
            </p>
        </div>
    )
}


================================================
FILE: apps/client/components/Meta.tsx
================================================
import Head from 'next/head'
import React from 'react'
import env from '../env'

export default function Meta() {
    return (
        <Head>
            {/* <!-- Primary Meta Tags --> */}
            <title>Maybe</title>
            <meta name="title" content="Maybe" />
            <meta name="description" content="Maybe is modern financial & investment planning" />

            {/* <!-- Open Graph / Facebook --> */}
            <meta property="og:type" content="website" />
            <meta property="og:url" content="https://www.maybe.co" />
            <meta property="og:title" content="Maybe" />
            <meta
                property="og:description"
                content="Maybe is modern financial & investment planning"
            />

            {/* <!-- Twitter --> */}
            <meta property="twitter:card" content="summary_large_image" />
            <meta property="twitter:url" content="https://www.maybe.co" />
            <meta property="twitter:title" content="Maybe" />
            <meta
                property="twitter:description"
                content="Maybe is modern financial & investment planning"
            />

            {/* <!-- Favicons - https://realfavicongenerator.net/favicon_checker#.YUNEifxKhhE --> */}
            <link rel="manifest" href="/assets/site.webmanifest" />

            {/* <!-- Safari --> */}
            <link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png" />
            <link rel="mask-icon" href="/assets/safari-pinned-tab.svg" color="#4361ee" />

            {/* <!-- Chrome --> */}
            <link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon-32x32.png" />
            <link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon-16x16.png" />

            <link
                href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
                rel="stylesheet"
            />
        </Head>
    )
}


================================================
FILE: apps/client/components/account-views/DefaultView.tsx
================================================
import type { ReactNode } from 'react'
import type { Account } from '@prisma/client'
import type { SharedType } from '@maybe-finance/shared'
import type { SelectableDateRange, SelectableRangeKeys } from '@maybe-finance/design-system'

import { AccountMenu, PageTitle } from '@maybe-finance/client/features'
import { TSeries } from '@maybe-finance/client/shared'
import { DatePickerRange, getRangeDescription } from '@maybe-finance/design-system'
import { NumberUtil } from '@maybe-finance/shared'
import { DateTime } from 'luxon'
import { useMemo } from 'react'

export type DefaultViewProps = {
    account?: SharedType.AccountDetail
    balances?: SharedType.AccountBalanceResponse
    dateRange: SharedType.DateRange
    onDateChange: (range: SharedType.DateRange) => void
    getContent: (accountId: Account['id']) => ReactNode
    isLoading: boolean
    isError: boolean
    selectableDateRanges?: Array<SelectableDateRange | SelectableRangeKeys>
}

export default function DefaultView({
    account,
    balances,
    dateRange,
    onDateChange,
    getContent,
    isLoading,
    isError,
    selectableDateRanges,
}: DefaultViewProps) {
    const allTimeRange = useMemo(() => {
        return {
            label: 'All',
            labelShort: 'All',
            start: balances?.minDate ?? DateTime.now().minus({ years: 2 }).toISODate(),
            end: DateTime.now().toISODate(),
        }
    }, [balances])

    return (
        <div className="space-y-5">
            <div className="flex justify-between">
                <PageTitle
                    isLoading={isLoading}
                    title={account?.name}
                    value={NumberUtil.format(balances?.today?.balance, 'currency')}
                    trend={balances?.trend}
                    trendLabel={getRangeDescription(dateRange, balances?.minDate)}
                    trendNegative={account?.classification === 'liability'}
                />
                <AccountMenu account={account} />
            </div>

            <div className="flex justify-end">
                <DatePickerRange
                    variant="tabs-custom"
                    minDate={balances?.minDate}
                    maxDate={DateTime.now().toISODate()}
                    value={dateRange}
                    onChange={onDateChange}
                    selectableRanges={
                        selectableDateRanges
                            ? [...selectableDateRanges, allTimeRange]
                            : [
                                  'last-30-days',
                                  'last-6-months',
                                  'last-365-days',
                                  'last-3-years',
                                  allTimeRange,
                              ]
                    }
                />
            </div>

            <div className="h-96">
                <TSeries.Chart
                    id="investment-chart"
                    isLoading={isLoading}
                    isError={isError}
                    dateRange={dateRange}
                    interval={balances?.series.interval}
                    data={balances?.series.data.map((v) => ({
                        date: v.date,
                        values: { balance: v.balance },
                    }))}
                    series={[
                        {
                            key: 'balances',
                            accessorFn: (d) => d.values.balance?.toNumber(),
                            negative: account?.classification === 'liability',
                        },
                    ]}
                >
                    <TSeries.Line seriesKey="balances" />
                </TSeries.Chart>
            </div>

            {account && <div>{getContent(account.id)}</div>}
        </div>
    )
}


================================================
FILE: apps/client/components/account-views/InvestmentView.tsx
================================================
import {
    type InsightCardOption,
    InsightPopout,
    usePopoutContext,
    useAccountApi,
    InsightGroup,
    TSeries,
} from '@maybe-finance/client/shared'
import {
    AccountMenu,
    Explainers,
    HoldingList,
    InvestmentTransactionList,
    PageTitle,
} from '@maybe-finance/client/features'
import {
    Checkbox,
    DatePickerRange,
    getRangeDescription,
    Listbox,
} from '@maybe-finance/design-system'
import { type SharedType, NumberUtil } from '@maybe-finance/shared'
import { DateTime } from 'luxon'
import { useCallback, useEffect, useMemo, useState } from 'react'
import {
    RiAddLine,
    RiArrowUpDownLine,
    RiCoinLine,
    RiLineChartLine,
    RiPercentLine,
    RiScalesFill,
    RiStackLine,
    RiSubtractLine,
} from 'react-icons/ri'
import type { IconType } from 'react-icons'
import classNames from 'classnames'

type Props = {
    account?: SharedType.AccountDetail
    balances?: SharedType.AccountBalanceResponse
    dateRange: SharedType.DateRange
    onDateChange: (range: SharedType.DateRange) => void
    isLoading: boolean
    isError: boolean
}

const stockInsightCards: InsightCardOption[] = [
    {
        id: 'profit-loss',
        display: 'Potential gain or loss',
        category: 'General',
        tooltip:
            'The amount you would gain or lose if you sold this entire portfolio today.  This is commonly referred to as "capital gains / losses".',
    },
    {
        id: 'avg-return',
        display: 'Average return',
        category: 'General',
        tooltip:
            'The average return you have achieved over the time period on this portfolio of holdings',
    },
    {
        id: 'net-deposits',
        display: 'Contributions',
        category: 'General',
        tooltip:
            'The total amount you have contributed to this brokerage account.  Deposits increase this number and withdrawals decrease it.',
    },
    {
        id: 'fees',
        display: 'Fees',
        category: 'Cost',
        tooltip:
            'The total brokerage and other fees you have incurred while buying and selling holdings',
    },
    {
        id: 'sector-allocation',
        display: 'Sector allocation',
        category: 'Market',
        tooltip: 'Shows how diverse your portfolio is',
    },
]

const transactionsFilters: {
    name: string
    icon: IconType
    data: { category?: SharedType.InvestmentTransactionCategory }
}[] = [
    {
        name: 'Show all',
        icon: RiStackLine,
        data: {},
    },
    {
        name: 'Buys',
        icon: RiAddLine,
        data: { category: 'buy' },
    },
    {
        name: 'Sales',
        icon: RiSubtractLine,
        data: { category: 'sell' },
    },
    {
        name: 'Dividends',
        icon: RiPercentLine,
        data: { category: 'dividend' },
    },
    {
        name: 'Transfers',
        icon: RiArrowUpDownLine,
        data: { category: 'transfer' },
    },
    {
        name: 'Fees',
        icon: RiCoinLine,
        data: { category: 'fee' },
    },
]

const returnPeriods: { key: 'ytd' | '1y' | '1m'; display: string }[] = [
    { key: 'ytd', display: 'This year' },
    { key: '1y', display: 'Past year' },
    { key: '1m', display: 'Past month' },
]

const contributionPeriods = [
    { key: 'ytd', display: 'This year' },
    { key: 'lastYear', display: 'Last year' },
]

const chartViews = [
    { key: 'value', display: 'Value', icon: RiLineChartLine },
    { key: 'return', display: 'Return', icon: RiLineChartLine },
]

type Comparison = { ticker: string; display: string; color: string }

const comparisonTickers: Comparison[] = [
    {
        ticker: 'VOO',
        display: 'S&P 500',
        color: 'teal',
    },
    {
        ticker: 'DIA',
        display: 'Dow Jones Industrial Avg',
        color: 'red',
    },
    {
        ticker: 'VONE',
        display: 'Russell 1000',
        color: 'indigo',
    },
    {
        ticker: 'QQQ',
        display: 'NASDAQ 100',
        color: 'grape',
    },
    {
        ticker: 'VT',
        display: 'Total World Stock Index',
        color: 'yellow',
    },
    {
        ticker: 'GLDM',
        display: 'Gold',
        color: 'blue',
    },
    {
        ticker: 'X:BTCUSD',
        display: 'Bitcoin',
        color: 'orange',
    },
    {
        ticker: 'X:ETHUSD',
        display: 'Ethereum',
        color: 'gray',
    },
]

export default function InvestmentView({
    account,
    balances,
    dateRange,
    onDateChange,
    isLoading,
    isError,
}: Props) {
    const [selectedComparisons, setSelectedComparisons] = useState<Comparison[]>([])
    const [chartView, setChartView] = useState(chartViews[0])
    const [showContributions, setShowContributions] = useState(false)

    const { open: openPopout } = usePopoutContext()

    const [returnPeriod, setReturnPeriod] = useState(returnPeriods[0])
    const [contributionPeriod, setContributionPeriod] = useState(contributionPeriods[0])

    const { useAccountInsights, useAccountReturns } = useAccountApi()

    const returns = useAccountReturns(
        {
            id: account?.id ?? -1,
            start: dateRange.start,
            end: dateRange.end,
            compare: selectedComparisons.map((c) => c.ticker),
        },
        {
            enabled: !!account?.id,
            keepPreviousData: true,
        }
    )

    const insights = useAccountInsights(account?.id ?? -1, { enabled: !!account?.id })

    const stocksAllocation = useMemo(() => {
        const stockPercent =
            insights.data?.portfolio?.holdingBreakdown
                .find((hb) => hb.asset_class === 'stocks')
                ?.percentage.toNumber() ?? 0

        return {
            stocks: Math.round(stockPercent * 100),
            other: Math.round(100 - stockPercent * 100),
        }
    }, [insights.data])

    const allTimeRange = useMemo(() => {
        return {
            label: 'All',
            labelShort: 'All',
            start: balances?.minDate ?? DateTime.now().minus({ years: 2 }).toISODate(),
            end: DateTime.now().toISODate(),
        }
    }, [balances])

    const returnColorAccessorFn = useCallback<
        TSeries.AccessorFn<{ rateOfReturn: SharedType.Decimal }, string>
    >((datum) => {
        return datum.values?.rateOfReturn?.lessThan(0) ? '#FF8787' : '#38D9A9' // text-red and text-teal
    }, [])

    const [transactionFilter, setTransactionFilter] = useState(transactionsFilters[0])

    // Whenever user modifies the comparisons dropdown, always go to "Returns" view
    useEffect(() => {
        if (selectedComparisons.length > 0) {
            setChartView(chartViews[1])
        }
    }, [selectedComparisons])

    return (
        <div className="space-y-5">
            <div className="flex justify-between">
                <PageTitle
                    isLoading={isLoading}
                    title={account?.name}
                    value={NumberUtil.format(balances?.today?.balance, 'currency')}
                    trend={balances?.trend}
                    trendLabel={getRangeDescription(dateRange, balances?.minDate)}
                />
                <AccountMenu account={account} />
            </div>

            <div className="flex justify-between flex-wrap gap-2">
                <div className="flex items-center flex-wrap gap-2">
                    <Listbox className="inline-block" value={chartView} onChange={setChartView}>
                        <Listbox.Button icon={chartView.icon}>{chartView.display}</Listbox.Button>
                        <Listbox.Options>
                            {chartViews.map((view) => (
                                <Listbox.Option key={view.key} value={view}>
                                    {view.display}
                                </Listbox.Option>
                            ))}
                        </Listbox.Options>
                    </Listbox>
                    <Listbox value={selectedComparisons} onChange={setSelectedComparisons} multiple>
                        <Listbox.Button icon={RiScalesFill}>
                            <span className="text-white text-base font-medium">Compare</span>
                        </Listbox.Button>
                        <Listbox.Options placement="bottom-start" className="min-w-[210px]">
                            {comparisonTickers.map((comparison) => (
                                <Listbox.Option
                                    key={comparison.ticker}
                                    value={comparison}
                                    className="my-2 whitespace-nowrap"
                                >
                                    {comparison.display}
                                </Listbox.Option>
                            ))}
                        </Listbox.Options>
                    </Listbox>
                    {chartView.key === 'value' && (
                        <div className="py-2">
                            <Checkbox
                                label="Show contribution"
                                onChange={setShowContributions}
                                checked={showContributions}
                                className="ml-1"
                            />
                        </div>
                    )}
                </div>

                <DatePickerRange
                    variant="tabs-custom"
                    minDate={balances?.minDate}
                    maxDate={DateTime.now().toISODate()}
                    value={dateRange}
                    onChange={onDateChange}
                    selectableRanges={[
                        'last-7-days',
                        'last-30-days',
                        'last-90-days',
                        'last-365-days',
                        allTimeRange,
                    ]}
                />
            </div>

            <div className="h-96">
                <TSeries.Chart<Record<string, SharedType.Decimal>>
                    id="investment-account-chart"
                    isLoading={isLoading}
                    isError={isError || returns.isError}
                    dateRange={dateRange}
                    data={{
                        balances:
                            balances?.series.data.map((d) => ({
                                date: d.date,
                                values: { balance: d.balance },
                            })) ?? [],
                        returns:
                            returns.data?.data.map((d) => ({
                                date: d.date,
                                values: { ...d.account, ...d.comparisons },
                            })) ?? [],
                    }}
                    series={[
                        {
                            key: 'portfolio-balance',
                            dataKey: 'balances',
                            accessorFn: (d) => d?.values?.balance?.toNumber(),
                            isActive: chartView.key === 'value',
                        },
                        {
                            key: 'contributions',
                            dataKey: 'returns',
                            accessorFn: (d) => d.values.contributions?.toNumber(),
                            isActive: showContributions && chartView.key === 'value',
                            color: TSeries.tailwindScale('grape'),
                        },
                        {
                            key: 'portfolio-return',
                            dataKey: 'returns',
                            accessorFn: (d) => d.values.rateOfReturn?.toNumber(),
                            isActive: chartView.key === 'return',
                            format: 'percent',
                            label: 'Portfolio return',
                            color:
                                selectedComparisons.length > 0
                                    ? TSeries.tailwindScale('cyan')
                                    : returnColorAccessorFn,
                        },
                        ...selectedComparisons.map(({ ticker, display, color }) => ({
                            key: ticker,
                            dataKey: 'returns',
                            accessorFn: (d) => {
                                return d.values?.[ticker]?.toNumber()
                            },
                            isActive: chartView.key === 'return' && selectedComparisons.length > 0,
                            label: `${display} return`,
                            format: 'percent' as SharedType.FormatString,
                            color: TSeries.tailwindScale(color),
                        })),
                    ]}
                    y1Axis={
                        <TSeries.AxisLeft
                            tickFormat={(v) =>
                                NumberUtil.format(
                                    v as number,
                                    chartView.key === 'return' ? 'percent' : 'short-currency'
                                )
                            }
                        />
                    }
                    // If showing returns graph, render a date range for the tooltip title
                    tooltipOptions={
                        chartView.key === 'return' && returns.data && returns.data.data.length > 0
                            ? {
                                  tooltipTitle: (tooltipData) =>
                                      `${DateTime.fromISO(returns.data.data[0].date).toFormat(
                                          'MMM dd, yyyy'
                                      )} - ${DateTime.fromISO(tooltipData.date).toFormat(
                                          'MMM dd, yyyy'
                                      )}`,
                              }
                            : undefined
                    }
                >
                    <TSeries.Line seriesKey="portfolio-balance" />

                    <TSeries.Line seriesKey="portfolio-return" />

                    <TSeries.Line seriesKey="contributions" strokeDasharray={4} />

                    {selectedComparisons.map((comparison) => (
                        <TSeries.Line key={comparison.ticker} seriesKey={comparison.ticker} />
                    ))}
                </TSeries.Chart>
            </div>

            {account && (
                <div>
                    <InsightGroup
                        id="investment-account-insights"
                        options={stockInsightCards}
                        initialInsights={['avg-return', 'profit-loss', 'net-deposits']}
                    >
                        <InsightGroup.Card
                            id="avg-return"
                            isLoading={insights.isLoading}
                            status="active"
                            onClick={() =>
                                openPopout(
                                    <InsightPopout>
                                        <Explainers.AverageReturn />
                                    </InsightPopout>
                                )
                            }
                            headerRight={
                                <Listbox
                                    onChange={setReturnPeriod}
                                    value={returnPeriod}
                                    onClick={(e) => e.stopPropagation()}
                                >
                                    <Listbox.Button
                                        size="small"
                                        onClick={(e) => e.stopPropagation()}
                                    >
                                        {returnPeriod.display}
                                    </Listbox.Button>

                                    <Listbox.Options>
                                        {returnPeriods.map((rp) => (
                                            <Listbox.Option key={rp.key} value={rp}>
                                                {rp.display}
                                            </Listbox.Option>
                                        ))}
                                    </Listbox.Options>
                                </Listbox>
                            }
                        >
                            {(() => {
                                const returnValues =
                                    insights.data?.portfolio?.return?.[returnPeriod.key]

                                return (
                                    <>
                                        <h3>
                                            {NumberUtil.format(
                                                returnValues?.percentage,
                                                'percent',
                                                { signDisplay: 'auto', maximumFractionDigits: 1 }
                                            )}
                                        </h3>
                                        <span className="text-gray-100 text-base">
                                            <span
                                                className={classNames(
                                                    returnValues?.direction === 'up'
                                                        ? 'text-teal'
                                                        : returnValues?.direction === 'down'
                                                        ? 'text-red'
                                                        : null
                                                )}
                                            >
                                                {NumberUtil.format(
                                                    returnValues?.amount,
                                                    'currency',
                                                    {
                                                        signDisplay: 'exceptZero',
                                                    }
                                                )}
                                            </span>{' '}
                                            {returnPeriod.display.toLowerCase()}
                                        </span>
                                    </>
                                )
                            })()}
                        </InsightGroup.Card>

                        <InsightGroup.Card
                            id="profit-loss"
                            isLoading={false}
                            status="active"
                            onClick={() =>
                                openPopout(
                                    <InsightPopout>
                                        <Explainers.PotentialGainLoss />
                                    </InsightPopout>
                                )
                            }
                        >
                            <h3>
                                {NumberUtil.format(
                                    insights.data?.portfolio?.pnl?.amount,
                                    'currency',
                                    { signDisplay: 'exceptZero' }
                                )}
                            </h3>
                            <span className="text-base text-gray-100">as of today</span>
                        </InsightGroup.Card>

                        <InsightGroup.Card
                            id="net-deposits"
                            isLoading={false}
                            status="active"
                            onClick={() =>
                                openPopout(
                                    <InsightPopout>
                                        <Explainers.Contributions />
                                    </InsightPopout>
                                )
                            }
                            headerRight={
                                <Listbox
                                    onChange={setContributionPeriod}
                                    value={contributionPeriod}
                                    onClick={(e) => e.stopPropagation()}
                                >
                                    <Listbox.Button
                                        size="small"
                                        onClick={(e) => e.stopPropagation()}
                                    >
                                        {contributionPeriod.display}
                                    </Listbox.Button>

                                    <Listbox.Options>
                                        {contributionPeriods.map((cp) => (
                                            <Listbox.Option key={cp.key} value={cp}>
                                                {cp.display}
                                            </Listbox.Option>
                                        ))}
                                    </Listbox.Options>
                                </Listbox>
                            }
                        >
                            <h3>
                                {NumberUtil.format(
                                    insights?.data?.portfolio?.contributions[contributionPeriod.key]
                                        .amount,
                                    'currency',
                                    { signDisplay: 'exceptZero' }
                                )}
                            </h3>
                            <span className="text-gray-100 text-base">Average:</span>
                            <span className="text-gray-25 ml-1 text-base">
                                {NumberUtil.format(
                                    insights?.data?.portfolio?.contributions[contributionPeriod.key]
                                        .monthlyAvg,
                                    'short-currency',
                                    { signDisplay: 'exceptZero' }
                                )}
                                /mo
                            </span>
                        </InsightGroup.Card>

                        <InsightGroup.Card
                            id="fees"
                            isLoading={false}
                            status="active"
                            onClick={() =>
                                openPopout(
                                    <InsightPopout>
                                        <Explainers.TotalFees />
                                    </InsightPopout>
                                )
                            }
                        >
                            <h3>
                                {NumberUtil.format(insights.data?.portfolio?.fees, 'currency', {
                                    signDisplay: 'auto',
                                })}
                            </h3>
                            <span className="text-base text-gray-100">all time</span>
                        </InsightGroup.Card>

                        <InsightGroup.Card
                            id="sector-allocation"
                            isLoading={false}
                            status={'active'}
                            onClick={() =>
                                openPopout(
                                    <InsightPopout>
                                        <Explainers.SectorAllocation />
                                    </InsightPopout>
                                )
                            }
                        >
                            <h3>
                                {stocksAllocation.stocks}/{stocksAllocation.other} split
                            </h3>
                            <span className="text-base text-gray-100">
                                {stocksAllocation.stocks}% in stocks and {stocksAllocation.other}%
                                in other
                            </span>
                        </InsightGroup.Card>
                    </InsightGroup>

                    <h5 className="uppercase mb-5">Holdings</h5>
                    <HoldingList accountId={account.id} />

                    <div className="flex items-center justify-between mt-2 mb-4">
                        <h5 className="uppercase mt-2 mb-4">Transactions</h5>
                        <Listbox value={transactionFilter} onChange={setTransactionFilter}>
                            <Listbox.Button icon={transactionFilter.icon}>
                                {transactionFilter.name}
                            </Listbox.Button>
                            <Listbox.Options placement="bottom-end">
                                {transactionsFilters.map((filter) => (
                                    <Listbox.Option
                                        key={filter.name}
                                        value={filter}
                                        icon={filter.icon}
                                    >
                                        {filter.name}
                                    </Listbox.Option>
                                ))}
                            </Listbox.Options>
                        </Listbox>
                    </div>
                    <InvestmentTransactionList
                        accountId={account.id}
                        filter={transactionFilter.data}
                    />
                </div>
            )}
        </div>
    )
}


================================================
FILE: apps/client/components/account-views/LoanView.tsx
================================================
import type { SharedType } from '@maybe-finance/shared'
import { AccountMenu, LoanDetail, PageTitle, TransactionList } from '@maybe-finance/client/features'
import { TSeries, useAccountContext } from '@maybe-finance/client/shared'
import { Button, DatePickerRange, getRangeDescription } from '@maybe-finance/design-system'
import { NumberUtil } from '@maybe-finance/shared'
import { DateTime } from 'luxon'
import { useMemo, useEffect, useState } from 'react'

export type LoanViewProps = {
    account?: SharedType.AccountDetail
    balances?: SharedType.AccountBalanceResponse
    dateRange: SharedType.DateRange
    onDateChange: (range: SharedType.DateRange) => void
    isLoading: boolean
    isError: boolean
}

export default function LoanView({
    account,
    balances,
    dateRange,
    onDateChange,
    isLoading,
    isError,
}: LoanViewProps) {
    const { editAccount } = useAccountContext()

    const [showOverlay, setShowOverlay] = useState(false)

    const allTimeRange = useMemo(() => {
        return {
            label: 'All',
            labelShort: 'All',
            start: balances?.minDate ?? DateTime.now().minus({ years: 2 }).toISODate(),
            end: DateTime.now().toISODate(),
        }
    }, [balances])

    useEffect(() => {
        const loanValid = ({ loan }: SharedType.AccountDetail) => {
            return (
                loan &&
                loan.originationDate &&
                loan.originationPrincipal &&
                loan.maturityDate &&
                loan.interestRate &&
                loan.loanDetail
            )
        }

        if (account && !loanValid(account)) {
            setShowOverlay(true)
        } else {
            setShowOverlay(false)
        }
    }, [account, editAccount])

    return (
        <div className="space-y-5">
            <div className="flex justify-between">
                <PageTitle
                    isLoading={isLoading}
                    title={account?.name}
                    value={NumberUtil.format(balances?.today?.balance, 'currency')}
                    trend={balances?.trend}
                    trendLabel={getRangeDescription(dateRange, balances?.minDate)}
                    trendNegative={account?.classification === 'liability'}
                />
                <AccountMenu account={account} />
            </div>

            <div className="flex justify-end">
                <DatePickerRange
                    variant="tabs-custom"
                    minDate={balances?.minDate}
                    maxDate={DateTime.now().toISODate()}
                    value={dateRange}
                    onChange={onDateChange}
                    selectableRanges={[
                        'last-30-days',
                        'last-6-months',
                        'last-365-days',
                        'last-3-years',
                        allTimeRange,
                    ]}
                />
            </div>

            <div className="h-96">
                <TSeries.Chart
                    id="loan-chart"
                    isLoading={isLoading}
                    isError={isError}
                    dateRange={dateRange}
                    interval={balances?.series.interval}
                    data={balances?.series.data.map((v) => ({
                        date: v.date,
                        values: { balance: v.balance },
                    }))}
                    series={[
                        {
                            key: 'balances',
                            accessorFn: (d) => d.values.balance?.toNumber(),
                            negative: true,
                        },
                    ]}
                    renderOverlay={
                        showOverlay && account
                            ? () => (
                                  <>
                                      <h3 className="mb-2">Chart unavailable</h3>
                                      <div className="max-w-screen-xs">
                                          <p className="text-base text-gray-50 max-w-[450px]">
                                              Please provide us with more details for this account
                                              so that we can build your chart with accurate values.
                                          </p>
                                      </div>
                                      <Button onClick={() => editAccount(account)} className="mt-4">
                                          Add loan terms
                                      </Button>
                                  </>
                              )
                            : undefined
                    }
                >
                    <TSeries.Line seriesKey="balances" />
                </TSeries.Chart>
            </div>

            {account && (
                <div>
                    <LoanDetail account={account} showComingSoon={!account.transactions.length} />
                    {account.transactions.length > 0 && (
                        <div className="mt-8">
                            <h5 className="uppercase mb-6">Payments</h5>
                            <TransactionList accountId={account.id} />
                        </div>
                    )}
                </div>
            )}
        </div>
    )
}


================================================
FILE: apps/client/components/account-views/index.ts
================================================
export { default as DefaultView } from './DefaultView'
export { default as LoanView } from './LoanView'


================================================
FILE: apps/client/env.sh
================================================
#!/bin/bash
# https://github.com/vercel/next.js/discussions/17641#discussioncomment-5919914

# Config
ENVSH_ENV="${ENVSH_ENV:-"./.env"}"
ENVSH_PREFIX="${ENVSH_PREFIX:-"NEXT_PUBLIC_"}"
ENVSH_PREFIX_STRIP="${ENVSH_PREFIX_STRIP:-false}"

# Can be `window.__appenv = {` or `const APPENV = {` or whatever you want
ENVSH_PREPEND="${ENVSH_PREPEND:-"window.__appenv = {"}"
ENVSH_APPEND="${ENVSH_APPEND:-"}"}"
ENVSH_OUTPUT="${ENVSH_OUTPUT:-"./public/__appenv.js"}"

[ -f "$ENVSH_ENV" ] && INPUT="$ENVSH_ENV" || INPUT=/dev/null

# Add assignment
echo "$ENVSH_PREPEND" >"$ENVSH_OUTPUT"

gawk -v PREFIX="$ENVSH_PREFIX" -v STRIP_PREFIX="$ENVSH_PREFIX_STRIP" '
BEGIN {
   OFS=": ";
   FS="=";
   PATTERN="^" PREFIX;

   for (v in ENVIRON)
      if (v ~ PATTERN)
         vars[v] = ENVIRON[v]
}

$0 ~ PATTERN {
   v = $2;

   for (i = 3; i <= NF; i++)
      v = v FS $i;

   vars[$1] = (vars[$1] ? vars[$1] : v);
}

END {
   for (v in vars) {
      val = vars[v];
      switch (val) {
         case /^true$/:
            break;

         case /^false$/:
            break;

         case /^'"'.*'"'$/:
            break;

         case /^".*"$/:
            break;

         case /^[[:digit:]]+$/:
            break;

         default:
            val = "\"" val "\"";
            break;
      }

      val = val ","

      if (STRIP_PREFIX == "true" || STRIP_PREFIX == "1")
         v = gensub(PATTERN, "", 1, v)

      print v, val;
   }
}
' "$INPUT" >>"$ENVSH_OUTPUT"

echo "$ENVSH_APPEND" >>"$ENVSH_OUTPUT"

# Accepting commands (for Docker)
exec "$@"

================================================
FILE: apps/client/env.ts
================================================
declare global {
    interface Window {
        __appenv: any
    }
}

function isBrowser() {
    return Boolean(typeof window !== 'undefined' && window.__appenv)
}

function getEnv(key: string): string | undefined {
    if (!key.length) {
        throw new Error('No env key provided')
    }

    if (isBrowser()) {
        return window.__appenv[key]
    }
}

const env = {
    NEXT_PUBLIC_API_URL:
        getEnv('NEXT_PUBLIC_API_URL') || process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3333',
    NEXT_PUBLIC_LD_CLIENT_SIDE_ID:
        getEnv('NEXT_PUBLIC_LD_CLIENT_SIDE_ID') ||
        process.env.NEXT_PUBLIC_LD_CLIENT_SIDE_ID ||
        'REPLACE_THIS',
    NEXT_PUBLIC_SENTRY_DSN: getEnv('NEXT_PUBLIC_SENTRY_DSN') || process.env.NEXT_PUBLIC_SENTRY_DSN,
    NEXT_PUBLIC_SENTRY_ENV: getEnv('NEXT_PUBLIC_SENTRY_ENV') || process.env.NEXT_PUBLIC_SENTRY_ENV,
}

export default env


================================================
FILE: apps/client/jest.config.ts
================================================
/* eslint-disable */
export default {
    displayName: 'client',
    preset: '../../jest.preset.js',
    transform: {
        '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',
        '^.+\\.[tj]sx?$': 'babel-jest',
    },
    moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
    coverageDirectory: '../../coverage/apps/client',
}


================================================
FILE: apps/client/next-env.d.ts
================================================
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.


================================================
FILE: apps/client/next.config.js
================================================
// eslint-disable-next-line @typescript-eslint/no-var-requires
const withNx = require('@nrwl/next/plugins/with-nx')
const withBundleAnalyzer = require('@next/bundle-analyzer')({
    enabled: process.env.ANALYZE === 'true',
})

/**
 * @type {import('@nrwl/next/plugins/with-nx').WithNxOptions}
 **/
const nextConfig = {
    nx: {
        // Set this to true if you would like to to use SVGR
        // See: https://github.com/gregberge/svgr
        svgr: false,
    },
    images: {
        loader: 'custom',
    },
    swcMinify: false,
}

module.exports = withBundleAnalyzer(withNx(nextConfig))


================================================
FILE: apps/client/pages/404.tsx
================================================
import { NotFoundPage } from '@maybe-finance/client/features'

export function Page404() {
    return <NotFoundPage />
}

export default Page404


================================================
FILE: apps/client/pages/_app.tsx
================================================
import { useEffect, type PropsWithChildren, type ReactElement } from 'react'
import type { AppProps } from 'next/app'
import { ErrorBoundary } from 'react-error-boundary'
import { Analytics } from '@vercel/analytics/react'
import {
    AxiosProvider,
    QueryProvider,
    ErrorFallback,
    LogProvider,
    UserAccountContextProvider,
} from '@maybe-finance/client/shared'
import { AccountsManager, OnboardingGuard } from '@maybe-finance/client/features'
import { AccountContextProvider } from '@maybe-finance/client/shared'
import * as Sentry from '@sentry/react'
import { BrowserTracing } from '@sentry/tracing'
import env from '../env'
import '../styles.css'
import { SessionProvider, useSession } from 'next-auth/react'
import Meta from '../components/Meta'
import APM from '../components/APM'
import { useRouter } from 'next/router'

Sentry.init({
    dsn: env.NEXT_PUBLIC_SENTRY_DSN,
    environment: env.NEXT_PUBLIC_SENTRY_ENV,
    integrations: [
        new BrowserTracing({
            tracingOrigins: ['localhost', new URL(env.NEXT_PUBLIC_API_URL).hostname],
        }),
    ],
    tracesSampleRate: 0.6,
})

// Providers and components only relevant to a logged-in user
const WithAuth = function ({ children }: PropsWithChildren) {
    const { data: session, status } = useSession()
    const router = useRouter()

    useEffect(() => {
        if (status === 'loading') return

        if (!session) {
            router.push('/login')
        }
    }, [session, status, router])

    if (session && status === 'authenticated') {
        return (
            <OnboardingGuard>
                <UserAccountContextProvider>
                    <AccountContextProvider>
                        {children}
                        <AccountsManager />
                    </AccountContextProvider>
                </UserAccountContextProvider>
            </OnboardingGuard>
        )
    }
    return null
}

export default function App({
    Component: Page,
    pageProps,
}: AppProps & {
    Component: AppProps['Component'] & {
        getLayout?: (component: ReactElement) => JSX.Element
        isPublic?: boolean
    }
}) {
    const getLayout = Page.getLayout ?? ((page) => page)

    return (
        <LogProvider logger={console}>
            <ErrorBoundary
                FallbackComponent={ErrorFallback}
                onError={(err) => {
                    Sentry.captureException(err)
                    console.error('React app crashed', err)
                }}
            >
                <Meta />
                <Analytics />
                <QueryProvider>
                    <SessionProvider>
                        <AxiosProvider baseUrl={env.NEXT_PUBLIC_API_URL}>
                            <>
                                <APM />
                                {Page.isPublic === true ? (
                                    getLayout(<Page {...pageProps} />)
                                ) : (
                                    <WithAuth>{getLayout(<Page {...pageProps} />)}</WithAuth>
                                )}
                            </>
                        </AxiosProvider>
                    </SessionProvider>
                </QueryProvider>
            </ErrorBoundary>
        </LogProvider>
    )
}


================================================
FILE: apps/client/pages/_document.tsx
================================================
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
    return (
        <Html lang="en">
            <Head>
                {/* <!-- NEXT_PUBLIC_ env variables --> */}
                {/* eslint-disable-next-line @next/next/no-sync-scripts */}
                <script src="/__appenv.js" />
            </Head>
            <body>
                <Main />
                <NextScript />
            </body>
        </Html>
    )
}


================================================
FILE: apps/client/pages/accounts/[accountId].tsx
================================================
import type { ReactElement } from 'react'
import type { SharedType } from '@maybe-finance/shared'

import { useEffect, useState } from 'react'
import {
    WithSidebarLayout,
    ValuationList,
    TransactionList,
    AccountSidebar,
} from '@maybe-finance/client/features'
import { useRouter } from 'next/router'
import { DateTime } from 'luxon'
import {
    MainContentOverlay,
    useAccountApi,
    useQueryParam,
    useUserAccountContext,
} from '@maybe-finance/client/shared'
import { DefaultView, LoanView } from '../../components/account-views'

import InvestmentView from '../../components/account-views/InvestmentView'

const initialRange = {
    start: DateTime.now().minus({ days: 30 }).toISODate(),
    end: DateTime.now().toISODate(),
}

export default function AccountDetailPage() {
    const router = useRouter()
    const [range, setRange] = useState<SharedType.DateRange>(initialRange)

    const { useAccount, useAccountBalances } = useAccountApi()
    const { isReady, accountSyncing } = useUserAccountContext()

    const accountId = useQueryParam('accountId', 'number')!
    const accountQuery = useAccount(accountId, { enabled: !!accountId && isReady })
    const accountBalancesQuery = useAccountBalances(
        { id: accountId, ...range },
        { enabled: !!accountId && isReady }
    )

    const isSyncing = accountSyncing(accountId)
    const isLoading = accountQuery.isLoading || accountBalancesQuery.isLoading || isSyncing
    const isError = accountQuery.isError || accountBalancesQuery.isError

    useEffect(() => {
        setRange(initialRange)
    }, [accountId])

    if (accountQuery.error || accountBalancesQuery.error) {
        return (
            <MainContentOverlay
                title="Unable to load account"
                actionText="Back home"
                onAction={() => {
                    router.push('/')
                }}
            >
                <p>
                    We&rsquo;re having some trouble loading this account. Please contact us if the
                    issue persists...
                </p>
            </MainContentOverlay>
        )
    }

    switch (accountQuery.data?.type) {
        case 'LOAN':
            return (
                <LoanView
                    account={accountQuery.data}
                    balances={accountBalancesQuery.data}
                    dateRange={range}
                    onDateChange={setRange}
                    isLoading={isLoading}
                    isError={isError}
                />
            )
        case 'INVESTMENT':
            return (
                <InvestmentView
                    account={accountQuery.data}
                    balances={accountBalancesQuery.data}
                    dateRange={range}
                    onDateChange={setRange}
                    isLoading={isLoading}
                    isError={isError}
                />
            )
        case 'CREDIT':
        case 'DEPOSITORY':
            return (
                <DefaultView
                    account={accountQuery.data}
                    balances={accountBalancesQuery.data}
                    dateRange={range}
                    onDateChange={setRange}
                    getContent={(accountId) => {
                        return (
                            <>
                                <h5 className="uppercase mb-6">Transactions</h5>
                                <TransactionList accountId={accountId} />
                            </>
                        )
                    }}
                    isLoading={isLoading}
                    isError={isError}
                    selectableDateRanges={[
                        'last-7-days',
                        'last-30-days',
                        'last-90-days',
                        'last-365-days',
                        'this-year',
                    ]}
                />
            )
        default:
            return (
                <DefaultView
                    account={accountQuery.data}
                    balances={accountBalancesQuery.data}
                    dateRange={range}
                    onDateChange={setRange}
                    getContent={(accountId: number) => {
                        return (
                            <ValuationList
                                accountId={accountId}
                                negative={accountQuery.data?.classification === 'liability'}
                            />
                        )
                    }}
                    isLoading={isLoading}
                    isError={isError}
                />
            )
    }
}

AccountDetailPage.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/accounts/index.tsx
================================================
import type { ReactElement } from 'react'
import { RiAddLine } from 'react-icons/ri'

import {
    AccountGroupContainer,
    ManualAccountGroup,
    AccountDevTools,
    ConnectedAccountGroup,
    DisconnectedAccountGroup,
    WithSidebarLayout,
    AccountSidebar,
} from '@maybe-finance/client/features'
import {
    MainContentLoader,
    MainContentOverlay,
    useAccountApi,
    useAccountContext,
} from '@maybe-finance/client/shared'
import { Button } from '@maybe-finance/design-system'
import { AccountUtil } from '@maybe-finance/shared'

export default function AccountsPage() {
    const { useAccounts } = useAccountApi()
    const { addAccount } = useAccountContext()

    const { isLoading, error, data, refetch } = useAccounts()

    if (isLoading) {
        return <MainContentLoader />
    }

    if (error || !data) {
        return (
            <MainContentOverlay
                title="Unable to load accounts"
                actionText="Try again"
                onAction={() => refetch()}
            >
                <p>
                    We&lsquo;re having some trouble loading your accounts. Please contact us{' '}
                    <a href="mailto:hello@maybe.co" className="underline text-cyan">
                        here
                    </a>{' '}
                    if the issue persists.
                </p>
            </MainContentOverlay>
        )
    }

    const { accounts, connections } = data

    const disconnected = connections.filter((c) => c.status === 'DISCONNECTED')
    const connected = connections.filter((c) => c.status !== 'DISCONNECTED')

    if (
        !isLoading &&
        disconnected.length === 0 &&
        connected.length === 0 &&
        accounts.length === 0
    ) {
        return (
            <>
                <AccountDevTools />
                <MainContentOverlay
                    title="No accounts yet"
                    actionText="Add account"
                    onAction={addAccount}
                >
                    <p>
                        You currently have no connected or manual accounts. Start by adding an
                        account.
                    </p>
                </MainContentOverlay>
            </>
        )
    }

    return (
        <div>
            <AccountDevTools />

            <div className="flex items-center justify-between">
                <h3>Accounts</h3>
                <Button onClick={addAccount} leftIcon={<RiAddLine size={20} />}>
                    Add account
                </Button>
            </div>

            <div className="mt-8 space-y-8">
                {connected.length > 0 && (
                    <AccountGroupContainer title="CONNECTED">
                        {connected.map((connection) => (
                            <ConnectedAccountGroup key={connection.id} connection={connection} />
                        ))}
                    </AccountGroupContainer>
                )}

                {accounts.length > 0 && (
                    <AccountGroupContainer title="MANUAL">
                        {AccountUtil.groupAccountsByCategory(accounts).map(
                            ({ category, subtitle, accounts }) => (
                                <ManualAccountGroup
                                    key={category}
                                    title={category}
                                    subtitle={subtitle}
                                    accounts={accounts}
                                />
                            )
                        )}
                    </AccountGroupContainer>
                )}

                {disconnected.length > 0 && (
                    <AccountGroupContainer title="DISCONNECTED">
                        {disconnected.map((connection) => (
                            <DisconnectedAccountGroup key={connection.id} connection={connection} />
                        ))}
                    </AccountGroupContainer>
                )}
            </div>
        </div>
    )
}

AccountsPage.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/api/auth/[...nextauth].ts
================================================
import NextAuth from 'next-auth'
import type { SessionStrategy, NextAuthOptions } from 'next-auth'
import CredentialsProvider from 'next-auth/providers/credentials'
import { z } from 'zod'
import { PrismaClient, AuthUserRole } from '@prisma/client'
import type { Prisma } from '@prisma/client'
import { PrismaAdapter } from '@auth/prisma-adapter'
import type { SharedType } from '@maybe-finance/shared'
import bcrypt from 'bcrypt'

let prismaInstance: PrismaClient | null = null

function getPrismaInstance() {
    if (!prismaInstance) {
        prismaInstance = new PrismaClient()
    }
    return prismaInstance
}

const prisma = getPrismaInstance()

async function createAuthUser(data: Prisma.AuthUserCreateInput) {
    const authUser = await prisma.authUser.create({ data: { ...data } })
    return authUser
}

async function getAuthUserByEmail(email: string) {
    if (!email) throw new Error('No email provided.')
    return await prisma.authUser.findUnique({
        where: { email },
    })
}

async function validateCredentials(credentials: any): Promise<z.infer<typeof authSchema>> {
    const authSchema = z.object({
        firstName: z.string().optional(),
        lastName: z.string().optional(),
        email: z.string().email({ message: 'Invalid email address.' }),
        password: z.string().min(6),
        role: z.string().default('user'),
    })

    const parsed = authSchema.safeParse(credentials)
    if (!parsed.success) {
        throw new Error(parsed.error.issues.map((issue) => issue.message).join(', '))
    }

    return parsed.data
}

async function createNewAuthUser(credentials: {
    firstName: string
    lastName: string
    email: string
    password: string
    role: string
}): Promise<SharedType.AuthUser> {
    const { firstName, lastName, email, password, role } = credentials

    if (!firstName || !lastName) {
        throw new Error('Both first name and last name are required.')
    }

    const isDevelopment = process.env.NODE_ENV === 'development'

    let userRole: AuthUserRole

    if (role === AuthUserRole.admin && isDevelopment) {
        userRole = AuthUserRole.admin
    } else if (role === AuthUserRole.ci) {
        userRole = AuthUserRole.ci
    } else {
        userRole = AuthUserRole.user
    }

    const hashedPassword = await bcrypt.hash(password, 10)
    return createAuthUser({
        firstName,
        lastName,
        name: `${firstName} ${lastName}`,
        email,
        password: hashedPassword,
        role: userRole,
    })
}

const authPrisma = {
    account: prisma.authAccount,
    user: prisma.authUser,
    session: prisma.authSession,
    verificationToken: prisma.authVerificationToken,
} as unknown as PrismaClient

export const authOptions = {
    adapter: PrismaAdapter(authPrisma),
    secret: process.env.NEXTAUTH_SECRET || 'CHANGE_ME',
    pages: {
        signIn: '/login',
    },
    session: {
        strategy: 'jwt' as SessionStrategy,
        maxAge: 1 * 24 * 60 * 60, // 1 Day
    },
    providers: [
        CredentialsProvider({
            name: 'Credentials',
            type: 'credentials',
            credentials: {
                firstName: { label: 'First name', type: 'text', placeholder: 'First name' },
                lastName: { label: 'Last name', type: 'text', placeholder: 'Last name' },
                email: { label: 'Email', type: 'email', placeholder: 'hello@maybe.co' },
                password: { label: 'Password', type: 'password' },
                role: { label: 'Admin', type: 'text' },
            },
            async authorize(credentials) {
                const { firstName, lastName, email, password, role } = await validateCredentials(
                    credentials
                )

                const existingUser = await getAuthUserByEmail(email)
                if (existingUser) {
                    const isPasswordMatch = await bcrypt.compare(password, existingUser.password!)
                    if (!isPasswordMatch) {
                        throw new Error('Email or password is invalid.')
                    }

                    return existingUser
                }

                if (!firstName || !lastName) {
                    throw new Error('Invalid credentials provided.')
                }

                return createNewAuthUser({ firstName, lastName, email, password, role })
            },
        }),
    ],
    callbacks: {
        async jwt({ token, user: authUser }: { token: any; user: any }) {
            if (authUser) {
                token.sub = authUser.id
                token['https://maybe.co/email'] = authUser.email
                token.firstName = authUser.firstName
                token.lastName = authUser.lastName
                token.name = authUser.name
                token.role = authUser.role
            }
            return token
        },
        async session({ session, token }: { session: any; token: any }) {
            session.user = token.sub
            session.sub = token.sub
            session['https://maybe.co/email'] = token['https://maybe.co/email']
            session.firstName = token.firstName
            session.lastName = token.lastName
            session.name = token.name
            session.role = token.role
            return session
        },
    },
} as NextAuthOptions

export default NextAuth(authOptions)


================================================
FILE: apps/client/pages/api/card.tsx
================================================
import { ImageResponse } from '@vercel/og'
import { DateTime } from 'luxon'
import type { NextRequest } from 'next/server'

export const config = {
    runtime: 'experimental-edge',
}

const font = fetch(
    new URL('../../public/assets/fonts/inter/Inter-Regular.ttf', import.meta.url)
).then((res) => res.arrayBuffer())

const now = DateTime.now()

export default async function handler(req: NextRequest) {
    const fontData = await font
    const { headers } = req
    const protocol = headers.get('x-forwarded-proto') || 'http'
    const host = headers.get('host')
    const baseUrl = `${protocol}://${host}`

    try {
        const { searchParams } = new URL(req.url)
        const isTwitter = searchParams.has('twitter')
        const date = searchParams.get('date')

        return new ImageResponse(
            (
                <div
                    style={{
                        fontSize: 16,
                        lineHeight: '24px',
                        color: '#868E96',
                        background: '#1c1c20',
                        width: '100%',
                        height: '100%',
                        display: 'flex',
                        textAlign: 'center',
                        alignItems: 'center',
                        justifyContent: 'center',
                        fontFamily: '"Inter"',
                        transform: `scale(${isTwitter ? 1 : 1.5})`,
                    }}
                >
                    <div
                        style={{
                            width: '406px',
                            height: '528px',
                            display: 'flex',
                            alignItems: 'center',
                            justifyContent: 'center',
                        }}
                    >
                        <img
                            alt=""
                            src={`${baseUrl}/assets/maybe-card.png`}
                            style={{ position: 'absolute', width: '100%' }}
                        />
                        <div
                            style={{
                                width: '276px',
                                height: '398px',
                                display: 'flex',
                                flexDirection: 'column',
                                justifyContent: 'flex-end',
                                alignItems: 'center',
                                padding: '24px',
                            }}
                        >
                            <span style={{ fontSize: 12, lineHeight: '16px' }}>
                                #{searchParams.get('number')?.padStart(3, '0') || '000'}
                            </span>
                            <span style={{ color: '#FFF', marginTop: '4px' }}>
                                {searchParams.get('name') || 'Maybe User'}
                            </span>
                            <span>{searchParams.get('title') || ' '}</span>
                            <span style={{ marginTop: '6px', fontSize: 12, lineHeight: '16px' }}>
                                Joined {(date ? DateTime.fromISO(date) : now).toFormat('LL.dd.yy')}
                            </span>
                        </div>
                    </div>
                </div>
            ),
            {
                width: 1200,
                height: isTwitter ? 628 : 1200,
                fonts: [
                    {
                        name: 'Inter',
                        data: fontData,
                        style: 'normal',
                    },
                ],
            }
        )
    } catch (e) {
        return new Response('Failed to generate image', { status: 500 })
    }
}


================================================
FILE: apps/client/pages/card/[id].tsx
================================================
import { MaybeCard } from '@maybe-finance/client/shared'
import { type SharedType, superjson } from '@maybe-finance/shared'
import { Button, LoadingSpinner, Tooltip } from '@maybe-finance/design-system'
import Head from 'next/head'
import { useState } from 'react'
import { RiAnticlockwise2Line } from 'react-icons/ri'
import env from '../../env'
import { NotFoundPage } from '@maybe-finance/client/features'

export default function Card({ rawData }: { rawData: any }) {
    const [isFlipped, setIsFlipped] = useState(false)

    if (!rawData.data) return <NotFoundPage />

    const data = superjson.deserialize(rawData.data) as SharedType.UserMemberCardDetails

    const title = data.name.trim()
        ? data.name
              .trim()
              .split(' ')
              .map((part, idx) => (idx > 0 ? part.substring(0, 1) : part))
              .join(' ') + "'s Maybe"
        : `Maybe Card #${data.memberNumber}`

    return (
        <>
            <Head>
                <title>{title}</title>
                <meta property="og:image" content={data.imageUrl} />
                <meta property="twitter:image" content={`${data.imageUrl}&twitter`} />
            </Head>
            <div className="fixed inset-0 flex flex-col items-center custom-gray-scroll pb-24">
                <a href="https://maybe.co" className="mt-12 md:mt-32 shrink-0">
                    <img src="/assets/maybe-full.svg" alt="Maybe" className="h-8" />
                </a>
                <div className="mt-8 w-[342px] sm:w-[406px] h-[464px] sm:h-[528px] shrink-0 flex justify-center items-center bg-gray-800 rounded-2xl overflow-hidden">
                    {data ? (
                        <MaybeCard variant="default" details={data} flipped={isFlipped} />
                    ) : (
                        <LoadingSpinner />
                    )}
                </div>
                <div className="mt-4 shrink-0">
                    <Tooltip content="Flip card" placement="bottom">
                        <div className="w-full">
                            <Button
                                type="button"
                                variant="secondary"
                                className="w-24"
                                onClick={() => setIsFlipped((flipped) => !flipped)}
                            >
                                <RiAnticlockwise2Line className="w-5 h-5 text-gray-50" />
                            </Button>
                        </div>
                    </Tooltip>
                </div>
            </div>
        </>
    )
}

export async function getServerSideProps(context) {
    const { id } = context.query

    return {
        props: {
            rawData: await fetch(`${env.NEXT_PUBLIC_API_URL}/v1/users/card/${id}`).then((data) =>
                data.json()
            ),
        },
    }
}

Card.isPublic = true


================================================
FILE: apps/client/pages/data-editor.tsx
================================================
import type { ReactElement } from 'react'
import { useMemo } from 'react'
import {
    WithSidebarLayout,
    AccountEditor,
    TransactionEditor,
    AccountSidebar,
} from '@maybe-finance/client/features'

import { Tab } from '@maybe-finance/design-system'
import { useQueryParam } from '@maybe-finance/client/shared'
import { useRouter } from 'next/router'

export default function DataEditor() {
    const currentTab = useQueryParam('tab', 'string')

    const router = useRouter()

    const selectedIndex = useMemo(() => {
        switch (currentTab) {
            case 'transactions':
                return 1
            default:
                return 0
        }
    }, [currentTab])

    return (
        <div>
            <h4>Fix my data</h4>
            <p className="text-base text-gray-100 mt-2">
                Is one of your accounts misclassified? A transaction showing the wrong category?
                Update your data below so we can show you the best insights possible.
            </p>
            <div className="mt-4">
                <Tab.Group
                    onChange={(idx) => {
                        switch (idx) {
                            case 0:
                                router.replace({ query: { tab: 'accounts' } })
                                break
                            case 1:
                                router.replace({ query: { tab: 'transactions' } })
                                break
                        }
                    }}
                    selectedIndex={selectedIndex}
                >
                    <Tab.List>
                        <Tab>Accounts</Tab>
                        <Tab>Transactions</Tab>
                    </Tab.List>
                    <Tab.Panels className="mt-4">
                        <Tab.Panel>{router.isReady && <AccountEditor />}</Tab.Panel>
                        <Tab.Panel>{router.isReady && <TransactionEditor />}</Tab.Panel>
                    </Tab.Panels>
                </Tab.Group>
            </div>
        </div>
    )
}

DataEditor.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/index.tsx
================================================
import type { ReactElement } from 'react'
import { useState } from 'react'
import {
    WithSidebarLayout,
    NetWorthInsightDetail,
    NetWorthPrimaryCardGroup,
    PageTitle,
    AccountSidebar,
} from '@maybe-finance/client/features'
import {
    MainContentOverlay,
    useAccountApi,
    useUserApi,
    useAccountContext,
    useUserAccountContext,
    TSeries,
} from '@maybe-finance/client/shared'
import { DateTime } from 'luxon'
import uniq from 'lodash/uniq'
import { NumberUtil } from '@maybe-finance/shared'
import { DatePickerRange, getRangeDescription, Listbox } from '@maybe-finance/design-system'
import { RiLineChartLine } from 'react-icons/ri'
import type { AccountCategory } from '@prisma/client'

function NoAccounts() {
    const { addAccount } = useAccountContext()

    return (
        <MainContentOverlay title="No accounts yet" actionText="Add account" onAction={addAccount}>
            <p>You currently have no connected or manual accounts. Start by adding an account.</p>
        </MainContentOverlay>
    )
}

function AllAccountsDisabled() {
    const { addAccount } = useAccountContext()

    // This user does not have any active accounts
    return (
        <MainContentOverlay
            title="No accounts enabled"
            actionText="Add account"
            onAction={addAccount}
        >
            <p>All your accounts are currently disabled. Enable one or connect a new account.</p>
        </MainContentOverlay>
    )
}

const chartViews = [
    {
        value: 'net-worth',
        display: 'Net worth value',
    },
    {
        value: 'assets-debts',
        display: 'Assets & debts',
    },
    {
        value: 'all',
        display: 'All categories',
    },
]

const categoryColors = ['blue', 'teal', 'orange', 'pink', 'grape', 'green', 'red', 'indigo', 'cyan']

export default function IndexPage() {
    const [chartView, setChartView] = useState(chartViews[0])

    const { useNetWorthSeries, useInsights } = useUserApi()
    const { useAccounts } = useAccountApi()

    const { isReady, someAccountsSyncing, noAccounts, allAccountsDisabled } =
        useUserAccountContext()

    const { dateRange, setDateRange } = useAccountContext()

    const accountsQuery = useAccounts()
    const insightsQuery = useInsights()

    const netWorthQuery = useNetWorthSeries(
        { start: dateRange.start, end: dateRange.end },
        { enabled: isReady && !noAccounts && !allAccountsDisabled }
    )

    const isLoading = someAccountsSyncing || accountsQuery.isLoading || netWorthQuery.isLoading

    if (netWorthQuery.error || accountsQuery.error) {
        return (
            <MainContentOverlay
                title="Unable to load data"
                actionText="Try again"
                onAction={() => {
                    netWorthQuery.refetch()
                }}
            >
                <p>
                    We&rsquo;re having some trouble loading your data. Please contact us if the
                    issue persists...
                </p>
            </MainContentOverlay>
        )
    }

    // This user has not created any accounts yet
    if (noAccounts) {
        return <NoAccounts />
    }

    if (allAccountsDisabled) {
        return <AllAccountsDisabled />
    }

    const seriesData = netWorthQuery.data?.series.data ?? []

    const categoriesWithData = uniq(
        seriesData.flatMap((d) =>
            Object.entries(d.categories)
                .filter(([_category, amount]) => !amount.isZero())
                .map(([category, _amount]) => category as AccountCategory)
        ) ?? []
    )

    return (
        <div className="space-y-5">
            <PageTitle
                isLoading={isLoading}
                title="Net worth"
                value={NumberUtil.format(netWorthQuery.data?.today?.netWorth, 'currency')}
                trend={netWorthQuery.data?.trend}
                trendLabel={getRangeDescription(dateRange, netWorthQuery.data?.minDate)}
            />

            <div className="flex flex-wrap justify-between items-center gap-2">
                <Listbox className="inline-block" value={chartView} onChange={setChartView}>
                    <Listbox.Button icon={RiLineChartLine}>{chartView.display}</Listbox.Button>
                    <Listbox.Options>
                        {chartViews.map((view) => (
                            <Listbox.Option key={view.value} value={view}>
                                {view.display}
                            </Listbox.Option>
                        ))}
                    </Listbox.Options>
                </Listbox>

                <DatePickerRange
                    variant="tabs-custom"
                    minDate={netWorthQuery.data && netWorthQuery.data.minDate}
                    maxDate={DateTime.now().toISODate()}
                    value={dateRange}
                    onChange={setDateRange}
                    selectableRanges={[
                        'last-30-days',
                        'last-90-days',
                        'last-365-days',
                        'this-year',
                        {
                            label: 'All time',
                            labelShort: 'All',
                            start: netWorthQuery.data
                                ? netWorthQuery.data.minDate
                                : DateTime.now().minus({ years: 3 }).toISODate(),
                            end: DateTime.now().toISODate(),
                        },
                    ]}
                />
            </div>

            <div className="h-96">
                <TSeries.Chart
                    id="net-worth-chart"
                    dateRange={dateRange}
                    interval={netWorthQuery.data?.series.interval}
                    tooltipOptions={{ renderInPortal: true }}
                    isLoading={netWorthQuery.isLoading}
                    isError={netWorthQuery.isError}
                    data={seriesData.map(({ date, ...values }) => ({ date, values }))}
                    series={[
                        {
                            key: 'net-worth',
                            label: chartView.value === 'net-worth' ? undefined : 'Net worth',
                            accessorFn: (d) => d.values?.netWorth?.toNumber(),
                            isActive: chartView.value !== 'all',
                            color: TSeries.tailwindScale('cyan'),
                        },
                        {
                            key: 'assets',
                            label: 'Assets',
                            accessorFn: (d) => d.values?.assets?.toNumber(),
                            isActive: chartView.value === 'assets-debts',
                            color: TSeries.tailwindScale('teal'),
                        },
                        {
                            key: 'liabilities',
                            label: 'Debts',
                            accessorFn: (d) => d.values?.liabilities?.toNumber(),
                            isActive: chartView.value === 'assets-debts',
                            color: TSeries.tailwindScale('red'),
                        },
                        ...categoriesWithData.map((category, idx) => ({
                            key: category,
                            accessorFn: (d) => d.values?.categories?.[category]?.toNumber(),
                            label: category,
                            isActive: chartView.value === 'all',
                            color: TSeries.tailwindScale(categoryColors[idx]),
                        })),
                    ]}
                >
                    <TSeries.Line seriesKey="assets" gradientOpacity={0.1} />
                    <TSeries.Line seriesKey="liabilities" gradientOpacity={0.1} />

                    {categoriesWithData.map((category) => (
                        <TSeries.Line key={category} seriesKey={category} gradientOpacity={0.1} />
                    ))}

                    {/* Keep at bottom so net worth line always has the highest stack index */}
                    <TSeries.Line
                        seriesKey="net-worth"
                        gradientOpacity={chartView.value === 'net-worth' ? 0.2 : 0.1}
                    />
                </TSeries.Chart>
            </div>

            <div>
                {insightsQuery.isError ? (
                    <div className="my-6 p-10 rounded-lg bg-gray-800 text-gray-100">
                        <p>Something went wrong loading your metrics. Please contact us.</p>
                    </div>
                ) : (
                    <div className="space-y-6">
                        <NetWorthPrimaryCardGroup query={insightsQuery} />
                        <NetWorthInsightDetail query={insightsQuery} />
                    </div>
                )}
            </div>
        </div>
    )
}

IndexPage.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/login.tsx
================================================
import { useState, type ReactElement } from 'react'
import { FullPageLayout } from '@maybe-finance/client/features'
import { Input, InputPassword, Button } from '@maybe-finance/design-system'
import { signIn, useSession } from 'next-auth/react'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import Script from 'next/script'
import Link from 'next/link'

export default function LoginPage() {
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [isValid, setIsValid] = useState(false)
    const [errorMessage, setErrorMessage] = useState<string | null>(null)
    const [isLoading, setIsLoading] = useState(false)

    const { data: session } = useSession()
    const router = useRouter()

    useEffect(() => {
        if (session) {
            router.push('/')
        }
    }, [session, router])

    const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault()
        setErrorMessage(null)
        setPassword('')
        setIsLoading(true)

        const response = await signIn('credentials', {
            email,
            password,
            redirect: false,
        })

        if (response && response.error) {
            setErrorMessage(response.error)
            setIsLoading(false)
            setIsValid(false)
        }
    }

    const onPasswordChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setErrorMessage(null)
        setPassword(e.target.value)
        setIsValid(e.target.value.length > 0)
    }

    return (
        <>
            <Script
                src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"
                strategy="lazyOnload"
            />
            <div className="absolute inset-0 flex flex-col items-center justify-center">
                <div className="p-px w-80 md:w-96 bg-white bg-opacity-10 card-light rounded-3xl radial-gradient-background">
                    <div className="bg-black bg-opacity-75 p-8 rounded-3xl w-full h-full items-center flex flex-col radial-gradient-background-dark">
                        <img
                            className="mb-8"
                            src="/assets/maybe-box.svg"
                            alt="Maybe Finance Logo"
                            height={120}
                            width={120}
                        />
                        <form className="space-y-4 w-full px-4" onSubmit={onSubmit}>
                            <Input
                                type="text"
                                name="email"
                                label="Email"
                                value={email}
                                onChange={(e) => setEmail(e.currentTarget.value)}
                            />

                            <InputPassword
                                autoComplete="password"
                                name="password"
                                label="Password"
                                value={password}
                                onChange={onPasswordChange}
                                showComplexityBar={false}
                            />

                            {errorMessage && password.length === 0 ? (
                                <div className="py-1 text-center text-red text-sm">
                                    {errorMessage}
                                </div>
                            ) : null}

                            <Button
                                type="submit"
                                fullWidth
                                disabled={!isValid || isLoading}
                                variant={isValid ? 'primary' : 'secondary'}
                                isLoading={isLoading}
                            >
                                Log in
                            </Button>
                            <div className="text-sm text-gray-50 text-center">
                                <div>
                                    Don&apos;t have an account?{' '}
                                    <Link
                                        className="hover:text-cyan-400 underline font-medium"
                                        href="/register"
                                    >
                                        Sign up
                                    </Link>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </>
    )
}

LoginPage.getLayout = function getLayout(page: ReactElement) {
    return <FullPageLayout>{page}</FullPageLayout>
}

LoginPage.isPublic = true


================================================
FILE: apps/client/pages/onboarding.tsx
================================================
import type { ReactElement } from 'react'
import { Transition } from '@headlessui/react'
import {
    AddFirstAccount,
    EmailVerification,
    FullPageLayout,
    Intro,
    OtherAccounts,
    Profile,
    OnboardingNavbar,
    Welcome,
    YourMaybe,
    OnboardingBackground,
    type StepProps,
} from '@maybe-finance/client/features'
import { MainContentOverlay, useQueryParam, useUserApi } from '@maybe-finance/client/shared'
import { LoadingSpinner } from '@maybe-finance/design-system'
import classNames from 'classnames'
import { useRouter } from 'next/router'

function getStepComponent(stepKey?: string): (props: StepProps) => JSX.Element {
    switch (stepKey) {
        case 'profile':
            return Profile
        case 'verifyEmail':
            return EmailVerification
        case 'firstAccount':
            return AddFirstAccount
        case 'accountSelection':
            return OtherAccounts
        case 'maybe':
            return YourMaybe
        case 'welcome':
            return Welcome
        case 'intro':
        default:
            return Intro
    }
}

export default function OnboardingPage() {
    const router = useRouter()
    const { useOnboarding, useUpdateOnboarding } = useUserApi()

    const stepParam = useQueryParam('step', 'string')

    const onboarding = useOnboarding('main', {
        onSuccess: (flow) => {
            if (!stepParam) {
                if (flow.currentStep) {
                    router.push({
                        pathname: '/onboarding',
                        query: { step: flow.currentStep.key },
                    })
                } else {
                    router.push('/')
                }
            }
        },
    })

    const updateOnboarding = useUpdateOnboarding()

    if (onboarding.isLoading || !stepParam) {
        return (
            <div className="absolute inset-0 flex items-center justify-center h-full">
                <LoadingSpinner />
            </div>
        )
    }

    if (onboarding.isError) {
        return (
            <MainContentOverlay
                title="Unable to load onboarding flow"
                actionText="Try again"
                onAction={() => window.location.reload()}
            >
                <p>Contact us if this issue persists.</p>
            </MainContentOverlay>
        )
    }

    const { steps } = onboarding.data
    const currentStep = steps.find((step) => step.key === stepParam)
    const currentStepIdx = steps.findIndex((step) => step.key === stepParam)
    const StepComponent = getStepComponent(stepParam)

    if (!currentStep) throw new Error('Could not load onboarding')

    async function prev() {
        if (currentStepIdx > 0) {
            router.push({ pathname: '/onboarding', query: { step: steps[currentStepIdx - 1].key } })
        }
    }

    async function next() {
        await updateOnboarding.mutateAsync({
            flow: 'main',
            updates: [{ key: currentStep!.key, markedComplete: true }],
        })

        if (currentStepIdx < steps.length - 1) {
            router.push({ pathname: '/onboarding', query: { step: steps[currentStepIdx + 1].key } })
        } else {
            router.push('/')
        }
    }

    return (
        <>
            <div className="fixed inset-0 z-1 overflow-hidden">
                <OnboardingBackground className="absolute -bottom-3 left-1/2 -translate-x-1/2" />
            </div>

            {currentStep.group && currentStep.group !== 'account' && (
                <OnboardingNavbar steps={steps} currentStep={currentStep} onBack={prev} />
            )}

            <Transition
                key={currentStep.key}
                className={classNames('px-6 mb-20 grow z-10')}
                appear
                show
                enter="ease-in duration-100"
                enterFrom="opacity-0 translate-y-8"
                enterTo="opacity-100 translate-y-0"
                leave="ease-in duration-100"
                leaveFrom="opacity-100 translate-y-0"
                leaveTo="opacity-0 translate-y-8"
            >
                <StepComponent title={currentStep.title} onNext={next} onPrev={prev} />
            </Transition>
        </>
    )
}

OnboardingPage.getLayout = function getLayout(page: ReactElement) {
    return <FullPageLayout>{page}</FullPageLayout>
}


================================================
FILE: apps/client/pages/plans/[planId].tsx
================================================
import type { ReactElement } from 'react'
import {
    WithSidebarLayout,
    AccountSidebar,
    RetirementPlanChart,
    PlanEventList,
    PlanRangeSelector,
    PlanContext,
    PlanMenu,
    PlanMilestones,
    AddPlanScenario,
    RetirementMilestoneForm,
} from '@maybe-finance/client/features'
import { useRouter } from 'next/router'
import { useState, useMemo } from 'react'
import {
    BlurredContentOverlay,
    MainContentOverlay,
    useAccountContext,
    usePlanApi,
    usePopoutContext,
    useQueryParam,
    useUserAccountContext,
    useUserApi,
} from '@maybe-finance/client/shared'
import { Breadcrumb, Button, DialogV2, LoadingSpinner } from '@maybe-finance/design-system'
import { RiAddLine, RiAlertLine, RiLineChartLine } from 'react-icons/ri'
import { DateTime } from 'luxon'
import classNames from 'classnames'
import { DateUtil, NumberUtil, PlanUtil } from '@maybe-finance/shared'

export default function PlanDetailPage() {
    const planId = useQueryParam('planId', 'string')!
    const router = useRouter()
    const { isReady, noAccounts, allAccountsDisabled } = useUserAccountContext()
    const { addAccount } = useAccountContext()
    const { close: closePopout } = usePopoutContext()
    const { usePlan, useUpdatePlan, usePlanProjections, useUpdatePlanTemplate } = usePlanApi()
    const { useProfile } = useUserApi()

    const plan = usePlan(+planId, { enabled: !!planId })
    const projections = usePlanProjections(+planId, { enabled: !!planId })
    const userProfile = useProfile()

    const updatePlan = useUpdatePlan()
    const updatePlanTemplate = useUpdatePlanTemplate()

    const [addScenario, setAddScenario] = useState<{ isOpen: boolean; scenarioYear?: number }>({
        isOpen: false,
    })

    const [editMilestoneId, setEditMilestoneId] = useState<number | undefined>()

    const [selectedYearRange, setSelectedYearRange] = useState<{ from: number; to: number } | null>(
        null
    )

    const [mode, setMode] = useState<'age' | 'year'>('age')

    const retirement = useMemo(() => {
        const retirementMilestone = plan.data?.milestones.find(
            (m) => m.category === PlanUtil.PlanMilestoneCategory.Retirement
        )
        if (!retirementMilestone) return null

        const projectionIdx = projections.data?.projection.data.findIndex(
            (p) => p.values.year === retirementMilestone.year
        )
        if (!projectionIdx || projectionIdx < 0) return null

        const upper = projections.data?.simulations.at(-1)?.simulation.data?.[projectionIdx]
        const lower = projections.data?.simulations.at(0)?.simulation.data?.[projectionIdx]
        const projection = projections.data?.projection.data?.[projectionIdx]

        if (!upper || !lower || !projection) return null

        return {
            milestone: retirementMilestone,
            projection,
            upper,
            lower,
        }
    }, [projections.data, plan.data])

    // Determines the maximum number of stackable icons that are present on any single year
    const maxIconsPerDatum = useMemo(() => {
        const eventCounts = projections.data?.projection.data.map(
            (datum) => datum.values.events.length + datum.values.milestones.length
        )

        return eventCounts ? Math.max(...eventCounts) : 4 // default makes room for 4 stacked icons
    }, [projections.data?.projection])

    const milestones = retirement?.milestone
        ? [
              {
                  ...retirement.milestone,
                  confidence: PlanUtil.CONFIDENCE_INTERVAL,
                  upper: retirement.upper.values.netWorth,
                  lower: retirement.lower.values.netWorth,
              },
          ]
        : []

    const failureDate = projections.data?.projection.data.find((p) =>
        p.values.netWorth.isNegative()
    )?.date

    if (plan.isError || userProfile.isError) {
        return (
            <MainContentOverlay
                title="Unable to load plan"
                actionText="Back home"
                onAction={() => {
                    router.push('/')
                }}
            >
                <p>
                    We&rsquo;re having some trouble loading this plan. Please contact us if the
                    issue persists.
                </p>
            </MainContentOverlay>
        )
    }

    // Don't render anything until we have a dob to use
    if (userProfile.isLoading || plan.isLoading) {
        return (
            <div className="absolute w-full h-full flex flex-col items-center justify-center">
                <LoadingSpinner />
            </div>
        )
    }

    const planData = plan.data
    const user = userProfile.data

    const userAge = DateUtil.dobToAge(user.dob) ?? PlanUtil.DEFAULT_AGE
    const planStartYear = DateTime.now().year
    const planEndYear = DateUtil.ageToYear(
        plan.data?.lifeExpectancy ?? PlanUtil.DEFAULT_LIFE_EXPECTANCY,
        userAge
    )
    const selectedStartYear = selectedYearRange?.from ?? planStartYear
    const selectedEndYear = selectedYearRange?.to ?? planEndYear

    const projectionEndData = projections.data?.projection.data.find(
        (p) => p.values.year === selectedEndYear
    )

    const insufficientData = isReady && (noAccounts || allAccountsDisabled)

    return (
        <div className={classNames('relative', insufficientData && 'max-h-full')}>
            <PlanContext.Provider
                value={{
                    userAge,
                    planStartYear,
                    planEndYear,
                    milestones,
                }}
            >
                <div className="flex items-center justify-between mb-5">
                    <Breadcrumb.Group>
                        <Breadcrumb href="/plans">Plans</Breadcrumb>
                        <Breadcrumb>{planData.name}</Breadcrumb>
                    </Breadcrumb.Group>
                    <PlanMenu plan={planData} />
                </div>

                <h3 className="max-w-lg">
                    At this rate, you&lsquo;ll have
                    {retirement?.projection.values.netWorth ? (
                        ` ${NumberUtil.format(
                            retirement?.projection.values.netWorth,
                            'short-currency'
                        )} by ${retirement.milestone.year}`
                    ) : projectionEndData ? (
                        ` ${NumberUtil.format(
                            projectionEndData.values.netWorth,
                            'short-currency'
                        )} by ${DateTime.fromISO(projectionEndData.date).year}`
                    ) : (
                        <span className="animate-pulse">...</span>
                    )}
                </h3>

                {failureDate != null && (
                    <div className="bg-red bg-opacity-10 rounded px-4 py-2 my-4 flex items-center gap-3 text-red">
                        <RiAlertLine size={18} className="shrink-0" />
                        <p className="text-base">
                            Your plan is failing. This usually means that your current expenses
                            exceed your income. To fix this, please edit your income and expense
                            events.
                        </p>
                    </div>
                )}

                {/* Range selector */}
                <div className="mt-4">
                    <PlanRangeSelector
                        fromYear={selectedStartYear}
                        toYear={selectedEndYear}
                        onChange={(range) => setSelectedYearRange(range)}
                        mode={mode}
                        onModeChange={setMode}
                    />
                </div>

                {/* Chart area */}
                <div className="mt-4 mb-7 h-[450px]">
                    <RetirementPlanChart
                        isLoading={projections.isLoading || projections.isRefetching}
                        isError={projections.isError}
                        data={projections.data}
                        dateRange={{
                            start: DateTime.fromObject({ year: selectedStartYear }),
                            end: DateTime.fromObject({ year: selectedEndYear }),
                        }}
                        retirement={retirement}
                        onAddEvent={(date) => {
                            setAddScenario({
                                isOpen: true,
                                scenarioYear: DateTime.fromISO(date).year,
                            })
                        }}
                        maxStackCount={maxIconsPerDatum}
                        failsEarly={failureDate != null}
                        mode={mode}
                    />
                </div>

                <div className="flex items-center justify-between">
                    <h5 className="uppercase">Milestones</h5>
                    <Button
                        className="py-1 px-[8px]" // override default size
                        leftIcon={<RiAddLine className="w-5 h-5" />}
                        onClick={() => setAddScenario({ isOpen: true })}
                    >
                        New
                    </Button>
                </div>

                {/* TODO: Once we add the ability to create multiple, arbitrary milestones, we will need to update this data array */}
                <PlanMilestones
                    isLoading={projections.isLoading || plan.isLoading}
                    onAdd={() => setAddScenario({ isOpen: true })}
                    onEdit={(id) => setEditMilestoneId(id)}
                    onDelete={(id) => {
                        updatePlan.mutate({
                            id: planData.id,
                            data: {
                                milestones: {
                                    delete: [id],
                                },
                            },
                        })
                    }}
                    milestones={milestones}
                    events={plan.data?.events ?? []}
                />

                {/* TODO - this will eventually need to be a switch statement to determine which form to open based on the milestone type  */}
                {plan.data && (
                    <DialogV2
                        open={editMilestoneId !== undefined}
                        title="Retirement"
                        onClose={() => setEditMilestoneId(undefined)}
                    >
                        <RetirementMilestoneForm
                            mode="update"
                            defaultValues={{
                                age: DateUtil.yearToAge(
                                    planData.milestones.find(
                                        (m) =>
                                            m.category === PlanUtil.PlanMilestoneCategory.Retirement
                                    )?.year ?? PlanUtil.RETIREMENT_MILESTONE_AGE,
                                    userAge
                                ),
                            }}
                            onSubmit={async (data) => {
                                await updatePlan.mutateAsync({
                                    id: planData.id,
                                    data: {
                                        milestones: {
                                            update: [
                                                {
                                                    id: editMilestoneId,
                                                    data: { type: 'year', year: data.year },
                                                },
                                            ],
                                        },
                                    },
                                })

                                setEditMilestoneId(undefined)
                            }}
                        />
                    </DialogV2>
                )}

                {plan.data && (
                    <AddPlanScenario
                        plan={planData}
                        isOpen={addScenario.isOpen}
                        scenarioYear={
                            addScenario.scenarioYear ??
                            retirement?.projection.values.year ??
                            DateUtil.ageToYear(
                                PlanUtil.RETIREMENT_MILESTONE_AGE,
                                userAge ?? PlanUtil.DEFAULT_AGE
                            )
                        }
                        onClose={() => setAddScenario({ isOpen: false })}
                        onSubmit={async (data) => {
                            switch (data.scenario) {
                                case 'retirement': {
                                    const { year, monthlySpending } = data.data

                                    await updatePlanTemplate.mutateAsync({
                                        id: planData.id,
                                        data: {
                                            type: 'retirement',
                                            data: {
                                                retirementYear: year,
                                                annualRetirementExpenses: monthlySpending * -12,
                                            },
                                        },
                                    })

                                    break
                                }
                                case 'income':
                                case 'expense': {
                                    await updatePlan.mutateAsync({
                                        id: planData.id,
                                        data: {
                                            events: {
                                                create: [data.data],
                                            },
                                        },
                                    })

                                    closePopout()

                                    break
                                }
                                default: {
                                    throw new Error('Scenario handler not implemented')
                                }
                            }

                            setAddScenario({ isOpen: false })
                        }}
                    />
                )}

                {/* Income/Expense Events */}

                <PlanEventList
                    className="mt-16"
                    isLoading={projections.isLoading}
                    events={planData.events}
                    projection={projections.data?.projection}
                    onCreate={(data) => {
                        updatePlan.mutate({
                            id: planData.id,
                            data: {
                                events: {
                                    create: [data],
                                },
                            },
                        })
                    }}
                    onUpdate={(id, data) => {
                        updatePlan.mutate({
                            id: planData.id,
                            data: {
                                events: {
                                    update: [{ id, data }],
                                },
                            },
                        })
                    }}
                    onDelete={(id) => {
                        updatePlan.mutate({
                            id: planData.id,
                            data: {
                                events: {
                                    delete: [id],
                                },
                            },
                        })
                    }}
                />

                {insufficientData && (
                    <BlurredContentOverlay icon={RiLineChartLine} title="Not enough data">
                        <p>
                            You haven&rsquo;t added enough assets or debts yet to be able to
                            generate a plan. Once you do, you&rsquo;ll be able to see your plan and
                            test different parameters.
                        </p>
                        <Button
                            className="w-full mt-6"
                            onClick={addAccount}
                            data-testid="not-enough-data-add-account-button"
                        >
                            Add account
                        </Button>
                    </BlurredContentOverlay>
                )}
            </PlanContext.Provider>
        </div>
    )
}

PlanDetailPage.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/plans/create.tsx
================================================
import type { ReactElement } from 'react'
import { useRouter } from 'next/router'
import { WithSidebarLayout, AccountSidebar, NewPlanForm } from '@maybe-finance/client/features'
import { usePlanApi } from '@maybe-finance/client/shared'

export default function CreatePlanPage() {
    const { useCreatePlan } = usePlanApi()
    const createPlan = useCreatePlan()

    const router = useRouter()

    return (
        <div>
            <h3 className="mb-6">New plan</h3>
            <div className="max-w-sm">
                <NewPlanForm
                    initialValues={{
                        name: 'Retirement',
                        lifeExpectancy: 85,
                    }}
                    onSubmit={async (data) => {
                        const plan = await createPlan.mutateAsync(data)
                        router.push(`/plans/${plan.id}`)
                    }}
                />
            </div>
        </div>
    )
}

CreatePlanPage.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/plans/index.tsx
================================================
import type { ReactElement } from 'react'
import { useEffect } from 'react'

import { WithSidebarLayout, AccountSidebar } from '@maybe-finance/client/features'
import { LoadingSpinner } from '@maybe-finance/design-system'
import { usePlanApi } from '@maybe-finance/client/shared'
import { useRouter } from 'next/router'

export default function PlansPage() {
    const { usePlans } = usePlanApi()
    const plans = usePlans()

    const router = useRouter()

    useEffect(() => {
        if (plans.data) {
            router.push(`/plans/${plans.data.plans[0].id}`)
        }
    }, [plans.data, router])

    if (plans.isLoading) {
        return (
            <div className="absolute inset-0 flex items-center justify-center h-full">
                <LoadingSpinner />
            </div>
        )
    }

    /** @todo add back UI when users are able to manage plans */
    return (
        <></>
        // <div className="h-full flex flex-col items-center justify-center">
        //     <h4 className="mb-2">No plans yet</h4>
        //     <div className="text-base text-gray-100 max-w-sm text-center mb-4">
        //         There are no plans yet. Start by creating a new one or start with sample data to get
        //         a preview.
        //     </div>
        //     <div className="flex space-x-3">
        //         <Link href="/plans/sample">
        //             <Button as="a" variant="secondary">
        //                 Use sample data
        //             </Button>
        //         </Link>
        //         <Link href="/plans/create">
        //             <Button as="a" leftIcon={<RiAddLine className="w-5 h-5" />}>
        //                 Create new plan
        //             </Button>
        //         </Link>
        //     </div>
        // </div>
    )
}

PlansPage.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/register.tsx
================================================
import { useState, type ReactElement } from 'react'
import { Input, InputPassword, Button } from '@maybe-finance/design-system'
import {
    FullPageLayout,
    UserDevTools,
    completedOnboarding,
    onboardedProfile,
} from '@maybe-finance/client/features'
import { signIn, useSession } from 'next-auth/react'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import Script from 'next/script'
import Link from 'next/link'
import { useUserApi } from '@maybe-finance/client/shared'

export default function RegisterPage() {
    const [firstName, setFirstName] = useState('')
    const [lastName, setLastName] = useState('')
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [isValid, setIsValid] = useState(false)
    const [errorMessage, setErrorMessage] = useState<string | null>(null)
    const [isLoading, setIsLoading] = useState(false)
    const [isAdmin, setIsAdmin] = useState<boolean>(false)
    const [isOnboarded, setIsOnboarded] = useState<boolean>(false)

    const { useUpdateOnboarding, useUpdateProfile } = useUserApi()
    const { data: session } = useSession()
    const router = useRouter()

    const updateOnboarding = useUpdateOnboarding()
    const updateProfile = useUpdateProfile()

    useEffect(() => {
        if (session) router.push('/')
    }, [session, router])

    const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault()

        setErrorMessage(null)
        setFirstName('')
        setLastName('')
        setEmail('')
        setPassword('')
        setIsLoading(true)

        const response = await signIn('credentials', {
            email,
            password,
            firstName,
            lastName,
            role: isAdmin ? 'admin' : 'user',
            redirect: false,
        })

        if (isOnboarded && response?.ok) {
            await updateProfile.mutateAsync(onboardedProfile)
            await updateOnboarding.mutateAsync(completedOnboarding)
        }

        if (response && response.error) {
            setErrorMessage(response.error)
            setIsLoading(false)
        }
    }

    return (
        <>
            <Script
                src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"
                strategy="lazyOnload"
            />
            <div className="absolute inset-0 flex flex-col items-center justify-center">
                <div className="p-px w-96 bg-white bg-opacity-10 card-light rounded-3xl radial-gradient-background">
                    <div className="bg-black bg-opacity-75 p-8 rounded-3xl w-full h-full items-center flex flex-col radial-gradient-background-dark">
                        <img
                            className="mb-8"
                            src="/assets/maybe-box.svg"
                            alt="Maybe Finance Logo"
                            height={120}
                            width={120}
                        />
                        <form className="space-y-4 w-full px-4" onSubmit={onSubmit}>
                            <Input
                                type="text"
                                name="firstName"
                                label="First name"
                                value={firstName}
                                onChange={(e) => setFirstName(e.currentTarget.value)}
                            />
                            <Input
                                type="text"
                                name="lastName"
                                label="Last name"
                                value={lastName}
                                onChange={(e) => setLastName(e.currentTarget.value)}
                            />
                            <Input
                                type="text"
                                name="email"
                                label="Email"
                                value={email}
                                onChange={(e) => setEmail(e.currentTarget.value)}
                            />

                            <InputPassword
                                autoComplete="password"
                                name="password"
                                label="Password"
                                value={password}
                                showPasswordRequirements={!isValid}
                                onValidityChange={(checks) => {
                                    const passwordValid =
                                        checks.filter((c) => !c.isValid).length === 0
                                    setIsValid(passwordValid)
                                }}
                                onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
                                    setPassword(e.target.value)
                                }
                            />

                            {errorMessage && password.length === 0 ? (
                                <div className="py-1 text-center text-red text-sm">
                                    {errorMessage}
                                </div>
                            ) : null}

                            <UserDevTools
                                isAdmin={isAdmin}
                                setIsAdmin={setIsAdmin}
                                isOnboarded={isOnboarded}
                                setIsOnboarded={setIsOnboarded}
                            />

                            <Button
                                type="submit"
                                fullWidth
                                disabled={!isValid}
                                variant={isValid ? 'primary' : 'secondary'}
                                isLoading={isLoading}
                            >
                                Register
                            </Button>
                            <div className="text-sm text-gray-50 text-center">
                                <div>
                                    Already have an account?{' '}
                                    <Link
                                        className="hover:text-cyan-400 underline font-medium"
                                        href="/login"
                                    >
                                        Sign in
                                    </Link>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </>
    )
}

RegisterPage.getLayout = function getLayout(page: ReactElement) {
    return <FullPageLayout>{page}</FullPageLayout>
}

RegisterPage.isPublic = true


================================================
FILE: apps/client/pages/settings.tsx
================================================
import type { ReactElement } from 'react'
import { useQueryParam } from '@maybe-finance/client/shared'
import {
    AccountSidebar,
    BillingPreferences,
    SecurityPreferences,
    UserDetails,
    WithSidebarLayout,
} from '@maybe-finance/client/features'
import { Tab } from '@maybe-finance/design-system'
import { useRouter } from 'next/router'
import Script from 'next/script'

export default function SettingsPage() {
    const router = useRouter()

    const tabs = ['details', 'notifications', 'security', 'documents', 'billing']

    const currentTab = useQueryParam('tab', 'string')

    return (
        <>
            <Script
                src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.4.2/zxcvbn.js"
                strategy="lazyOnload"
            />
            <section className="space-y-4">
                <h3>Settings</h3>
                <Tab.Group
                    onChange={(idx) => {
                        router.replace({ query: { tab: tabs[idx] } })
                    }}
                    selectedIndex={tabs.findIndex((tab) => tab === currentTab)}
                >
                    <Tab.List>
                        <Tab>Details</Tab>
                        <Tab>Security</Tab>
                        {process.env.STRIPE_API_KEY && <Tab>Billing</Tab>}
                    </Tab.List>
                    <Tab.Panels>
                        <Tab.Panel>
                            <UserDetails />
                        </Tab.Panel>
                        <Tab.Panel>
                            <div className="mt-6 max-w-lg">
                                <SecurityPreferences />
                            </div>
                        </Tab.Panel>
                        {process.env.STRIPE_API_KEY && (
                            <Tab.Panel>
                                <BillingPreferences />
                            </Tab.Panel>
                        )}
                    </Tab.Panels>
                </Tab.Group>
            </section>
        </>
    )
}

SettingsPage.getLayout = function getLayout(page: ReactElement) {
    return <WithSidebarLayout sidebar={<AccountSidebar />}>{page}</WithSidebarLayout>
}


================================================
FILE: apps/client/pages/upgrade.tsx
================================================
import { UpgradeTakeover } from '@maybe-finance/client/features'
import { useUserApi } from '@maybe-finance/client/shared'
import { useRouter } from 'next/router'

export default function UpgradePage() {
    const router = useRouter()

    const { useSubscription } = useUserApi()
    const subscription = useSubscription()

    return (
        <UpgradeTakeover
            open
            onClose={() =>
                router.push(
                    !subscription.data || subscription.data?.subscribed
                        ? '/'
                        : '/settings?tab=billing'
                )
            }
        />
    )
}


================================================
FILE: apps/client/postcss.config.js
================================================
module.exports = {
    plugins: {
        tailwindcss: { config: './apps/client/tailwind.config.js' },
        autoprefixer: {},
    },
}


================================================
FILE: apps/client/public/.gitkeep
================================================


================================================
FILE: apps/client/public/__appenv.js
================================================
window.__appenv = {}

================================================
FILE: apps/client/public/assets/browserconfig.xml
================================================
<!-- This is just another favicon config for Windows OS, generated by https://realfavicongenerator.net/ -->
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
    <msapplication>
        <tile>
            <square150x150logo src="/mstile-150x150.png"/>
            <TileColor>#da532c</TileColor>
        </tile>
    </msapplication>
</browserconfig>


================================================
FILE: apps/client/public/assets/site.webmanifest
================================================
{
    "name": "Maybe",
    "short_name": "Maybe",
    "description": "Modern day financial planning & wealth management",
    "icons": [
        {
            "src": "/android-chrome-192x192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "/android-chrome-512x512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ],
    "theme_color": "#242629",
    "background_color": "#242629",
    "display": "standalone"
}


================================================
FILE: apps/client/stories/404.stories.tsx
================================================
import React from 'react'
import type { Story, Meta } from '@storybook/react'
import Page404 from '../pages/404'

export default {
    title: 'pages/Page404',
    component: Page404,
} as Meta

export const Default: Story = () => <Page404 />


================================================
FILE: apps/client/styles.css
================================================
@tailwind base;
@tailwind components;
@tailwind utilities;

/* https://tailwindcss.com/docs/adding-base-styles#using-css */
@layer base {
    @font-face {
        font-family: 'Monument Extended';
        font-weight: 100;
        src: url('/assets/fonts/monument/MonumentExtended-Thin.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Monument Extended';
        font-weight: 200;
        src: url('/assets/fonts/monument/MonumentExtended-Light.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Monument Extended';
        font-weight: 300;
        src: url('/assets/fonts/monument/MonumentExtended-Book.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Monument Extended';
        font-weight: 400;
        src: url('/assets/fonts/monument/MonumentExtended-Regular.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Monument Extended';
        font-weight: 500;
        src: url('/assets/fonts/monument/MonumentExtended-Medium.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Monument Extended';
        font-weight: 700;
        src: url('/assets/fonts/monument/MonumentExtended-Bold.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Monument Extended';
        font-weight: 800;
        src: url('/assets/fonts/monument/MonumentExtended-Black.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Monument Extended';
        font-weight: 900;
        src: url('/assets/fonts/monument/MonumentExtended-Heavy.woff2') format('woff2');
    }

    @font-face {
        font-family: 'Inter';
        src: url('/assets/fonts/inter/Inter-Variable.woff2') format('woff2-variations');
        font-weight: 100 900;
    }

    body {
        @apply text-white bg-black;
        overflow: hidden;
    }

    input {
        outline: 0;
    }

    /* This prevents inputs from having a white background when user autofills them
       TODO: Move this into design system
       https://stackoverflow.com/a/41148494 */
    input:-webkit-autofill,
    input:-webkit-autofill:hover,
    input:-webkit-autofill:focus {
        border: none !important;
        caret-color: white !important;
        -webkit-text-fill-color: white !important;
        -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
        transition: background-color 5000s ease-in-out 0s;
    }

    h1 {
        @apply text-5xl font-bold font-display;
    }

    h2 {
        @apply text-4xl font-bold font-display;
    }

    h3 {
        @apply text-3xl font-bold font-display;
    }

    h4 {
        @apply text-2xl font-bold font-display;
    }

    h5 {
        @apply text-lg font-bold font-display;
    }

    h6 {
        @apply text-base font-bold font-display;
    }

    .scrollbar-none {
        overflow: -moz-scrollbars-none;
    }

    .scrollbar-none::-webkit-scrollbar {
        width: 0 !important;
    }

    .custom-gray-scroll::-webkit-scrollbar {
        height: 14px;
        width: 14px;
    }

    .custom-gray-scroll::-webkit-scrollbar-thumb {
        border: 4px solid rgba(0, 0, 0, 0);
        background-clip: content-box;
        @apply bg-gray-200 rounded-full;
    }

    .custom-gray-scroll {
        overflow: overlay !important;
    }

    @-moz-document url-prefix() {
        .custom-gray-scroll {
            overflow: auto !important;
        }
    }

    .show-on-hover-custom-gray-scroll::-webkit-scrollbar {
        height: 14px;
        width: 14px;
    }

    .show-on-hover-custom-gray-scroll::-webkit-scrollbar-thumb {
        border: 4px solid rgba(0, 0, 0, 0);
        background-clip: content-box;
        @apply bg-transparent rounded-full;
    }

    .show-on-hover-custom-gray-scroll {
        overflow: overlay !important;
    }

    .show-on-hover-custom-gray-scroll:hover::-webkit-scrollbar-thumb {
        @apply bg-gray-200;
    }

    @-moz-document url-prefix() {
        .show-on-hover-custom-gray-scroll {
            overflow: auto !important;
        }
    }
}

/* tiptap / prosemirror customization */
.ProseMirror:focus {
    outline: none;
}

.ProseMirror p.placeholder:first-child::before {
    content: attr(data-placeholder);
    float: left;
    height: 0;
    pointer-events: none;
}

.radial-gradient-background {
    background-image: radial-gradient(
        60% 200% at 50% 50%,
        rgba(67, 97, 238, 0.5) 0%,
        transparent 100%
    );
}

.radial-gradient-background-dark {
    background-image: radial-gradient(
        100% 100% at clamp(20%, calc(30% + var(--mx) * 0.05), 40%)
            clamp(50%, calc(50% + var(--my) * 0.05), 60%),
        #4361ee33 0%,
        #16161af4 120%
    );
}


================================================
FILE: apps/client/tailwind.config.js
================================================
const { join } = require('path')
const merge = require('lodash/fp/merge')

// https://blog.nrwl.io/setup-next-js-to-use-tailwind-with-nx-849b7e21d8d0
const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind')

// TODO: Figure out how to simplify this import with scope
const designSystemConfig = require(__dirname + '/../../libs/design-system/tailwind.config.js')

module.exports = merge(designSystemConfig, {
    content: [
        join(__dirname, 'pages/**/*.{js,ts,jsx,tsx}'),
        join(__dirname, 'components/**/*.{js,ts,jsx,tsx}'),
        ...createGlobPatternsForDependencies(__dirname, '/**/!(*.stories|*.spec).{tsx,ts,jsx,js}'),
    ],
    theme: {
        extend: {
            transitionProperty: {
                width: 'width',
            },
            keyframes: {
                wave: {
                    '0%, 100%': { transform: 'rotate(0deg)' },
                    '50%': { transform: 'rotate(20deg)' },
                },
                float: {
                    from: { transform: 'rotate(0deg) translateX(2px) rotate(0deg)' },
                    to: { transform: 'rotate(360deg) translateX(2px) rotate(-360deg)' },
                },
            },
            animation: {
                wave: '3 wave 0.6s ease-in-out',
                float: 'float 4s infinite linear',
            },
            typography: () => {
                const { white, gray, cyan } = designSystemConfig.theme.colors
                return {
                    light: {
                        css: {
                            '--tw-prose-body': white,
                            '--tw-prose-headings': white,
                            '--tw-prose-lead': white,
                            '--tw-prose-links': cyan['600'],
                            '--tw-prose-bold': white,
                            '--tw-prose-counters': white,
                            '--tw-prose-bullets': gray['50'],
                            '--tw-prose-hr': gray['500'],
                            '--tw-prose-quotes': gray['50'],
                            '--tw-prose-quote-borders': gray['50'],
                            '--tw-prose-captions': white,
                            '--tw-prose-code': gray['200'],
                            '--tw-prose-pre-code': gray['100'],
                            '--tw-prose-pre-bg': gray['600'],
                            '--tw-prose-th-borders': gray['50'],
                            '--tw-prose-td-borders': gray['50'],
                            '--tw-prose-invert-body': white,
                            '--tw-prose-invert-headings': white,
                            '--tw-prose-invert-lead': white,
                            '--tw-prose-invert-links': cyan['600'],
                            '--tw-prose-invert-bold': white,
                            '--tw-prose-invert-counters': white,
                            '--tw-prose-invert-bullets': gray['50'],
                            '--tw-prose-invert-hr': gray['500'],
                            '--tw-prose-invert-quotes': gray['50'],
                            '--tw-prose-invert-quote-borders': gray['50'],
                            '--tw-prose-invert-captions': white,
                            '--tw-prose-invert-code': gray['200'],
                            '--tw-prose-invert-pre-code': gray['100'],
                            '--tw-prose-invert-pre-bg': gray['600'],
                            '--tw-prose-invert-th-borders': gray['50'],
                            '--tw-prose-invert-td-borders': gray['50'],
                        },
                    },
                }
            },
        },
    },
    plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')],
})


================================================
FILE: apps/client/tsconfig.json
================================================
{
    "extends": "../../tsconfig.base.json",
    "compilerOptions": {
        "jsx": "preserve",
        "allowJs": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "types": ["node", "jest"],
        "strict": false,
        "strictNullChecks": true,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "resolveJsonModule": true,
        "isolatedModules": true,
        "incremental": true,
        "plugins": [
            {
                "name": "next"
            }
        ]
    },
    "include": [
        "**/*.ts",
        "**/*.tsx",
        "**/*.js",
        "**/*.jsx",
        "next-env.d.ts",
        ".next/types/**/*.ts"
    ],
    "exclude": ["node_modules", "jest.config.ts"]
}


================================================
FILE: apps/client/tsconfig.spec.json
================================================
{
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "outDir": "../../dist/out-tsc",
        "module": "commonjs",
        "types": ["jest", "node"],
        "jsx": "react"
    },
    "include": [
        "**/*.spec.ts",
        "**/*.test.ts",
        "**/*.spec.tsx",
        "**/*.test.tsx",
        "**/*.spec.js",
        "**/*.test.js",
        "**/*.spec.jsx",
        "**/*.test.jsx",
        "**/*.d.ts"
    ]
}


================================================
FILE: apps/e2e/.eslintrc.json
================================================
{
    "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
    "ignorePatterns": ["!**/*"],
    "overrides": [
        {
            "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
            "rules": {}
        },
        {
            "files": ["src/plugins/index.js"],
            "rules": {
                "@typescript-eslint/no-var-requires": "off",
                "no-undef": "off"
            }
        }
    ]
}


================================================
FILE: apps/e2e/cypress.config.ts
================================================
import { defineConfig } from 'cypress'
import { nxE2EPreset } from '@nrwl/cypress/plugins/cypress-preset'

export default defineConfig({
    e2e: {
        ...nxE2EPreset(__dirname),
        video: false,
        screenshotsFolder: '../../dist/cypress/apps/e2e/screenshots',
        viewportWidth: 1280,
        viewportHeight: 720,
        baseUrl: 'http://localhost:4200',
        env: {
            API_URL: 'http://localhost:3333/v1',
            NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
            NEXT_PUBLIC_NEXTAUTH_URL: 'http://localhost:4200',
            NEXTAUTH_URL: process.env.NEXTAUTH_URL,
            STRIPE_WEBHOOK_SECRET: 'REPLACE_THIS',
            STRIPE_CUSTOMER_ID: 'REPLACE_THIS',
            STRIPE_SUBSCRIPTION_ID: 'REPLACE_THIS',
        },
        specPattern: 'src/e2e/**/*.cy.{js,jsx,ts,tsx}',
        supportFile: 'src/support/e2e.ts',
        fixturesFolder: './src/fixtures',
        setupNodeEvents(on, config) {
            on('task', {
                log(message) {
                    console.log(message)
                    return null
                },
            })
        },
    },
})


================================================
FILE: apps/e2e/src/e2e/accounts.cy.ts
================================================
import { DateTime } from 'luxon'

const assertSidebarAccounts = (expectedRows: [string, string][]) => {
    cy.getByTestId('account-accordion-row', { timeout: 60000 }).each((row, index) => {
        cy.wrap(row)
            .find('[data-testid="account-accordion-row-name"]', { timeout: 60000 })
            .should('contain.text', expectedRows[index][0])
        cy.wrap(row)
            .find('[data-testid="account-accordion-row-balance"]', { timeout: 60000 })
            .should('contain.text', expectedRows[index][1])
    })
}

function openEditAccountModal() {
    cy.getByTestId('account-menu').within(() => {
        cy.getByTestId('account-menu-btn').click()
        cy.contains('Edit').click()
    })
}

describe('Accounts', () => {
    it('should interpolate and display manual vehicle account data', () => {
        cy.getByTestId('add-account-button').click()
        cy.contains('h4', 'Add account')
        cy.getByTestId('vehicle-form-add-account').click()
        cy.contains('h4', 'Add vehicle')

        // Details
        cy.get('input[name="make"]').type('Tesla')
        cy.get('input[name="model"]').type('Model 3')
        cy.get('input[name="year"]').type('2022')

        // Purchase date
        cy.get('input[name="startDate"]')
            .clear()
            .type(DateTime.now().minus({ months: 1 }).toFormat('MMddyyyy'))

        // Valuation
        cy.get('input[n
Download .txt
gitextract_0nt4pr3f/

├── .dockerignore
├── .editorconfig
├── .eslintrc.json
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature-request-or-improvement.md
│   └── workflows/
│       └── docker-publish.yml
├── .gitignore
├── .husky/
│   └── pre-commit
├── .prettierignore
├── .prettierrc
├── .storybook/
│   ├── main.js
│   └── tsconfig.json
├── .vscode/
│   ├── extensions.json
│   ├── launch.json
│   └── settings.json
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps/
│   ├── .gitkeep
│   ├── client/
│   │   ├── .babelrc.json
│   │   ├── .eslintrc.json
│   │   ├── .storybook/
│   │   │   ├── main.js
│   │   │   ├── manager.js
│   │   │   ├── preview.js
│   │   │   ├── theme.js
│   │   │   └── tsconfig.json
│   │   ├── Dockerfile
│   │   ├── components/
│   │   │   ├── APM.tsx
│   │   │   ├── Maintenance.stories.tsx
│   │   │   ├── Maintenance.tsx
│   │   │   ├── Meta.tsx
│   │   │   └── account-views/
│   │   │       ├── DefaultView.tsx
│   │   │       ├── InvestmentView.tsx
│   │   │       ├── LoanView.tsx
│   │   │       └── index.ts
│   │   ├── env.sh
│   │   ├── env.ts
│   │   ├── jest.config.ts
│   │   ├── next-env.d.ts
│   │   ├── next.config.js
│   │   ├── pages/
│   │   │   ├── 404.tsx
│   │   │   ├── _app.tsx
│   │   │   ├── _document.tsx
│   │   │   ├── accounts/
│   │   │   │   ├── [accountId].tsx
│   │   │   │   └── index.tsx
│   │   │   ├── api/
│   │   │   │   ├── auth/
│   │   │   │   │   └── [...nextauth].ts
│   │   │   │   └── card.tsx
│   │   │   ├── card/
│   │   │   │   └── [id].tsx
│   │   │   ├── data-editor.tsx
│   │   │   ├── index.tsx
│   │   │   ├── login.tsx
│   │   │   ├── onboarding.tsx
│   │   │   ├── plans/
│   │   │   │   ├── [planId].tsx
│   │   │   │   ├── create.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── register.tsx
│   │   │   ├── settings.tsx
│   │   │   └── upgrade.tsx
│   │   ├── postcss.config.js
│   │   ├── public/
│   │   │   ├── .gitkeep
│   │   │   ├── __appenv.js
│   │   │   └── assets/
│   │   │       ├── browserconfig.xml
│   │   │       └── site.webmanifest
│   │   ├── stories/
│   │   │   └── 404.stories.tsx
│   │   ├── styles.css
│   │   ├── tailwind.config.js
│   │   ├── tsconfig.json
│   │   └── tsconfig.spec.json
│   ├── e2e/
│   │   ├── .eslintrc.json
│   │   ├── cypress.config.ts
│   │   ├── src/
│   │   │   ├── e2e/
│   │   │   │   ├── accounts.cy.ts
│   │   │   │   ├── auth.cy.ts
│   │   │   │   └── subscription.cy.ts
│   │   │   ├── fixtures/
│   │   │   │   └── stripe/
│   │   │   │       ├── checkoutSessionCompleted.ts
│   │   │   │       ├── customerSubscriptionCreated.ts
│   │   │   │       ├── customerSubscriptionDeleted.ts
│   │   │   │       └── index.ts
│   │   │   └── support/
│   │   │       ├── commands.ts
│   │   │       ├── e2e.ts
│   │   │       └── index.ts
│   │   └── tsconfig.json
│   ├── server/
│   │   ├── .eslintrc.json
│   │   ├── Dockerfile
│   │   ├── jest.config.ts
│   │   ├── src/
│   │   │   ├── app/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── account.integration.spec.ts
│   │   │   │   │   ├── balance-sync.integration.spec.ts
│   │   │   │   │   ├── connection.integration.spec.ts
│   │   │   │   │   ├── insights.integration.spec.ts
│   │   │   │   │   ├── net-worth.integration.spec.ts
│   │   │   │   │   ├── prisma.integration.spec.ts
│   │   │   │   │   ├── stripe.integration.spec.ts
│   │   │   │   │   ├── test-data/
│   │   │   │   │   │   ├── portfolio-1/
│   │   │   │   │   │   │   ├── holdings.csv
│   │   │   │   │   │   │   ├── securities.csv
│   │   │   │   │   │   │   └── transactions.csv
│   │   │   │   │   │   └── portfolio-2/
│   │   │   │   │   │       ├── holdings.csv
│   │   │   │   │   │       ├── securities.csv
│   │   │   │   │   │       └── transactions.csv
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── account.ts
│   │   │   │   │       ├── axios.ts
│   │   │   │   │       ├── csv.ts
│   │   │   │   │       ├── server.ts
│   │   │   │   │       └── user.ts
│   │   │   │   ├── admin/
│   │   │   │   │   └── views/
│   │   │   │   │       ├── pages/
│   │   │   │   │       │   ├── dashboard.ejs
│   │   │   │   │       │   └── index.ejs
│   │   │   │   │       └── partials/
│   │   │   │   │           └── head.ejs
│   │   │   │   ├── app.ts
│   │   │   │   ├── lib/
│   │   │   │   │   ├── ability.ts
│   │   │   │   │   ├── email.ts
│   │   │   │   │   ├── endpoint.ts
│   │   │   │   │   ├── logger.ts
│   │   │   │   │   ├── prisma.ts
│   │   │   │   │   ├── stripe.ts
│   │   │   │   │   ├── teller.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── webhook.ts
│   │   │   │   ├── middleware/
│   │   │   │   │   ├── auth-error-handler.ts
│   │   │   │   │   ├── dev-only.ts
│   │   │   │   │   ├── error-handler.ts
│   │   │   │   │   ├── identify-user.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── maintenance.ts
│   │   │   │   │   ├── superjson.ts
│   │   │   │   │   ├── validate-auth-jwt.ts
│   │   │   │   │   └── validate-teller-signature.ts
│   │   │   │   ├── routes/
│   │   │   │   │   ├── account-rollup.router.ts
│   │   │   │   │   ├── accounts.router.ts
│   │   │   │   │   ├── admin.router.ts
│   │   │   │   │   ├── connections.router.ts
│   │   │   │   │   ├── e2e.router.ts
│   │   │   │   │   ├── holdings.router.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── institutions.router.ts
│   │   │   │   │   ├── plans.router.ts
│   │   │   │   │   ├── public.router.ts
│   │   │   │   │   ├── securities.router.ts
│   │   │   │   │   ├── teller.router.ts
│   │   │   │   │   ├── tools.router.ts
│   │   │   │   │   ├── transactions.router.ts
│   │   │   │   │   ├── users.router.ts
│   │   │   │   │   ├── valuations.router.ts
│   │   │   │   │   └── webhooks.router.ts
│   │   │   │   └── trpc.ts
│   │   │   ├── assets/
│   │   │   │   ├── script.js
│   │   │   │   └── styles.css
│   │   │   ├── env.ts
│   │   │   ├── environments/
│   │   │   │   ├── environment.prod.ts
│   │   │   │   └── environment.ts
│   │   │   └── main.ts
│   │   ├── tsconfig.app.json
│   │   ├── tsconfig.json
│   │   └── tsconfig.spec.json
│   └── workers/
│       ├── .eslintrc.json
│       ├── Dockerfile
│       ├── jest.config.ts
│       ├── src/
│       │   ├── app/
│       │   │   ├── __tests__/
│       │   │   │   ├── helpers/
│       │   │   │   │   └── user.test-helper.ts
│       │   │   │   ├── queue.integration.spec.ts
│       │   │   │   ├── security-sync.integration.spec.ts
│       │   │   │   └── teller.integration.spec.ts
│       │   │   ├── lib/
│       │   │   │   ├── di.ts
│       │   │   │   ├── email.ts
│       │   │   │   ├── logger.ts
│       │   │   │   ├── prisma.ts
│       │   │   │   ├── stripe.ts
│       │   │   │   └── teller.ts
│       │   │   └── services/
│       │   │       ├── bull-queue-event-handler.ts
│       │   │       ├── index.ts
│       │   │       └── worker-error.service.ts
│       │   ├── assets/
│       │   │   └── .gitkeep
│       │   ├── env.ts
│       │   ├── environments/
│       │   │   ├── environment.prod.ts
│       │   │   └── environment.ts
│       │   ├── main.ts
│       │   └── utils.ts
│       ├── tsconfig.app.json
│       ├── tsconfig.json
│       └── tsconfig.spec.json
├── babel.config.json
├── custom-express.d.ts
├── docker-compose.test.yml
├── docker-compose.yml
├── jest.config.ts
├── jest.preset.js
├── libs/
│   ├── .gitkeep
│   ├── client/
│   │   ├── features/
│   │   │   ├── .babelrc
│   │   │   ├── .eslintrc.json
│   │   │   ├── jest.config.ts
│   │   │   ├── src/
│   │   │   │   ├── account/
│   │   │   │   │   ├── AccountMenu.tsx
│   │   │   │   │   ├── AccountsSidebar.tsx
│   │   │   │   │   ├── PageTitle.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── accounts-list/
│   │   │   │   │   ├── Account.tsx
│   │   │   │   │   ├── AccountDevTools.tsx
│   │   │   │   │   ├── AccountGroup.tsx
│   │   │   │   │   ├── AccountGroupContainer.tsx
│   │   │   │   │   ├── ConnectedAccountGroup.tsx
│   │   │   │   │   ├── DeleteConnectionDialog.tsx
│   │   │   │   │   ├── DisconnectedAccountGroup.tsx
│   │   │   │   │   ├── ManualAccountGroup.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── accounts-manager/
│   │   │   │   │   ├── AccountTypeGrid.tsx
│   │   │   │   │   ├── AccountTypeSelector.tsx
│   │   │   │   │   ├── AccountValuationFormFields.tsx
│   │   │   │   │   ├── AccountsManager.tsx
│   │   │   │   │   ├── DeleteAccount.tsx
│   │   │   │   │   ├── EditAccount.tsx
│   │   │   │   │   ├── InstitutionGrid.tsx
│   │   │   │   │   ├── InstitutionList.tsx
│   │   │   │   │   ├── asset/
│   │   │   │   │   │   ├── AddAsset.tsx
│   │   │   │   │   │   ├── AssetForm.tsx
│   │   │   │   │   │   ├── EditAsset.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── connected/
│   │   │   │   │   │   ├── ConnectedAccountForm.tsx
│   │   │   │   │   │   ├── EditConnectedAccount.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── liability/
│   │   │   │   │   │   ├── AddLiability.tsx
│   │   │   │   │   │   ├── EditLiability.tsx
│   │   │   │   │   │   ├── LiabilityForm.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── property/
│   │   │   │   │   │   ├── AddProperty.tsx
│   │   │   │   │   │   ├── EditProperty.tsx
│   │   │   │   │   │   ├── PropertyForm.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── stock/
│   │   │   │   │   │   ├── AddStock.tsx
│   │   │   │   │   │   ├── CreateStockAccount.tsx
│   │   │   │   │   │   ├── StockForm.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── vehicle/
│   │   │   │   │       ├── AddVehicle.tsx
│   │   │   │   │       ├── EditVehicle.tsx
│   │   │   │   │       ├── VehicleForm.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── data-editor/
│   │   │   │   │   ├── account/
│   │   │   │   │   │   ├── AccountEditor.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── transaction/
│   │   │   │   │       ├── TransactionEditor.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── holdings-list/
│   │   │   │   │   ├── CostBasisForm.tsx
│   │   │   │   │   ├── HoldingList.tsx
│   │   │   │   │   ├── HoldingPopout.tsx
│   │   │   │   │   ├── HoldingsTable.tsx
│   │   │   │   │   ├── SecurityPriceChart.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── insights/
│   │   │   │   │   ├── explainers/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── investments/
│   │   │   │   │   │   │   ├── AverageReturn.tsx
│   │   │   │   │   │   │   ├── Contributions.tsx
│   │   │   │   │   │   │   ├── PotentialGainLoss.tsx
│   │   │   │   │   │   │   ├── SectorAllocation.tsx
│   │   │   │   │   │   │   ├── TotalFees.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── net-worth/
│   │   │   │   │   │       ├── BadDebt.tsx
│   │   │   │   │   │       ├── GoodDebt.tsx
│   │   │   │   │   │       ├── IlliquidAssets.tsx
│   │   │   │   │   │       ├── IncomePayingDebt.tsx
│   │   │   │   │   │       ├── LiquidAssets.tsx
│   │   │   │   │   │       ├── NetWorthTrend.tsx
│   │   │   │   │   │       ├── SafetyNet.tsx
│   │   │   │   │   │       ├── TotalDebtRatio.tsx
│   │   │   │   │   │       ├── YieldingAssets.tsx
│   │   │   │   │   │       └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── insight-states.ts
│   │   │   │   ├── investment-transactions-list/
│   │   │   │   │   ├── InvestmentTransactionList.tsx
│   │   │   │   │   ├── InvestmentTransactionListItem.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── layout/
│   │   │   │   │   ├── DesktopLayout.tsx
│   │   │   │   │   ├── FullPageLayout.tsx
│   │   │   │   │   ├── MenuPopover.tsx
│   │   │   │   │   ├── MobileLayout.tsx
│   │   │   │   │   ├── NotFound.tsx
│   │   │   │   │   ├── SidebarNav.tsx
│   │   │   │   │   ├── WithOnboardingLayout.tsx
│   │   │   │   │   ├── WithSidebarLayout.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── loan-details/
│   │   │   │   │   ├── LoanCard.tsx
│   │   │   │   │   ├── LoanDetail.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── net-worth-insights/
│   │   │   │   │   ├── NetWorthInsightBadge.tsx
│   │   │   │   │   ├── NetWorthInsightCard.tsx
│   │   │   │   │   ├── NetWorthInsightDetail.tsx
│   │   │   │   │   ├── NetWorthInsightStateAxis.tsx
│   │   │   │   │   ├── NetWorthPrimaryCardGroup.tsx
│   │   │   │   │   ├── breakdown-slider/
│   │   │   │   │   │   ├── NetWorthBreakdownSlider.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── breakdown-table/
│   │   │   │   │   │   ├── BreakdownTableIcon.tsx
│   │   │   │   │   │   ├── NetWorthBreakdownTable.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── income-debt/
│   │   │   │   │   │   ├── IncomeDebtBlock.tsx
│   │   │   │   │   │   ├── IncomeDebtDialog.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── safety-net/
│   │   │   │   │       ├── SafetyNetDialog.tsx
│   │   │   │   │       ├── SafetyNetOpportunityCost.tsx
│   │   │   │   │       ├── SliderBlock.tsx
│   │   │   │   │       └── index.ts
│   │   │   │   ├── onboarding/
│   │   │   │   │   ├── ExampleApp.tsx
│   │   │   │   │   ├── OnboardingBackground.tsx
│   │   │   │   │   ├── OnboardingGuard.tsx
│   │   │   │   │   ├── OnboardingNavbar.tsx
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── sidebar/
│   │   │   │   │   │   ├── SidebarOnboarding.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── steps/
│   │   │   │   │       ├── Intro.tsx
│   │   │   │   │       ├── Profile.tsx
│   │   │   │   │       ├── StepProps.ts
│   │   │   │   │       ├── Welcome.tsx
│   │   │   │   │       ├── YourMaybe.tsx
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── setup/
│   │   │   │   │           ├── AddFirstAccount.tsx
│   │   │   │   │           ├── EmailVerification.tsx
│   │   │   │   │           ├── OtherAccounts.tsx
│   │   │   │   │           └── index.ts
│   │   │   │   ├── plans/
│   │   │   │   │   ├── AddPlanScenario.tsx
│   │   │   │   │   ├── NewPlanForm.tsx
│   │   │   │   │   ├── PlanContext.ts
│   │   │   │   │   ├── PlanEventCard.tsx
│   │   │   │   │   ├── PlanEventForm.tsx
│   │   │   │   │   ├── PlanEventList.tsx
│   │   │   │   │   ├── PlanEventPopout.tsx
│   │   │   │   │   ├── PlanExplainer.tsx
│   │   │   │   │   ├── PlanMenu.tsx
│   │   │   │   │   ├── PlanMilestones.tsx
│   │   │   │   │   ├── PlanParameterCard.tsx
│   │   │   │   │   ├── PlanRangeInput.tsx
│   │   │   │   │   ├── PlanRangeSelector.tsx
│   │   │   │   │   ├── RetirementMilestoneForm.tsx
│   │   │   │   │   ├── RetirementPlanChart.tsx
│   │   │   │   │   ├── icon-utils.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── transactions-list/
│   │   │   │   │   ├── ExcludeTransactionDialog.tsx
│   │   │   │   │   ├── TransactionList.tsx
│   │   │   │   │   ├── TransactionListItem.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── user-billing/
│   │   │   │   │   ├── BillingPreferences.tsx
│   │   │   │   │   ├── PlanSelector.tsx
│   │   │   │   │   ├── PremiumIcon.tsx
│   │   │   │   │   ├── SubscriberGuard.tsx
│   │   │   │   │   ├── UpgradePrompt.tsx
│   │   │   │   │   ├── UpgradeTakeover.tsx
│   │   │   │   │   ├── graphics/
│   │   │   │   │   │   ├── FeaturesGlow.tsx
│   │   │   │   │   │   ├── SideGrid.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── user-details/
│   │   │   │   │   ├── DeleteUserButton.tsx
│   │   │   │   │   ├── DeleteUserModal.tsx
│   │   │   │   │   ├── UserDetails.tsx
│   │   │   │   │   ├── UserDevTools.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── user-security/
│   │   │   │   │   ├── PasswordReset.tsx
│   │   │   │   │   ├── SecurityPreferences.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   └── valuations-list/
│   │   │   │       ├── PerformanceMetric.tsx
│   │   │   │       ├── ValuationList.tsx
│   │   │   │       ├── ValuationsDateCell.tsx
│   │   │   │       ├── ValuationsTable.tsx
│   │   │   │       ├── ValuationsTableForm.tsx
│   │   │   │       ├── index.ts
│   │   │   │       └── types.ts
│   │   │   ├── tsconfig.json
│   │   │   ├── tsconfig.lib.json
│   │   │   └── tsconfig.spec.json
│   │   └── shared/
│   │       ├── .babelrc
│   │       ├── .eslintrc.json
│   │       ├── README.md
│   │       ├── jest.config.ts
│   │       ├── src/
│   │       │   ├── api/
│   │       │   │   ├── index.ts
│   │       │   │   ├── useAccountApi.ts
│   │       │   │   ├── useAccountConnectionApi.ts
│   │       │   │   ├── useAuthUserApi.ts
│   │       │   │   ├── useHoldingApi.ts
│   │       │   │   ├── useInstitutionApi.ts
│   │       │   │   ├── usePlanApi.ts
│   │       │   │   ├── useSecurityApi.ts
│   │       │   │   ├── useTellerApi.ts
│   │       │   │   ├── useTransactionApi.ts
│   │       │   │   ├── useUserApi.ts
│   │       │   │   └── useValuationApi.ts
│   │       │   ├── components/
│   │       │   │   ├── cards/
│   │       │   │   │   ├── MaybeCard.tsx
│   │       │   │   │   ├── MaybeCardShareModal.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── charts/
│   │       │   │   │   ├── index.ts
│   │       │   │   │   └── time-series/
│   │       │   │   │       ├── AxisBottom.tsx
│   │       │   │   │       ├── AxisLeft.tsx
│   │       │   │   │       ├── BaseChart.tsx
│   │       │   │   │       ├── Chart.tsx
│   │       │   │   │       ├── DefaultTooltip.tsx
│   │       │   │   │       ├── FloatingIcon.tsx
│   │       │   │   │       ├── Line.tsx
│   │       │   │   │       ├── LineRange.tsx
│   │       │   │   │       ├── LoadingChart.tsx
│   │       │   │   │       ├── MultiColorGradient.tsx
│   │       │   │   │       ├── PlusCircleGlyph.tsx
│   │       │   │   │       ├── ZeroPointGradient.tsx
│   │       │   │   │       ├── colorScales.ts
│   │       │   │   │       ├── index.ts
│   │       │   │   │       ├── types.ts
│   │       │   │   │       ├── useSeries.ts
│   │       │   │   │       └── useTooltip.ts
│   │       │   │   ├── dialogs/
│   │       │   │   │   ├── NonUSDDialog.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── explainers/
│   │       │   │   │   ├── ExplainerExternalLink.tsx
│   │       │   │   │   ├── ExplainerInfoBlock.tsx
│   │       │   │   │   ├── ExplainerPerformanceBlock.tsx
│   │       │   │   │   ├── ExplainerSection.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── generic/
│   │       │   │   │   ├── BoxIcon.tsx
│   │       │   │   │   ├── Confetti.tsx
│   │       │   │   │   ├── InfiniteScroll.tsx
│   │       │   │   │   ├── InsightGroup.tsx
│   │       │   │   │   ├── InsightPopout.tsx
│   │       │   │   │   ├── ProfileCircle.tsx
│   │       │   │   │   ├── RelativeTime.tsx
│   │       │   │   │   ├── TakeoverBackground.tsx
│   │       │   │   │   ├── Toaster.tsx
│   │       │   │   │   ├── TrendBadge.tsx
│   │       │   │   │   ├── index.ts
│   │       │   │   │   └── small-decimals/
│   │       │   │   │       ├── SmallDecimals.test.tsx
│   │       │   │   │       ├── SmallDecimals.tsx
│   │       │   │   │       └── index.ts
│   │       │   │   ├── index.ts
│   │       │   │   ├── loaders/
│   │       │   │   │   ├── MainContentLoader.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   ├── overlays/
│   │       │   │   │   ├── BlurredContentOverlay.tsx
│   │       │   │   │   ├── ErrorFallbackOverlay.tsx
│   │       │   │   │   ├── MainContentOverlay.tsx
│   │       │   │   │   ├── Overlay.tsx
│   │       │   │   │   └── index.ts
│   │       │   │   └── tables/
│   │       │   │       ├── data-table/
│   │       │   │       │   ├── DataTable.tsx
│   │       │   │       │   ├── DefaultCell.tsx
│   │       │   │       │   ├── EditableBooleanCell.tsx
│   │       │   │       │   ├── EditableCell.tsx
│   │       │   │       │   ├── EditableDateCell.tsx
│   │       │   │       │   ├── EditableDropdownCell.tsx
│   │       │   │       │   ├── EditableStringCell.tsx
│   │       │   │       │   ├── index.ts
│   │       │   │       │   └── types.ts
│   │       │   │       └── index.ts
│   │       │   ├── hooks/
│   │       │   │   ├── index.ts
│   │       │   │   ├── useAccountNotifications.ts
│   │       │   │   ├── useAxiosWithAuth.ts
│   │       │   │   ├── useDebounce.ts
│   │       │   │   ├── useFrame.ts
│   │       │   │   ├── useInterval.ts
│   │       │   │   ├── useLastUpdated.ts
│   │       │   │   ├── useLocalStorage.ts
│   │       │   │   ├── useLogger.ts
│   │       │   │   ├── useModalManager.ts
│   │       │   │   ├── useProviderStatus.ts
│   │       │   │   ├── useQueryParam.ts
│   │       │   │   ├── useScreenSize.ts
│   │       │   │   └── useTeller.ts
│   │       │   ├── index.ts
│   │       │   ├── providers/
│   │       │   │   ├── AccountContextProvider.tsx
│   │       │   │   ├── AxiosProvider.tsx
│   │       │   │   ├── LayoutContextProvider.tsx
│   │       │   │   ├── LogProvider.tsx
│   │       │   │   ├── PopoutProvider.tsx
│   │       │   │   ├── QueryProvider.tsx
│   │       │   │   ├── UserAccountContextProvider.tsx
│   │       │   │   └── index.ts
│   │       │   ├── types/
│   │       │   │   ├── client-side-feature-flags.ts
│   │       │   │   ├── index.ts
│   │       │   │   └── react-types.ts
│   │       │   └── utils/
│   │       │       ├── account-utils.ts
│   │       │       ├── browser-utils.ts
│   │       │       ├── form-utils.ts
│   │       │       ├── image-loaders.ts
│   │       │       └── index.ts
│   │       ├── tsconfig.json
│   │       ├── tsconfig.lib.json
│   │       └── tsconfig.spec.json
│   ├── design-system/
│   │   ├── .babelrc
│   │   ├── .eslintrc.json
│   │   ├── .storybook/
│   │   │   ├── main.js
│   │   │   ├── manager.js
│   │   │   ├── preview.js
│   │   │   ├── theme.js
│   │   │   └── tsconfig.json
│   │   ├── README.md
│   │   ├── assets/
│   │   │   └── styles.css
│   │   ├── docs/
│   │   │   ├── Getting Started/
│   │   │   │   ├── About.stories.mdx
│   │   │   │   ├── Colors.stories.mdx
│   │   │   │   └── Typography.stories.mdx
│   │   │   └── util/
│   │   │       ├── Swatch.tsx
│   │   │       └── SwatchGroup.tsx
│   │   ├── jest.config.ts
│   │   ├── jest.setup.js
│   │   ├── package.json
│   │   ├── postcss.config.js
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   └── lib/
│   │   │       ├── AccordionRow/
│   │   │       │   ├── AccordionRow.spec.tsx
│   │   │       │   ├── AccordionRow.stories.tsx
│   │   │       │   ├── AccordionRow.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── AccordionRow.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Alert/
│   │   │       │   ├── Alert.stories.tsx
│   │   │       │   ├── Alert.tsx
│   │   │       │   └── index.ts
│   │   │       ├── Badge/
│   │   │       │   ├── Badge.spec.tsx
│   │   │       │   ├── Badge.stories.tsx
│   │   │       │   ├── Badge.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Badge.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Breadcrumb/
│   │   │       │   ├── Breadcrumb.spec.tsx
│   │   │       │   ├── Breadcrumb.stories.tsx
│   │   │       │   ├── Breadcrumb.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Breadcrumb.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Button/
│   │   │       │   ├── Button.spec.tsx
│   │   │       │   ├── Button.stories.tsx
│   │   │       │   ├── Button.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Button.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Checkbox/
│   │   │       │   ├── Checkbox.spec.tsx
│   │   │       │   ├── Checkbox.stories.tsx
│   │   │       │   ├── Checkbox.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Checkbox.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── DatePicker/
│   │   │       │   ├── DatePicker.spec.tsx
│   │   │       │   ├── DatePicker.stories.tsx
│   │   │       │   ├── DatePicker.tsx
│   │   │       │   ├── DatePickerCalendar.tsx
│   │   │       │   ├── DatePickerInput.tsx
│   │   │       │   ├── DatePickerMonth.tsx
│   │   │       │   ├── DatePickerQuickSelect.tsx
│   │   │       │   ├── DatePickerRange/
│   │   │       │   │   ├── DatePickerRange.spec.tsx
│   │   │       │   │   ├── DatePickerRange.stories.tsx
│   │   │       │   │   ├── DatePickerRange.tsx
│   │   │       │   │   ├── DatePickerRangeButton.tsx
│   │   │       │   │   ├── DatePickerRangeCalendar.tsx
│   │   │       │   │   ├── DatePickerRangeTabs.tsx
│   │   │       │   │   ├── __snapshots__/
│   │   │       │   │   │   └── DatePickerRange.spec.tsx.snap
│   │   │       │   │   └── index.ts
│   │   │       │   ├── DatePickerYear.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── DatePicker.spec.tsx.snap
│   │   │       │   ├── index.ts
│   │   │       │   ├── selectableRanges.ts
│   │   │       │   ├── utils.spec.tsx
│   │   │       │   └── utils.tsx
│   │   │       ├── Dialog/
│   │   │       │   ├── Dialog.spec.tsx
│   │   │       │   ├── Dialog.stories.tsx
│   │   │       │   ├── Dialog.tsx
│   │   │       │   ├── DialogV2.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Dialog.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── FormGroup/
│   │   │       │   ├── FormGroup.spec.tsx
│   │   │       │   ├── FormGroup.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── FormGroup.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── FractionalCircle/
│   │   │       │   ├── FractionalCircle.stories.tsx
│   │   │       │   ├── FractionalCircle.tsx
│   │   │       │   └── index.ts
│   │   │       ├── IndexTabs/
│   │   │       │   ├── IndexTabs.spec.tsx
│   │   │       │   ├── IndexTabs.stories.tsx
│   │   │       │   ├── IndexTabs.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── IndexTabs.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Listbox/
│   │   │       │   ├── Listbox.spec.tsx
│   │   │       │   ├── Listbox.stories.tsx
│   │   │       │   ├── Listbox.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Listbox.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── LoadingPlaceholder/
│   │   │       │   ├── LoadingPlaceholder.spec.tsx
│   │   │       │   ├── LoadingPlaceholder.stories.tsx
│   │   │       │   ├── LoadingPlaceholder.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── LoadingPlaceholder.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── LoadingSpinner/
│   │   │       │   ├── LoadingSpinner.spec.tsx
│   │   │       │   ├── LoadingSpinner.stories.tsx
│   │   │       │   ├── LoadingSpinner.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── LoadingSpinner.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Menu/
│   │   │       │   ├── Menu.spec.tsx
│   │   │       │   ├── Menu.stories.tsx
│   │   │       │   ├── Menu.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Menu.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Popover/
│   │   │       │   ├── Popover.spec.tsx
│   │   │       │   ├── Popover.stories.tsx
│   │   │       │   ├── Popover.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Popover.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── RTEditor/
│   │   │       │   ├── RTEditor.tsx
│   │   │       │   └── index.ts
│   │   │       ├── RadioGroup/
│   │   │       │   ├── RadioGroup.stories.tsx
│   │   │       │   ├── RadioGroup.tsx
│   │   │       │   └── index.ts
│   │   │       ├── Slider/
│   │   │       │   ├── Slider.spec.tsx
│   │   │       │   ├── Slider.stories.tsx
│   │   │       │   ├── Slider.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Slider.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Step/
│   │   │       │   ├── Step.spec.tsx
│   │   │       │   ├── Step.stories.tsx
│   │   │       │   ├── Step.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Step.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Tab/
│   │   │       │   ├── Tab.spec.tsx
│   │   │       │   ├── Tab.stories.tsx
│   │   │       │   ├── Tab.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Tab.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Takeover/
│   │   │       │   ├── Takeover.spec.tsx
│   │   │       │   ├── Takeover.stories.tsx
│   │   │       │   ├── Takeover.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Takeover.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Toast/
│   │   │       │   ├── Toast.spec.tsx
│   │   │       │   ├── Toast.stories.tsx
│   │   │       │   ├── Toast.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Toast.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Toggle/
│   │   │       │   ├── Toggle.spec.tsx
│   │   │       │   ├── Toggle.stories.tsx
│   │   │       │   ├── Toggle.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Toggle.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── Tooltip/
│   │   │       │   ├── Tooltip.spec.tsx
│   │   │       │   ├── Tooltip.stories.tsx
│   │   │       │   ├── Tooltip.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Tooltip.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       ├── TrendLine/
│   │   │       │   ├── TrendLine.stories.tsx
│   │   │       │   ├── TrendLine.tsx
│   │   │       │   ├── Trendline.spec.tsx
│   │   │       │   ├── __snapshots__/
│   │   │       │   │   └── Trendline.spec.tsx.snap
│   │   │       │   └── index.ts
│   │   │       └── inputs/
│   │   │           ├── Input/
│   │   │           │   ├── Input.spec.tsx
│   │   │           │   ├── Input.stories.tsx
│   │   │           │   ├── Input.tsx
│   │   │           │   ├── __snapshots__/
│   │   │           │   │   └── Input.spec.tsx.snap
│   │   │           │   └── index.ts
│   │   │           ├── InputColorHint/
│   │   │           │   ├── InputColorHint.tsx
│   │   │           │   └── index.ts
│   │   │           ├── InputCurrency/
│   │   │           │   ├── InputCurrency.spec.tsx
│   │   │           │   ├── InputCurrency.stories.tsx
│   │   │           │   ├── InputCurrency.tsx
│   │   │           │   ├── __snapshots__/
│   │   │           │   │   └── InputCurrency.spec.tsx.snap
│   │   │           │   └── index.ts
│   │   │           ├── InputHint/
│   │   │           │   ├── InputHint.tsx
│   │   │           │   └── index.ts
│   │   │           ├── InputPassword/
│   │   │           │   ├── InputPassword.spec.tsx
│   │   │           │   ├── InputPassword.stories.tsx
│   │   │           │   ├── InputPassword.tsx
│   │   │           │   ├── __snapshots__/
│   │   │           │   │   └── InputPassword.spec.tsx.snap
│   │   │           │   └── index.ts
│   │   │           └── index.ts
│   │   ├── tailwind.config.js
│   │   ├── tsconfig.json
│   │   ├── tsconfig.lib.json
│   │   └── tsconfig.spec.json
│   ├── server/
│   │   ├── features/
│   │   │   ├── .babelrc
│   │   │   ├── .eslintrc.json
│   │   │   ├── README.md
│   │   │   ├── jest.config.ts
│   │   │   ├── src/
│   │   │   │   ├── account/
│   │   │   │   │   ├── account-query.service.ts
│   │   │   │   │   ├── account.processor.ts
│   │   │   │   │   ├── account.provider.ts
│   │   │   │   │   ├── account.schema.ts
│   │   │   │   │   ├── account.service.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── insight.service.ts
│   │   │   │   ├── account-balance/
│   │   │   │   │   ├── balance-sync.strategy.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── investment-transaction-balance-sync.strategy.ts
│   │   │   │   │   ├── loan-balance-sync.strategy.ts
│   │   │   │   │   ├── transaction-balance-sync.strategy.ts
│   │   │   │   │   └── valuation-balance-sync.strategy.ts
│   │   │   │   ├── account-connection/
│   │   │   │   │   ├── account-connection.processor.ts
│   │   │   │   │   ├── account-connection.provider.ts
│   │   │   │   │   ├── account-connection.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── auth-user/
│   │   │   │   │   ├── auth-user.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── email/
│   │   │   │   │   ├── email.processor.ts
│   │   │   │   │   ├── email.schema.ts
│   │   │   │   │   ├── email.service.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── providers/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── postmark.provider.ts
│   │   │   │   │       └── smtp.provider.ts
│   │   │   │   ├── holding/
│   │   │   │   │   ├── holding.schema.ts
│   │   │   │   │   ├── holding.service.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── institution/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── institution.provider.ts
│   │   │   │   │   └── institution.service.ts
│   │   │   │   ├── investment-transaction/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── investment-transaction.schema.ts
│   │   │   │   ├── plan/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── plan.schema.ts
│   │   │   │   │   ├── plan.service.ts
│   │   │   │   │   └── projection/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── monte-carlo.spec.ts
│   │   │   │   │       ├── monte-carlo.ts
│   │   │   │   │       ├── projection-calculator.spec.ts
│   │   │   │   │       ├── projection-calculator.ts
│   │   │   │   │       ├── projection-value.spec.ts
│   │   │   │   │       └── projection-value.ts
│   │   │   │   ├── providers/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── property/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── property.service.ts
│   │   │   │   │   ├── teller/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── teller.etl.ts
│   │   │   │   │   │   ├── teller.service.ts
│   │   │   │   │   │   └── teller.webhook.ts
│   │   │   │   │   └── vehicle/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── vehicle.service.ts
│   │   │   │   ├── security-pricing/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── security-pricing.processor.ts
│   │   │   │   │   └── security-pricing.service.ts
│   │   │   │   ├── stripe/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── stripe.webhook.ts
│   │   │   │   ├── transaction/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── transaction.schema.ts
│   │   │   │   │   └── transaction.service.ts
│   │   │   │   ├── user/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── onboarding.schema.ts
│   │   │   │   │   ├── onboarding.service.ts
│   │   │   │   │   ├── user.processor.ts
│   │   │   │   │   └── user.service.ts
│   │   │   │   └── valuation/
│   │   │   │       ├── index.ts
│   │   │   │       └── valuation.service.ts
│   │   │   ├── tsconfig.json
│   │   │   ├── tsconfig.lib.json
│   │   │   └── tsconfig.spec.json
│   │   └── shared/
│   │       ├── .babelrc
│   │       ├── .eslintrc.json
│   │       ├── README.md
│   │       ├── jest.config.ts
│   │       ├── src/
│   │       │   ├── endpoint.ts
│   │       │   ├── etl.ts
│   │       │   ├── index.ts
│   │       │   ├── logger.ts
│   │       │   ├── services/
│   │       │   │   ├── cache.service.ts
│   │       │   │   ├── crypto.service.ts
│   │       │   │   ├── index.ts
│   │       │   │   ├── market-data.service.spec.ts
│   │       │   │   ├── market-data.service.ts
│   │       │   │   ├── pg.service.ts
│   │       │   │   ├── queue/
│   │       │   │   │   ├── bull-queue.ts
│   │       │   │   │   ├── in-memory-queue.ts
│   │       │   │   │   └── index.ts
│   │       │   │   └── queue.service.ts
│   │       │   ├── sql-template-tag.ts
│   │       │   └── utils/
│   │       │       ├── db-utils.ts
│   │       │       ├── error-utils.ts
│   │       │       ├── index.ts
│   │       │       ├── server-utils.ts
│   │       │       └── teller-utils.ts
│   │       ├── tsconfig.json
│   │       ├── tsconfig.lib.json
│   │       └── tsconfig.spec.json
│   ├── shared/
│   │   ├── .babelrc
│   │   ├── .eslintrc.json
│   │   ├── README.md
│   │   ├── jest.config.ts
│   │   ├── src/
│   │   │   ├── index.ts
│   │   │   ├── superjson.spec.ts
│   │   │   ├── superjson.ts
│   │   │   ├── types/
│   │   │   │   ├── account-types.ts
│   │   │   │   ├── api-types.ts
│   │   │   │   ├── email-types.ts
│   │   │   │   ├── general-types.ts
│   │   │   │   ├── holding-types.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── institution-types.ts
│   │   │   │   ├── investment-transaction-types.ts
│   │   │   │   ├── plan-types.ts
│   │   │   │   ├── security-types.ts
│   │   │   │   ├── transaction-types.ts
│   │   │   │   └── user-types.ts
│   │   │   └── utils/
│   │   │       ├── account-utils.ts
│   │   │       ├── date-utils.spec.ts
│   │   │       ├── date-utils.ts
│   │   │       ├── geo-utils.ts
│   │   │       ├── index.ts
│   │   │       ├── market-utils.ts
│   │   │       ├── number-utils.spec.ts
│   │   │       ├── number-utils.ts
│   │   │       ├── plan-utils.ts
│   │   │       ├── shared-utils.spec.ts
│   │   │       ├── shared-utils.ts
│   │   │       ├── stats-utils.spec.ts
│   │   │       ├── stats-utils.ts
│   │   │       ├── test-utils.ts
│   │   │       ├── transaction-utils.ts
│   │   │       └── user-utils.ts
│   │   ├── tsconfig.json
│   │   ├── tsconfig.lib.json
│   │   └── tsconfig.spec.json
│   └── teller-api/
│       ├── .eslintrc.json
│       ├── jest.config.ts
│       ├── src/
│       │   ├── index.ts
│       │   ├── teller-api.ts
│       │   └── types/
│       │       ├── account-balance.ts
│       │       ├── account-details.ts
│       │       ├── accounts.ts
│       │       ├── authentication.ts
│       │       ├── enrollment.ts
│       │       ├── error.ts
│       │       ├── identity.ts
│       │       ├── index.ts
│       │       ├── institutions.ts
│       │       ├── transactions.ts
│       │       └── webhooks.ts
│       ├── tsconfig.json
│       ├── tsconfig.lib.json
│       └── tsconfig.spec.json
├── nx.json
├── package.json
├── prisma/
│   ├── migrations/
│   │   ├── 20211005200319_init/
│   │   │   └── migration.sql
│   │   ├── 20211019194924_unique_constraint_on_account_balances/
│   │   │   └── migration.sql
│   │   ├── 20211019214200_default_values/
│   │   │   └── migration.sql
│   │   ├── 20211025200206_account_balance_schema_update/
│   │   │   └── migration.sql
│   │   ├── 20211026174357_default_text_type/
│   │   │   └── migration.sql
│   │   ├── 20211026175641_default_values/
│   │   │   └── migration.sql
│   │   ├── 20211102165759_account_status/
│   │   │   └── migration.sql
│   │   ├── 20211102183151_add_account_types_and_subtypes/
│   │   │   └── migration.sql
│   │   ├── 20211104155259_account_uniqueness/
│   │   │   └── migration.sql
│   │   ├── 20211105234550_posted_date_type/
│   │   │   └── migration.sql
│   │   ├── 20211109151750_account_type_seed/
│   │   │   └── migration.sql
│   │   ├── 20211110044559_manual_accounts_rename_fk/
│   │   │   └── migration.sql
│   │   ├── 20211116235652_investment_data/
│   │   │   └── migration.sql
│   │   ├── 20211117190140_add_manual_account_types/
│   │   │   └── migration.sql
│   │   ├── 20211117190719_updated_at_default/
│   │   │   └── migration.sql
│   │   ├── 20211117210112_valuation_date/
│   │   │   └── migration.sql
│   │   ├── 20211117233026_add_date_indices/
│   │   │   └── migration.sql
│   │   ├── 20211118160716_account_balance_update/
│   │   │   └── migration.sql
│   │   ├── 20211118191000_account_balance_timestamps/
│   │   │   └── migration.sql
│   │   ├── 20211118194940_account_functions/
│   │   │   └── migration.sql
│   │   ├── 20211118214727_txn_date_naming/
│   │   │   └── migration.sql
│   │   ├── 20211129155121_connection_status_codes/
│   │   │   └── migration.sql
│   │   ├── 20211130184227_new_accounts_available_flag/
│   │   │   └── migration.sql
│   │   ├── 20211201023540_account_single_table_inheritance/
│   │   │   └── migration.sql
│   │   ├── 20211203180216_security_pricing/
│   │   │   └── migration.sql
│   │   ├── 20211204053810_account_balance_hypertable/
│   │   │   └── migration.sql
│   │   ├── 20211207192726_add_valuation_generated_cols/
│   │   │   └── migration.sql
│   │   ├── 20211208162929_transaction_date/
│   │   │   └── migration.sql
│   │   ├── 20211209041710_remove_initial_txn/
│   │   │   └── migration.sql
│   │   ├── 20211209050532_update_fns/
│   │   │   └── migration.sql
│   │   ├── 20211211140103_add_institution_id_to_connection/
│   │   │   └── migration.sql
│   │   ├── 20211213211517_account_user_index/
│   │   │   └── migration.sql
│   │   ├── 20211214162659_security_pricing_source/
│   │   │   └── migration.sql
│   │   ├── 20211215195518_add_account_start_date/
│   │   │   └── migration.sql
│   │   ├── 20211230035441_account_sync_status/
│   │   │   └── migration.sql
│   │   ├── 20220106215040_add_mask_to_account/
│   │   │   └── migration.sql
│   │   ├── 20220107170334_hypertable_chunk_size_tuning/
│   │   │   └── migration.sql
│   │   ├── 20220112171128_update_fn/
│   │   │   └── migration.sql
│   │   ├── 20220121175453_account_liability_json/
│   │   │   └── migration.sql
│   │   ├── 20220124193549_add_plaid_valuation_valuation_type/
│   │   │   └── migration.sql
│   │   ├── 20220124211317_update_valuation_types_and_sources/
│   │   │   └── migration.sql
│   │   ├── 20220125211038_add_unique_constraint_to_valuations/
│   │   │   └── migration.sql
│   │   ├── 20220202184342_account_balances_gapfilled_fn/
│   │   │   └── migration.sql
│   │   ├── 20220203234737_update_fn/
│   │   │   └── migration.sql
│   │   ├── 20220214175713_narrow_transaction_category/
│   │   │   └── migration.sql
│   │   ├── 20220215201534_transaction_remove_subcategory_add_plaid_category/
│   │   │   └── migration.sql
│   │   ├── 20220215212216_add_transaction_indexes/
│   │   │   └── migration.sql
│   │   ├── 20220217040807_add_merchant_name_to_transactions/
│   │   │   └── migration.sql
│   │   ├── 20220228233043_change_money_type/
│   │   │   └── migration.sql
│   │   ├── 20220302181536_add_price_as_of_to_security_pricing/
│   │   │   └── migration.sql
│   │   ├── 20220307200633_remove_price_from_holding/
│   │   │   └── migration.sql
│   │   ├── 20220307211701_valuation_trigger/
│   │   │   └── migration.sql
│   │   ├── 20220311165323_add_shares_per_contract_to_security/
│   │   │   └── migration.sql
│   │   ├── 20220315172110_institution/
│   │   │   └── migration.sql
│   │   ├── 20220316200652_reset_plaid_derivative_prices/
│   │   │   └── migration.sql
│   │   ├── 20220317191949_reset_plaid_derivative_prices_again/
│   │   │   └── migration.sql
│   │   ├── 20220323203441_multi_provider_updates/
│   │   │   └── migration.sql
│   │   ├── 20220323212807_fix_function/
│   │   │   └── migration.sql
│   │   ├── 20220411193518_stop_generating_and_enumize_account_category/
│   │   │   └── migration.sql
│   │   ├── 20220426190758_add_url_and_logo_url_to_institution/
│   │   │   └── migration.sql
│   │   ├── 20220504231954_finicity_updates/
│   │   │   └── migration.sql
│   │   ├── 20220518005502_finicity_customer_id_uniqueness/
│   │   │   └── migration.sql
│   │   ├── 20220519192445_institution_refactor/
│   │   │   └── migration.sql
│   │   ├── 20220520161223_institution_search_algo/
│   │   │   └── migration.sql
│   │   ├── 20220606160203_add_finicity_username_to_user/
│   │   │   └── migration.sql
│   │   ├── 20220607162542_add_crisp_session_token_to_user/
│   │   │   └── migration.sql
│   │   ├── 20220608171009_add_success_rate_and_oauth_to_provider_institutions/
│   │   │   └── migration.sql
│   │   ├── 20220608190342_add_unique_constraint_to_institution/
│   │   │   └── migration.sql
│   │   ├── 20220608202739_add_success_rate_updated_to_provider_institution/
│   │   │   └── migration.sql
│   │   ├── 20220609195136_remove_success_rate_from_provider_institution/
│   │   │   └── migration.sql
│   │   ├── 20220622160129_add_finicity_error/
│   │   │   └── migration.sql
│   │   ├── 20220623171212_remove_holding_unique_constraint/
│   │   │   └── migration.sql
│   │   ├── 20220630005107_category_overrides/
│   │   │   └── migration.sql
│   │   ├── 20220701013813_merge_updates/
│   │   │   └── migration.sql
│   │   ├── 20220707195013_user_overrides/
│   │   │   └── migration.sql
│   │   ├── 20220708191740_txn_excluded_flag/
│   │   │   └── migration.sql
│   │   ├── 20220713134742_add_provider_field/
│   │   │   └── migration.sql
│   │   ├── 20220714180514_update_account_start_date_fn/
│   │   │   └── migration.sql
│   │   ├── 20220714180819_account_category_consolidation/
│   │   │   └── migration.sql
│   │   ├── 20220714181018_update_account_type_model/
│   │   │   └── migration.sql
│   │   ├── 20220715191415_add_liability_fields/
│   │   │   └── migration.sql
│   │   ├── 20220719200317_plaid_txn_category/
│   │   │   └── migration.sql
│   │   ├── 20220720191551_generated_loan_credit_fields/
│   │   │   └── migration.sql
│   │   ├── 20220725143246_map_credit_loan_data/
│   │   │   └── migration.sql
│   │   ├── 20220726003918_reset_loan_account_balances/
│   │   │   └── migration.sql
│   │   ├── 20220727145316_loan_credit_json_nullable/
│   │   │   └── migration.sql
│   │   ├── 20220727202956_loan_account_start_date/
│   │   │   └── migration.sql
│   │   ├── 20220729012630_security_fields/
│   │   │   └── migration.sql
│   │   ├── 20220729202323_txn_updates/
│   │   │   └── migration.sql
│   │   ├── 20220804180126_holdings_view/
│   │   │   └── migration.sql
│   │   ├── 20220804191558_add_excluded_to_holding/
│   │   │   └── migration.sql
│   │   ├── 20220808171116_investment_txn_fees/
│   │   │   └── migration.sql
│   │   ├── 20220808174032_update_holdings_view/
│   │   │   └── migration.sql
│   │   ├── 20220810190306_transaction_category_update/
│   │   │   └── migration.sql
│   │   ├── 20220817180833_dietz/
│   │   │   └── migration.sql
│   │   ├── 20220819151658_add_investment_transaction_category/
│   │   │   └── migration.sql
│   │   ├── 20220915200544_add_plans/
│   │   │   └── migration.sql
│   │   ├── 20220919203059_make_dob_optional/
│   │   │   └── migration.sql
│   │   ├── 20220929161359_remove_crisp_session_token/
│   │   │   └── migration.sql
│   │   ├── 20221004193621_security_brokerage_cash_flag/
│   │   │   └── migration.sql
│   │   ├── 20221007143103_dietz_div0_fix/
│   │   │   └── migration.sql
│   │   ├── 20221017145454_plan_events_milestones/
│   │   │   └── migration.sql
│   │   ├── 20221021162836_remove_dob_from_plan/
│   │   │   └── migration.sql
│   │   ├── 20221024203133_plan_event_milestone_category/
│   │   │   └── migration.sql
│   │   ├── 20221027180912_cascade_plan_milestone_deletion/
│   │   │   └── migration.sql
│   │   ├── 20221109192536_add_stripe_fields/
│   │   │   └── migration.sql
│   │   ├── 20221111192223_ata/
│   │   │   └── migration.sql
│   │   ├── 20221115201138_advisor_approval_status/
│   │   │   └── migration.sql
│   │   ├── 20221117150434_update_advisor_profile/
│   │   │   └── migration.sql
│   │   ├── 20221117213140_add_stripe_trial_reminder_sent/
│   │   │   └── migration.sql
│   │   ├── 20221121214349_add_user_goals/
│   │   │   └── migration.sql
│   │   ├── 20221129201601_conversation_advisor_unique_key/
│   │   │   └── migration.sql
│   │   ├── 20221202213727_notification_preferences/
│   │   │   └── migration.sql
│   │   ├── 20221206153642_conversation_user_required/
│   │   │   └── migration.sql
│   │   ├── 20221207235557_expiry_email_sent/
│   │   │   └── migration.sql
│   │   ├── 20221209041210_user_advisor_notes/
│   │   │   └── migration.sql
│   │   ├── 20221212164355_update_risk_data_type/
│   │   │   └── migration.sql
│   │   ├── 20221214145140_add_audit_table_and_trigger/
│   │   │   └── migration.sql
│   │   ├── 20221222200240_add_onboarding_profile_fields/
│   │   │   └── migration.sql
│   │   ├── 20230105203751_add_maybe_and_title/
│   │   │   └── migration.sql
│   │   ├── 20230105210810_add_member_number/
│   │   │   └── migration.sql
│   │   ├── 20230105221446_user_audit/
│   │   │   └── migration.sql
│   │   ├── 20230106172727_add_user_residence/
│   │   │   └── migration.sql
│   │   ├── 20230106221847_user_profile/
│   │   │   └── migration.sql
│   │   ├── 20230110173017_add_user_member_id/
│   │   │   └── migration.sql
│   │   ├── 20230112163100_add_agreements_table/
│   │   │   └── migration.sql
│   │   ├── 20230113230312_user_email_required/
│   │   │   └── migration.sql
│   │   ├── 20230117131125_update_ama_onboarding/
│   │   │   └── migration.sql
│   │   ├── 20230117150048_user_name/
│   │   │   └── migration.sql
│   │   ├── 20230117192734_update_agreement_types/
│   │   │   └── migration.sql
│   │   ├── 20230119114411_add_onboarding_steps/
│   │   │   └── migration.sql
│   │   ├── 20230123121401_separate_onboarding_flows/
│   │   │   └── migration.sql
│   │   ├── 20230123192138_user_country_state/
│   │   │   └── migration.sql
│   │   ├── 20230126230520_user_deletion/
│   │   │   └── migration.sql
│   │   ├── 20230127003359_store_link_tokens/
│   │   │   └── migration.sql
│   │   ├── 20230130161915_account_value_start_date/
│   │   │   └── migration.sql
│   │   ├── 20230207111117_user_account_linking/
│   │   │   └── migration.sql
│   │   ├── 20230207181233_add_conversation_relations/
│   │   │   └── migration.sql
│   │   ├── 20230207230108_account_balance_strategy/
│   │   │   └── migration.sql
│   │   ├── 20230210163006_add_user_trial_end/
│   │   │   └── migration.sql
│   │   ├── 20230211134603_advisor_crm/
│   │   │   └── migration.sql
│   │   ├── 20230220194746_remove_stripe_trials/
│   │   │   └── migration.sql
│   │   ├── 20230223020847_txn_view/
│   │   │   └── migration.sql
│   │   ├── 20240111031553_remove_advisor_and_related_data/
│   │   │   └── migration.sql
│   │   ├── 20240111213125_next_auth_models/
│   │   │   └── migration.sql
│   │   ├── 20240111213725_add_password_to_auth_user/
│   │   │   └── migration.sql
│   │   ├── 20240112000538_remove_agreement_code/
│   │   │   └── migration.sql
│   │   ├── 20240112001215_remove_convert_kit_usage/
│   │   │   └── migration.sql
│   │   ├── 20240112201750_remove_auth0id_from_user/
│   │   │   └── migration.sql
│   │   ├── 20240112204004_add_first_last_to_authuser/
│   │   │   └── migration.sql
│   │   ├── 20240115222631_add_fields_for_teller/
│   │   │   └── migration.sql
│   │   ├── 20240116023100_add_additional_teller_fields/
│   │   │   └── migration.sql
│   │   ├── 20240116185600_add_teller_provider/
│   │   │   └── migration.sql
│   │   ├── 20240116224800_add_enrollment_id_for_teller/
│   │   │   └── migration.sql
│   │   ├── 20240117191553_categories_for_teller/
│   │   │   └── migration.sql
│   │   ├── 20240118234302_remove_finicity_investment_transaction_categories/
│   │   │   └── migration.sql
│   │   ├── 20240118234302_remove_finicity_transaction_categories/
│   │   │   └── migration.sql
│   │   ├── 20240118234303_remove_finicity_usage/
│   │   │   └── migration.sql
│   │   ├── 20240120213022_remove_transaction_category_generation/
│   │   │   └── migration.sql
│   │   ├── 20240120215821_remove_investment_transaction_category_generation/
│   │   │   └── migration.sql
│   │   ├── 20240121003016_add_asset_class_to_security/
│   │   │   └── migration.sql
│   │   ├── 20240121011219_add_provider_name_to_security/
│   │   │   └── migration.sql
│   │   ├── 20240121013630_add_exchange_info_to_security/
│   │   │   └── migration.sql
│   │   ├── 20240121084645_create_unique_fields_for_security/
│   │   │   └── migration.sql
│   │   ├── 20240121204146_add_auth_user_role/
│   │   │   └── migration.sql
│   │   ├── 20240124090855_add_options_asset_class/
│   │   │   └── migration.sql
│   │   ├── 20240124102931_remove_plaid_usage/
│   │   │   └── migration.sql
│   │   └── migration_lock.toml
│   ├── schema.prisma
│   └── seed.ts
├── redis.Dockerfile
├── redis.conf
├── render.yaml
├── tools/
│   ├── generators/
│   │   ├── .gitkeep
│   │   ├── index.ts
│   │   └── tellerGenerator.ts
│   ├── pages/
│   │   └── projections.html
│   ├── scripts/
│   │   ├── gen-cloudfront-signing-keys.sh
│   │   ├── gen-secret.sh
│   │   ├── getAffectedApps.sh
│   │   ├── runStagingE2ETests.sh
│   │   ├── vercelBuildIgnore.js
│   │   └── wait-for-it.sh
│   ├── test-data/
│   │   ├── index.ts
│   │   └── polygon/
│   │       ├── exchanges.ts
│   │       ├── index.ts
│   │       ├── snapshots.ts
│   │       └── tickers.ts
│   └── tsconfig.tools.json
├── tsconfig.base.json
├── vercel.json
└── workspace.json
Download .txt
SYMBOL INDEX (1573 symbols across 467 files)

FILE: apps/client/components/APM.tsx
  function APM (line 5) | function APM() {

FILE: apps/client/components/Maintenance.tsx
  function Maintenance (line 1) | function Maintenance() {

FILE: apps/client/components/Meta.tsx
  function Meta (line 5) | function Meta() {

FILE: apps/client/components/account-views/DefaultView.tsx
  type DefaultViewProps (line 13) | type DefaultViewProps = {
  function DefaultView (line 24) | function DefaultView({

FILE: apps/client/components/account-views/InvestmentView.tsx
  type Props (line 38) | type Props = {
  type Comparison (line 137) | type Comparison = { ticker: string; display: string; color: string }
  function InvestmentView (line 182) | function InvestmentView({

FILE: apps/client/components/account-views/LoanView.tsx
  type LoanViewProps (line 9) | type LoanViewProps = {
  function LoanView (line 18) | function LoanView({

FILE: apps/client/env.ts
  type Window (line 2) | interface Window {
  function isBrowser (line 7) | function isBrowser() {
  function getEnv (line 11) | function getEnv(key: string): string | undefined {

FILE: apps/client/pages/404.tsx
  function Page404 (line 3) | function Page404() {

FILE: apps/client/pages/_app.tsx
  function App (line 62) | function App({

FILE: apps/client/pages/_document.tsx
  function Document (line 3) | function Document() {

FILE: apps/client/pages/accounts/[accountId].tsx
  function AccountDetailPage (line 28) | function AccountDetailPage() {

FILE: apps/client/pages/accounts/index.tsx
  function AccountsPage (line 22) | function AccountsPage() {

FILE: apps/client/pages/api/auth/[...nextauth].ts
  function getPrismaInstance (line 13) | function getPrismaInstance() {
  function createAuthUser (line 22) | async function createAuthUser(data: Prisma.AuthUserCreateInput) {
  function getAuthUserByEmail (line 27) | async function getAuthUserByEmail(email: string) {
  function validateCredentials (line 34) | async function validateCredentials(credentials: any): Promise<z.infer<ty...
  function createNewAuthUser (line 51) | async function createNewAuthUser(credentials: {
  method authorize (line 115) | async authorize(credentials) {
  method jwt (line 139) | async jwt({ token, user: authUser }: { token: any; user: any }) {
  method session (line 150) | async session({ session, token }: { session: any; token: any }) {

FILE: apps/client/pages/api/card.tsx
  function handler (line 15) | async function handler(req: NextRequest) {

FILE: apps/client/pages/card/[id].tsx
  function Card (line 10) | function Card({ rawData }: { rawData: any }) {
  function getServerSideProps (line 62) | async function getServerSideProps(context) {

FILE: apps/client/pages/data-editor.tsx
  function DataEditor (line 14) | function DataEditor() {

FILE: apps/client/pages/index.tsx
  function NoAccounts (line 25) | function NoAccounts() {
  function AllAccountsDisabled (line 35) | function AllAccountsDisabled() {
  function IndexPage (line 67) | function IndexPage() {

FILE: apps/client/pages/login.tsx
  function LoginPage (line 10) | function LoginPage() {

FILE: apps/client/pages/onboarding.tsx
  function getStepComponent (line 21) | function getStepComponent(stepKey?: string): (props: StepProps) => JSX.E...
  function OnboardingPage (line 41) | function OnboardingPage() {

FILE: apps/client/pages/plans/[planId].tsx
  function PlanDetailPage (line 32) | function PlanDetailPage() {

FILE: apps/client/pages/plans/create.tsx
  function CreatePlanPage (line 6) | function CreatePlanPage() {

FILE: apps/client/pages/plans/index.tsx
  function PlansPage (line 9) | function PlansPage() {

FILE: apps/client/pages/register.tsx
  function RegisterPage (line 16) | function RegisterPage() {

FILE: apps/client/pages/settings.tsx
  function SettingsPage (line 14) | function SettingsPage() {

FILE: apps/client/pages/upgrade.tsx
  function UpgradePage (line 5) | function UpgradePage() {

FILE: apps/e2e/cypress.config.ts
  method setupNodeEvents (line 24) | setupNodeEvents(on, config) {

FILE: apps/e2e/src/e2e/accounts.cy.ts
  function openEditAccountModal (line 14) | function openEditAccountModal() {

FILE: apps/e2e/src/e2e/subscription.cy.ts
  function getAuth0Id (line 7) | function getAuth0Id(): string {
  function sendWebhook (line 14) | function sendWebhook(payload: Record<string, any>) {

FILE: apps/e2e/src/fixtures/stripe/checkoutSessionCompleted.ts
  function checkoutSessionCompleted (line 1) | function checkoutSessionCompleted(auth0Id: string) {

FILE: apps/e2e/src/fixtures/stripe/customerSubscriptionCreated.ts
  function customerSubscriptionCreated (line 3) | function customerSubscriptionCreated() {

FILE: apps/e2e/src/fixtures/stripe/customerSubscriptionDeleted.ts
  function customerSubscriptionDeleted (line 3) | function customerSubscriptionDeleted() {

FILE: apps/e2e/src/support/commands.ts
  type Chainable (line 4) | interface Chainable<Subject> {

FILE: apps/e2e/src/support/e2e.ts
  function authenticateCIUser (line 26) | function authenticateCIUser() {

FILE: apps/server/src/app/__tests__/utils/account.ts
  function createTestInvestmentAccount (line 31) | async function createTestInvestmentAccount(

FILE: apps/server/src/app/__tests__/utils/axios.ts
  function getAxiosClient (line 7) | async function getAxiosClient() {

FILE: apps/server/src/app/__tests__/utils/csv.ts
  function parseCsv (line 3) | async function parseCsv<Keys extends string>(path: string): Promise<Reco...

FILE: apps/server/src/app/__tests__/utils/user.ts
  constant EMAIL (line 4) | const EMAIL = 'test@example.com'
  function resetUser (line 6) | async function resetUser(authId = '__TEST_USER_ID__'): Promise<User> {

FILE: apps/server/src/app/lib/ability.ts
  type CRUDActions (line 22) | type CRUDActions = 'create' | 'read' | 'update' | 'delete'
  type AppActions (line 23) | type AppActions = CRUDActions | 'manage'
  type PrismaSubjects (line 25) | type PrismaSubjects = Subjects<{
  type AppSubjects (line 40) | type AppSubjects = PrismaSubjects | 'all'
  type AppAbility (line 42) | type AppAbility = PrismaAbility<[AppActions, AppSubjects]>
  function defineAbilityFor (line 44) | function defineAbilityFor(user: (Pick<User, 'id'> & { role: AuthUserRole...

FILE: apps/server/src/app/lib/email.ts
  function initializeEmailClient (line 6) | function initializeEmailClient() {

FILE: apps/server/src/app/lib/endpoint.ts
  function getCurrentUser (line 251) | async function getCurrentUser(jwt: NonNullable<Request['user']>) {
  function createContext (line 281) | async function createContext(req: Request) {

FILE: apps/server/src/app/lib/prisma.ts
  function createPrismaClient (line 12) | function createPrismaClient() {

FILE: apps/server/src/app/lib/teller.ts
  function getTellerWebhookUrl (line 8) | async function getTellerWebhookUrl() {

FILE: apps/server/src/app/lib/types.ts
  type TypedRequest (line 3) | interface TypedRequest<T> extends Omit<Request, 'body'> {
  type TypedResponse (line 7) | interface TypedResponse<T> extends Response {
  type DefaultHandler (line 11) | type DefaultHandler<Req, Res> = (
  type GetHandler (line 18) | type GetHandler<Res> = (
  type PostHandler (line 25) | type PostHandler<Req, Res> = DefaultHandler<Req, Res>
  type PutHandler (line 26) | type PutHandler<Req, Res> = DefaultHandler<Req, Res>
  type DeleteHandler (line 27) | type DeleteHandler<Req, Res> = DefaultHandler<Req, Res>

FILE: apps/server/src/app/lib/webhook.ts
  function getWebhookUrl (line 6) | async function getWebhookUrl(): Promise<string> {

FILE: apps/server/src/app/middleware/maintenance.ts
  type MaintenanceOptions (line 3) | type MaintenanceOptions = {
  function maintenance (line 9) | function maintenance(

FILE: apps/server/src/app/middleware/validate-auth-jwt.ts
  constant SECRET (line 5) | const SECRET = process.env.NEXTAUTH_SECRET ?? 'REPLACE_THIS'

FILE: apps/server/src/app/routes/tools.router.ts
  function getInput (line 19) | function getInput(scenario: string, randomized = false): ProjectionInput {

FILE: apps/server/src/app/routes/webhooks.router.ts
  method resolve (line 14) | async resolve({ req, ctx }) {
  method resolve (line 55) | async resolve({ input, ctx }) {

FILE: apps/server/src/app/trpc.ts
  function createTRPCContext (line 6) | async function createTRPCContext({ req }: trpcExpress.CreateExpressConte...
  type Context (line 10) | type Context = trpc.inferAsyncReturnType<typeof createTRPCContext>
  type AppRouter (line 41) | type AppRouter = typeof appRouter

FILE: apps/server/src/assets/script.js
  function login (line 2) | function login() {
  function logout (line 7) | function logout() {

FILE: apps/workers/src/app/__tests__/helpers/user.test-helper.ts
  function resetUser (line 4) | async function resetUser(prisma: PrismaClient, authId = '__TEST_USER_ID_...

FILE: apps/workers/src/app/lib/email.ts
  function initializeEmailClient (line 6) | function initializeEmailClient() {

FILE: apps/workers/src/app/lib/prisma.ts
  function createPrismaClient (line 12) | function createPrismaClient() {

FILE: apps/workers/src/app/services/bull-queue-event-handler.ts
  class BullQueueEventHandler (line 13) | class BullQueueEventHandler implements IBullQueueEventHandler {
    method constructor (line 14) | constructor(private readonly logger: Logger, private readonly prisma: ...
    method onQueueCreated (line 16) | onQueueCreated({ queue }: BullQueue) {
    method getUserFromJob (line 84) | private async getUserFromJob(job: Job) {

FILE: apps/workers/src/app/services/worker-error.service.ts
  type WorkerErrorContext (line 5) | type WorkerErrorContext = { variant: 'unhandled'; error: unknown }
  class WorkerErrorHandlerService (line 7) | class WorkerErrorHandlerService {
    method constructor (line 8) | constructor(private readonly logger: Logger) {}
    method handleWorkersError (line 10) | async handleWorkersError(ctx: WorkerErrorContext) {

FILE: apps/workers/src/main.ts
  function onShutdown (line 239) | async function onShutdown() {

FILE: apps/workers/src/utils.ts
  function cleanUpOutdatedJobs (line 4) | async function cleanUpOutdatedJobs(queues: IQueue[]) {
  function filterOutdatedJobs (line 15) | function filterOutdatedJobs(jobs: JobInformation[]) {

FILE: custom-express.d.ts
  type Request (line 7) | interface Request {
  type Response (line 12) | interface Response {

FILE: libs/client/features/src/account/AccountMenu.tsx
  type Props (line 7) | type Props = {
  function AccountMenu (line 11) | function AccountMenu({ account }: Props) {

FILE: libs/client/features/src/account/AccountsSidebar.tsx
  function SidebarAccountsLoader (line 25) | function SidebarAccountsLoader() {
  function AccountsSidebar (line 41) | function AccountsSidebar() {
  function AccountsSidebarRow (line 221) | function AccountsSidebarRow({

FILE: libs/client/features/src/account/PageTitle.tsx
  type Props (line 5) | type Props = {
  function PageTitle (line 14) | function PageTitle({ isLoading, title, value, trend, trendLabel, trendNe...

FILE: libs/client/features/src/accounts-list/Account.tsx
  type AccountProps (line 10) | type AccountProps = {
  function Account (line 19) | function Account({
  function AccountToggle (line 118) | function AccountToggle({

FILE: libs/client/features/src/accounts-list/AccountDevTools.tsx
  function AccountDevTools (line 13) | function AccountDevTools() {
  type TestEmailFormProps (line 86) | type TestEmailFormProps = {
  type EmailFormFields (line 90) | type EmailFormFields = {
  function TestEmailForm (line 96) | function TestEmailForm({ setOpen }: TestEmailFormProps) {

FILE: libs/client/features/src/accounts-list/AccountGroup.tsx
  type AccountGroupProps (line 5) | type AccountGroupProps = {
  function AccountGroup (line 13) | function AccountGroup({ title, subtitle, content, menu, footer }: Accoun...

FILE: libs/client/features/src/accounts-list/AccountGroupContainer.tsx
  type AccountGroupContainerProps (line 3) | type AccountGroupContainerProps = PropsWithChildren<{
  function AccountGroupContainer (line 8) | function AccountGroupContainer({

FILE: libs/client/features/src/accounts-list/ConnectedAccountGroup.tsx
  type ConnectedAccountGroupProps (line 16) | interface ConnectedAccountGroupProps {
  function ConnectedAccountGroup (line 20) | function ConnectedAccountGroup({ connection }: ConnectedAccountGroupProp...
  function useAccountConnectionStatus (line 148) | function useAccountConnectionStatus(connection: SharedType.ConnectionWit...

FILE: libs/client/features/src/accounts-list/DeleteConnectionDialog.tsx
  type DeleteConnectionDialogProps (line 5) | interface DeleteConnectionDialogProps {
  function DeleteConnectionDialog (line 11) | function DeleteConnectionDialog({

FILE: libs/client/features/src/accounts-list/DisconnectedAccountGroup.tsx
  type DisconnectedAccountGroupProps (line 12) | type DisconnectedAccountGroupProps = {
  function DisconnectedAccountGroup (line 16) | function DisconnectedAccountGroup({ connection }: DisconnectedAccountGro...

FILE: libs/client/features/src/accounts-list/ManualAccountGroup.tsx
  type ManualAccountGroupProps (line 8) | type ManualAccountGroupProps = {
  function ManualAccountGroup (line 14) | function ManualAccountGroup({ title, accounts }: ManualAccountGroupProps) {

FILE: libs/client/features/src/accounts-manager/AccountTypeGrid.tsx
  type AccountSelectorView (line 14) | type AccountSelectorView =
  function AccountTypeGridItem (line 24) | function AccountTypeGridItem({
  function AccountTypeGrid (line 88) | function AccountTypeGrid({ onChange }: { onChange: (view: AccountSelecto...

FILE: libs/client/features/src/accounts-manager/AccountTypeSelector.tsx
  constant SEARCH_DEBOUNCE_MS (line 17) | const SEARCH_DEBOUNCE_MS = 300
  function AccountTypeSelector (line 19) | function AccountTypeSelector({

FILE: libs/client/features/src/accounts-manager/AccountValuationFormFields.tsx
  type AccountValuationFieldProps (line 7) | type AccountValuationFieldProps = {
  function AccountValuationFormFields (line 13) | function AccountValuationFormFields({

FILE: libs/client/features/src/accounts-manager/AccountsManager.tsx
  function AccountsManager (line 15) | function AccountsManager() {

FILE: libs/client/features/src/accounts-manager/DeleteAccount.tsx
  type DeleteAccountProps (line 4) | interface DeleteAccountProps {
  function DeleteAccount (line 10) | function DeleteAccount({ accountId, accountName, onDelete }: DeleteAccou...

FILE: libs/client/features/src/accounts-manager/EditAccount.tsx
  function EditAccount (line 8) | function EditAccount({ accountId }: { accountId?: number }) {

FILE: libs/client/features/src/accounts-manager/InstitutionGrid.tsx
  type GridImage (line 5) | type GridImage = {
  constant BASE_IMAGES_FOLDER (line 11) | const BASE_IMAGES_FOLDER = '/assets/images/financial-institutions/'
  function InstitutionGrid (line 82) | function InstitutionGrid({

FILE: libs/client/features/src/accounts-manager/InstitutionList.tsx
  constant MIN_QUERY_LENGTH (line 6) | const MIN_QUERY_LENGTH = 2
  function InstitutionList (line 8) | function InstitutionList({

FILE: libs/client/features/src/accounts-manager/asset/AddAsset.tsx
  function AddAsset (line 9) | function AddAsset({ defaultValues }: { defaultValues: Partial<CreateAsse...

FILE: libs/client/features/src/accounts-manager/asset/AssetForm.tsx
  type Props (line 9) | type Props =
  function AssetForm (line 23) | function AssetForm({ mode, defaultValues, onSubmit, accountType }: Props) {

FILE: libs/client/features/src/accounts-manager/asset/EditAsset.tsx
  function EditAsset (line 5) | function EditAsset({ account }: { account: SharedType.AccountDetail }) {

FILE: libs/client/features/src/accounts-manager/connected/ConnectedAccountForm.tsx
  type FormData (line 8) | type FormData = {
  type Props (line 14) | type Props = {
  function ConnectedAccountForm (line 20) | function ConnectedAccountForm({ defaultValues, onSubmit, accountType }: ...

FILE: libs/client/features/src/accounts-manager/connected/EditConnectedAccount.tsx
  function EditConnectedAccount (line 5) | function EditConnectedAccount({ account }: { account: SharedType.Account...

FILE: libs/client/features/src/accounts-manager/liability/AddLiability.tsx
  function AddLiability (line 9) | function AddLiability({ defaultValues }: { defaultValues: Partial<Create...

FILE: libs/client/features/src/accounts-manager/liability/EditLiability.tsx
  function EditLiability (line 6) | function EditLiability({ account }: { account: SharedType.AccountDetail ...

FILE: libs/client/features/src/accounts-manager/liability/LiabilityForm.tsx
  type Props (line 40) | type Props =
  function LiabilityForm (line 54) | function LiabilityForm({ mode, defaultValues, onSubmit, accountType }: P...

FILE: libs/client/features/src/accounts-manager/property/AddProperty.tsx
  function AddProperty (line 9) | function AddProperty({ defaultValues }: { defaultValues: Partial<CreateP...

FILE: libs/client/features/src/accounts-manager/property/EditProperty.tsx
  function EditProperty (line 9) | function EditProperty({ account }: { account: SharedType.AccountDetail }) {

FILE: libs/client/features/src/accounts-manager/property/PropertyForm.tsx
  type Props (line 7) | type Props =
  function PropertyForm (line 19) | function PropertyForm({ mode, defaultValues, onSubmit }: Props) {

FILE: libs/client/features/src/accounts-manager/stock/AddStock.tsx
  function AddStock (line 10) | function AddStock({ defaultValues }: { defaultValues: Partial<UpdateStoc...

FILE: libs/client/features/src/accounts-manager/stock/CreateStockAccount.tsx
  type CreateStockAccountProps (line 7) | type CreateStockAccountProps = {
  function CreateStockAccount (line 11) | function CreateStockAccount() {

FILE: libs/client/features/src/accounts-manager/stock/StockForm.tsx
  type Props (line 15) | type Props = {
  function StockForm (line 21) | function StockForm({ mode, defaultValues, onSubmit }: Props) {

FILE: libs/client/features/src/accounts-manager/vehicle/AddVehicle.tsx
  function AddVehicle (line 9) | function AddVehicle({ defaultValues }: { defaultValues: Partial<CreateVe...

FILE: libs/client/features/src/accounts-manager/vehicle/EditVehicle.tsx
  function EditVehicle (line 9) | function EditVehicle({ account }: { account: SharedType.AccountDetail }) {

FILE: libs/client/features/src/accounts-manager/vehicle/VehicleForm.tsx
  type Props (line 7) | type Props =
  function VehicleForm (line 19) | function VehicleForm({ mode, defaultValues, onSubmit }: Props) {

FILE: libs/client/features/src/data-editor/account/AccountEditor.tsx
  type AccountEditorProps (line 15) | type AccountEditorProps = { className?: string }
  type AccountRow (line 17) | type AccountRow = Pick<
  function AccountEditor (line 24) | function AccountEditor({ className }: AccountEditorProps) {

FILE: libs/client/features/src/data-editor/transaction/TransactionEditor.tsx
  type TransactionEditorProps (line 12) | type TransactionEditorProps = { className?: string }
  type TransactionRow (line 14) | type TransactionRow = Pick<
  constant PAGE_SIZE (line 21) | const PAGE_SIZE = 10
  function TransactionEditor (line 23) | function TransactionEditor({ className }: TransactionEditorProps) {

FILE: libs/client/features/src/holdings-list/CostBasisForm.tsx
  type FormValues (line 5) | type FormValues =
  type Props (line 9) | type Props = {
  function CostBasisForm (line 16) | function CostBasisForm({ defaultValues, onSubmit, onClose, isEstimate }:...

FILE: libs/client/features/src/holdings-list/HoldingList.tsx
  type HoldingListProps (line 8) | interface HoldingListProps {
  function HoldingList (line 12) | function HoldingList({ accountId }: HoldingListProps) {

FILE: libs/client/features/src/holdings-list/HoldingPopout.tsx
  type HoldingPopoutProps (line 20) | type HoldingPopoutProps = {
  function HoldingPopout (line 25) | function HoldingPopout({ holdingId, securityId }: HoldingPopoutProps) {

FILE: libs/client/features/src/holdings-list/HoldingsTable.tsx
  type HoldingRowData (line 12) | interface HoldingRowData {
  type HoldingsTableProps (line 30) | interface HoldingsTableProps {
  function HoldingsTable (line 34) | function HoldingsTable({ data }: HoldingsTableProps) {
  function PerformanceMetric (line 202) | function PerformanceMetric({ trend }: { trend: SharedType.Trend | null }) {

FILE: libs/client/features/src/holdings-list/SecurityPriceChart.tsx
  function SecurityPriceChart (line 11) | function SecurityPriceChart({

FILE: libs/client/features/src/insights/explainers/investments/AverageReturn.tsx
  function AverageReturn (line 12) | function AverageReturn(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/investments/Contributions.tsx
  function Contributions (line 10) | function Contributions(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/investments/PotentialGainLoss.tsx
  function PotentialGainLoss (line 10) | function PotentialGainLoss(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/investments/SectorAllocation.tsx
  function SectorAllocation (line 10) | function SectorAllocation(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/investments/TotalFees.tsx
  function TotalFees (line 10) | function TotalFees(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/net-worth/BadDebt.tsx
  function BadDebt (line 15) | function BadDebt(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/net-worth/GoodDebt.tsx
  function GoodDebt (line 15) | function GoodDebt(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/net-worth/IlliquidAssets.tsx
  function IlliquidAssets (line 15) | function IlliquidAssets(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/net-worth/IncomePayingDebt.tsx
  function IncomePayingDebt (line 20) | function IncomePayingDebt({ defaultState }: { defaultState: InsightState...

FILE: libs/client/features/src/insights/explainers/net-worth/LiquidAssets.tsx
  function LiquidAssets (line 15) | function LiquidAssets(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/net-worth/NetWorthTrend.tsx
  function NetWorthTrend (line 18) | function NetWorthTrend(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/net-worth/SafetyNet.tsx
  function SafetyNet (line 20) | function SafetyNet({ defaultState }: { defaultState: InsightState }): JS...

FILE: libs/client/features/src/insights/explainers/net-worth/TotalDebtRatio.tsx
  function TotalDebtRatio (line 15) | function TotalDebtRatio(): JSX.Element {

FILE: libs/client/features/src/insights/explainers/net-worth/YieldingAssets.tsx
  function YieldingAssets (line 15) | function YieldingAssets(): JSX.Element {

FILE: libs/client/features/src/insights/insight-states.ts
  type InsightState (line 3) | type InsightState = 'healthy' | 'review' | 'at-risk' | 'excessive'
  function safetyNetState (line 26) | function safetyNetState(months: Prisma.Decimal): InsightState {
  function incomePayingDebtState (line 33) | function incomePayingDebtState(debtIncomeRatio: Prisma.Decimal): Insight...

FILE: libs/client/features/src/investment-transactions-list/InvestmentTransactionList.tsx
  function InvestmentTransactionList (line 9) | function InvestmentTransactionList({

FILE: libs/client/features/src/investment-transactions-list/InvestmentTransactionListItem.tsx
  function InvestmentTransactionListItem (line 20) | function InvestmentTransactionListItem({

FILE: libs/client/features/src/layout/DesktopLayout.tsx
  type DesktopLayoutProps (line 29) | interface DesktopLayoutProps {
  function NavItem (line 46) | function NavItem({
  function DesktopLayout (line 89) | function DesktopLayout({ children, sidebar }: DesktopLayoutProps) {
  function DefaultContent (line 310) | function DefaultContent({

FILE: libs/client/features/src/layout/FullPageLayout.tsx
  function FullPageLayout (line 4) | function FullPageLayout({ children }: PropsWithChildren) {

FILE: libs/client/features/src/layout/MenuPopover.tsx
  function MenuPopover (line 10) | function MenuPopover({

FILE: libs/client/features/src/layout/MobileLayout.tsx
  type MobileLayoutProps (line 21) | interface MobileLayoutProps {
  function NavItem (line 62) | function NavItem({
  function MobileLayout (line 105) | function MobileLayout({ children, sidebar }: MobileLayoutProps) {

FILE: libs/client/features/src/layout/NotFound.tsx
  function NotFoundSVG (line 4) | function NotFoundSVG() {
  function NotFoundPage (line 120) | function NotFoundPage() {

FILE: libs/client/features/src/layout/SidebarNav.tsx
  type SidebarNavProps (line 6) | type SidebarNavProps = {
  function SidebarNav (line 10) | function SidebarNav({ accountsNotification }: SidebarNavProps) {

FILE: libs/client/features/src/layout/WithOnboardingLayout.tsx
  type Path (line 7) | type Path = {
  type WithOnboardingLayoutProps (line 12) | interface WithOnboardingLayoutProps {
  function WithOnboardingLayout (line 17) | function WithOnboardingLayout({ paths, children }: WithOnboardingLayoutP...

FILE: libs/client/features/src/layout/WithSidebarLayout.tsx
  type WithSidebarLayoutProps (line 6) | interface WithSidebarLayoutProps {
  function WithSidebarLayout (line 11) | function WithSidebarLayout({ sidebar, children }: WithSidebarLayoutProps) {

FILE: libs/client/features/src/loan-details/LoanCard.tsx
  type LoanCardProps (line 7) | type LoanCardProps = PropsWithChildren<{
  function LoanCard (line 20) | function LoanCard({

FILE: libs/client/features/src/loan-details/LoanDetail.tsx
  type LoanDetailProps (line 9) | type LoanDetailProps = {
  function LoanDetail (line 14) | function LoanDetail({ account, showComingSoon = false }: LoanDetailProps) {

FILE: libs/client/features/src/net-worth-insights/NetWorthInsightBadge.tsx
  function NetWorthInsightBadge (line 4) | function NetWorthInsightBadge({ variant }: { variant: InsightState }) {

FILE: libs/client/features/src/net-worth-insights/NetWorthInsightCard.tsx
  type InsightCardProps (line 7) | type InsightCardProps = PropsWithChildren<{
  function NetWorthInsightCard (line 20) | function NetWorthInsightCard({

FILE: libs/client/features/src/net-worth-insights/NetWorthInsightDetail.tsx
  type NetWorthInsightDetailProps (line 16) | type NetWorthInsightDetailProps = {
  function NetWorthInsightDetail (line 20) | function NetWorthInsightDetail({ query }: NetWorthInsightDetailProps) {
  function BreakdownTabPanel (line 181) | function BreakdownTabPanel({
  function ComingSoonBlur (line 227) | function ComingSoonBlur({

FILE: libs/client/features/src/net-worth-insights/NetWorthInsightStateAxis.tsx
  type NetWorthInsightStateAxisProps (line 6) | type NetWorthInsightStateAxisProps = {
  function NetWorthInsightStateAxis (line 11) | function NetWorthInsightStateAxis({ className, steps }: NetWorthInsightS...

FILE: libs/client/features/src/net-worth-insights/NetWorthPrimaryCardGroup.tsx
  type NetWorthPrimaryCardGroupProps (line 15) | type NetWorthPrimaryCardGroupProps = {
  function NetWorthPrimaryCardGroup (line 19) | function NetWorthPrimaryCardGroup({ query }: NetWorthPrimaryCardGroupPro...

FILE: libs/client/features/src/net-worth-insights/breakdown-slider/NetWorthBreakdownSlider.tsx
  type SliderProps (line 9) | interface SliderProps {
  function NetWorthBreakdownSlider (line 28) | function NetWorthBreakdownSlider({ isLoading, rollup }: SliderProps) {

FILE: libs/client/features/src/net-worth-insights/breakdown-table/BreakdownTableIcon.tsx
  function BreakdownTableIcon (line 4) | function BreakdownTableIcon({ className, Icon }: { className: string; Ic...

FILE: libs/client/features/src/net-worth-insights/breakdown-table/NetWorthBreakdownTable.tsx
  type NetWorthBreakdownTableProps (line 18) | interface NetWorthBreakdownTableProps {
  type RowData (line 23) | type RowData =
  function NetWorthBreakdownTable (line 27) | function NetWorthBreakdownTable({ isLoading, rollup }: NetWorthBreakdown...

FILE: libs/client/features/src/net-worth-insights/income-debt/IncomeDebtBlock.tsx
  type IncomeDebtBlock (line 16) | interface IncomeDebtBlock {
  function IncomeDebtBlock (line 22) | function IncomeDebtBlock({

FILE: libs/client/features/src/net-worth-insights/income-debt/IncomeDebtDialog.tsx
  type IncomeDebtDialogProps (line 7) | interface IncomeDebtDialogProps {
  function IncomeDebtDialog (line 13) | function IncomeDebtDialog({ isOpen, onClose, data }: IncomeDebtDialogPro...

FILE: libs/client/features/src/net-worth-insights/safety-net/SafetyNetDialog.tsx
  type SafetyNetDialogProps (line 9) | type SafetyNetDialogProps = {
  function SafetyNetDialog (line 16) | function SafetyNetDialog({

FILE: libs/client/features/src/net-worth-insights/safety-net/SafetyNetOpportunityCost.tsx
  function SafetyNetOpportunityCost (line 4) | function SafetyNetOpportunityCost({

FILE: libs/client/features/src/net-worth-insights/safety-net/SliderBlock.tsx
  type SliderBlock (line 5) | type SliderBlock = {
  function SliderBlock (line 16) | function SliderBlock({

FILE: libs/client/features/src/onboarding/ExampleApp.tsx
  function ExampleApp (line 22) | function ExampleApp({ checklist }: { checklist?: string[] }) {
  function AccountsSidebarRow (line 203) | function AccountsSidebarRow({

FILE: libs/client/features/src/onboarding/OnboardingBackground.tsx
  function OnboardingBackground (line 1) | function OnboardingBackground({ className }: { className: string }) {

FILE: libs/client/features/src/onboarding/OnboardingGuard.tsx
  function shouldRedirect (line 8) | function shouldRedirect(pathname: string, data?: SharedType.OnboardingRe...
  function OnboardingGuard (line 15) | function OnboardingGuard({ children }: PropsWithChildren) {

FILE: libs/client/features/src/onboarding/OnboardingNavbar.tsx
  type Props (line 11) | type Props = {
  function OnboardingNavbar (line 17) | function OnboardingNavbar({ steps, currentStep, onBack }: Props) {

FILE: libs/client/features/src/onboarding/sidebar/SidebarOnboarding.tsx
  type DescriptionProps (line 19) | type DescriptionProps = {
  function Description (line 24) | function Description({ summary, examples }: DescriptionProps) {
  function getDescriptionComponent (line 39) | function getDescriptionComponent(key: string) {
  type Props (line 111) | type Props = {
  function SidebarOnboarding (line 116) | function SidebarOnboarding({ onClose, onHide }: Props) {

FILE: libs/client/features/src/onboarding/steps/Intro.tsx
  function Intro (line 7) | function Intro({ onNext, title }: StepProps) {
  function Wave (line 41) | function Wave() {

FILE: libs/client/features/src/onboarding/steps/Profile.tsx
  type FormValues (line 34) | type FormValues = {
  function Profile (line 43) | function Profile({ title, onNext }: StepProps) {
  type ProfileViewProps (line 86) | type ProfileViewProps = {
  function ProfileForm (line 92) | function ProfileForm({ title, onSubmit, defaultValues }: ProfileViewProp...
  function Question (line 341) | function Question({

FILE: libs/client/features/src/onboarding/steps/StepProps.ts
  type StepProps (line 1) | type StepProps = {

FILE: libs/client/features/src/onboarding/steps/Welcome.tsx
  function Welcome (line 17) | function Welcome({ title: stepTitle, onNext }: StepProps) {

FILE: libs/client/features/src/onboarding/steps/YourMaybe.tsx
  function YourMaybe (line 69) | function YourMaybe({ title, onNext }: StepProps) {
  function Fire (line 183) | function Fire() {

FILE: libs/client/features/src/onboarding/steps/setup/AddFirstAccount.tsx
  function AddFirstAccount (line 11) | function AddFirstAccount({ title, onNext }: StepProps) {

FILE: libs/client/features/src/onboarding/steps/setup/EmailVerification.tsx
  function EmailVerification (line 10) | function EmailVerification({ title, onNext }: StepProps) {

FILE: libs/client/features/src/onboarding/steps/setup/OtherAccounts.tsx
  function OtherAccounts (line 97) | function OtherAccounts({ title, onNext }: StepProps) {

FILE: libs/client/features/src/plans/AddPlanScenario.tsx
  type PlanScenario (line 52) | type PlanScenario =
  type ScenarioOption (line 62) | type ScenarioOption = {
  type ScenarioData (line 69) | type ScenarioData =
  type Props (line 85) | type Props = {
  function AddPlanScenario (line 93) | function AddPlanScenario({ plan, isOpen, scenarioYear, onClose, onSubmit...
  function Option (line 219) | function Option({
  function Search (line 241) | function Search({ onSelect }: { onSelect(scenario: PlanScenario): void }) {

FILE: libs/client/features/src/plans/NewPlanForm.tsx
  type NewPlanValues (line 6) | type NewPlanValues = {
  type Props (line 11) | type Props = {
  function NewPlanForm (line 16) | function NewPlanForm({ initialValues, onSubmit }: Props) {

FILE: libs/client/features/src/plans/PlanContext.ts
  type PlanContext (line 4) | type PlanContext = {
  function usePlanContext (line 13) | function usePlanContext() {

FILE: libs/client/features/src/plans/PlanEventCard.tsx
  type PlanEventCardProps (line 10) | type PlanEventCardProps = PropsWithChildren<{
  function toYearRange (line 17) | function toYearRange(
  function PlanEventCard (line 47) | function PlanEventCard({ event, projection, onClick, className }: PlanEv...

FILE: libs/client/features/src/plans/PlanEventForm.tsx
  type PlanEventValues (line 11) | type PlanEventValues = Pick<
  type PlanEventFormProps (line 24) | type PlanEventFormProps = {
  function PlanEventForm (line 32) | function PlanEventForm({

FILE: libs/client/features/src/plans/PlanEventList.tsx
  type PlanCreateInput (line 13) | type PlanCreateInput = Record<string, any>
  type PlanUpdateInput (line 14) | type PlanUpdateInput = PlanCreateInput
  type PlanEventListProps (line 16) | type PlanEventListProps = PropsWithChildren<{
  function PlanEventList (line 27) | function PlanEventList({
  function EmptyStateCards (line 211) | function EmptyStateCards({

FILE: libs/client/features/src/plans/PlanEventPopout.tsx
  type PlanEventListProps (line 6) | type PlanEventListProps = PropsWithChildren<{}>
  function PlanEventPopout (line 8) | function PlanEventPopout({ children }: PlanEventListProps) {

FILE: libs/client/features/src/plans/PlanExplainer.tsx
  type Props (line 14) | type Props = {
  function PlanExplainer (line 18) | function PlanExplainer({ initialSection }: Props) {
  type ReturnsData (line 176) | type ReturnsData = {
  function ReturnsTable (line 217) | function ReturnsTable() {

FILE: libs/client/features/src/plans/PlanMenu.tsx
  type Props (line 11) | type Props = {
  function PlanMenu (line 15) | function PlanMenu({ plan }: Props) {

FILE: libs/client/features/src/plans/PlanMilestones.tsx
  type MilestoneRange (line 11) | type MilestoneRange = {
  type Props (line 17) | type Props = {
  function PlanMilestones (line 26) | function PlanMilestones({ isLoading, onAdd, onEdit, onDelete, milestones...

FILE: libs/client/features/src/plans/PlanParameterCard.tsx
  type PlanParameterCardProps (line 6) | type PlanParameterCardProps = PropsWithChildren<{
  function PlanParameterCard (line 15) | function PlanParameterCard({

FILE: libs/client/features/src/plans/PlanRangeInput.tsx
  type ValueType (line 21) | type ValueType = { year: number | null; milestoneId: SharedType.PlanMile...
  type PlanRangeInputProps (line 23) | type PlanRangeInputProps = {
  type OptionType (line 31) | type OptionType = 'retirement' | 'start' | 'end' | 'now' | 'age' | 'year'
  function PlanRangeInput (line 42) | function PlanRangeInput({
  function SectionLabel (line 180) | function SectionLabel({ children }: { children: ReactNode }) {
  function Option (line 184) | function Option({

FILE: libs/client/features/src/plans/PlanRangeSelector.tsx
  type PlanRangeSelectorProps (line 8) | type PlanRangeSelectorProps = {
  function PlanRangeSelector (line 16) | function PlanRangeSelector({

FILE: libs/client/features/src/plans/RetirementMilestoneForm.tsx
  type FormData (line 8) | type FormData = {
  type RefMode (line 14) | type RefMode = {
  type Props (line 19) | type Props = {
  function RetirementMilestoneForm (line 36) | function RetirementMilestoneForm({ mode, onSubmit, defaultValues }: Prop...

FILE: libs/client/features/src/plans/RetirementPlanChart.tsx
  type Props (line 14) | type Props = {
  constant MAX_ICONS_PER_DATUM (line 29) | const MAX_ICONS_PER_DATUM = 4
  function RetirementPlanChart (line 31) | function RetirementPlanChart({

FILE: libs/client/features/src/plans/icon-utils.ts
  function getEventIcon (line 7) | function getEventIcon(
  function getMilestoneIcon (line 39) | function getMilestoneIcon(milestone: SharedType.PlanMilestone) {

FILE: libs/client/features/src/transactions-list/ExcludeTransactionDialog.tsx
  type ExcludeTransactionDialogProps (line 5) | interface ExcludeTransactionDialogProps {
  function ExcludeTransactionDialog (line 12) | function ExcludeTransactionDialog({

FILE: libs/client/features/src/transactions-list/TransactionList.tsx
  function TransactionList (line 8) | function TransactionList({ accountId }: { accountId: number }) {

FILE: libs/client/features/src/transactions-list/TransactionListItem.tsx
  function TransactionListItem (line 29) | function TransactionListItem({

FILE: libs/client/features/src/user-billing/BillingPreferences.tsx
  function BillingPreferences (line 8) | function BillingPreferences() {

FILE: libs/client/features/src/user-billing/PlanSelector.tsx
  type PlanSelectorProps (line 3) | type PlanSelectorProps = {
  function PlanSelector (line 9) | function PlanSelector({ selected, onChange, className }: PlanSelectorPro...
  function PlanOption (line 38) | function PlanOption({

FILE: libs/client/features/src/user-billing/PremiumIcon.tsx
  type PremiumIconProps (line 14) | type PremiumIconProps = React.HTMLAttributes<HTMLImageElement> & {
  function PremiumIcon (line 20) | function PremiumIcon({

FILE: libs/client/features/src/user-billing/SubscriberGuard.tsx
  function shouldRedirect (line 8) | function shouldRedirect(path: string, data?: SharedType.UserSubscription) {
  function SubscriberGuard (line 23) | function SubscriberGuard({ children }: PropsWithChildren) {

FILE: libs/client/features/src/user-billing/UpgradePrompt.tsx
  function UpgradePrompt (line 9) | function UpgradePrompt() {

FILE: libs/client/features/src/user-billing/UpgradeTakeover.tsx
  type UpgradeTakeoverProps (line 20) | type UpgradeTakeoverProps = {
  function UpgradeTakeover (line 25) | function UpgradeTakeover({ open, onClose }: UpgradeTakeoverProps) {

FILE: libs/client/features/src/user-billing/graphics/FeaturesGlow.tsx
  function FeaturesGlow (line 1) | function FeaturesGlow({ className }: { className: string }) {

FILE: libs/client/features/src/user-billing/graphics/SideGrid.tsx
  function SideGrid (line 1) | function SideGrid({ className }: { className: string }) {

FILE: libs/client/features/src/user-details/DeleteUserButton.tsx
  function DeleteUserButton (line 6) | function DeleteUserButton({ onDelete }: { onDelete: () => void }) {

FILE: libs/client/features/src/user-details/DeleteUserModal.tsx
  constant COUNT_DOWN_SECONDS (line 4) | const COUNT_DOWN_SECONDS = 3
  type DeleteUserModalProps (line 6) | interface DeleteUserModalProps {
  function DeleteUserModal (line 16) | function DeleteUserModal({ isOpen, onClose, onConfirm }: DeleteUserModal...

FILE: libs/client/features/src/user-details/UserDetails.tsx
  function UserDetails (line 30) | function UserDetails() {
  type ProfileFields (line 96) | type ProfileFields = {
  type ProfileFormProps (line 102) | type ProfileFormProps = {
  function ProfileForm (line 108) | function ProfileForm({ defaultValues, onSubmit, isSubmitting }: ProfileF...
  function MaybeCardSection (line 150) | function MaybeCardSection() {

FILE: libs/client/features/src/user-details/UserDevTools.tsx
  type UserDevToolsProps (line 4) | type UserDevToolsProps = {
  function UserDevTools (line 11) | function UserDevTools({
  type OnboardingType (line 34) | interface OnboardingType {

FILE: libs/client/features/src/user-security/PasswordReset.tsx
  function PasswordReset (line 6) | function PasswordReset() {

FILE: libs/client/features/src/user-security/SecurityPreferences.tsx
  function SecurityPreferences (line 5) | function SecurityPreferences() {

FILE: libs/client/features/src/valuations-list/PerformanceMetric.tsx
  function PerformanceMetric (line 5) | function PerformanceMetric({

FILE: libs/client/features/src/valuations-list/ValuationList.tsx
  type ValuationListProps (line 12) | interface ValuationListProps {
  function ValuationList (line 17) | function ValuationList({ accountId, negative = false }: ValuationListPro...

FILE: libs/client/features/src/valuations-list/ValuationsDateCell.tsx
  function ValuationsDateCell (line 11) | function ValuationsDateCell({
  function ValuationIcon (line 106) | function ValuationIcon({ className, Icon }: { className: string; Icon: I...

FILE: libs/client/features/src/valuations-list/ValuationsTable.tsx
  type ValuationsTableProps (line 10) | interface ValuationsTableProps {
  function ValuationsTable (line 18) | function ValuationsTable({ data, rowEditingIndex, onEdit, negative }: Va...

FILE: libs/client/features/src/valuations-list/ValuationsTableForm.tsx
  type FormValues (line 10) | type FormValues = { date: string; amount: number }
  function ValuationsTableForm (line 12) | function ValuationsTableForm({

FILE: libs/client/features/src/valuations-list/types.ts
  type ValuationRowData (line 4) | interface ValuationRowData {

FILE: libs/client/shared/src/api/useAccountApi.ts
  method getAccounts (line 17) | async getAccounts() {
  method get (line 22) | async get(id: SharedType.Account['id']): Promise<SharedType.AccountDetai...
  method create (line 27) | async create(input: Record<string, any>) {
  method update (line 32) | async update(id: SharedType.Account['id'], input: Record<string, any>) {
  method delete (line 37) | async delete(id: SharedType.Account['id']) {
  method getBalances (line 42) | async getBalances(
  method getReturns (line 54) | async getReturns(
  method getTransactions (line 67) | async getTransactions(
  method getHoldings (line 78) | async getHoldings(
  method getInvestmentTransactions (line 89) | async getInvestmentTransactions(
  method getInsights (line 103) | async getInsights(id: SharedType.Account['id']): Promise<SharedType.Acco...
  method getRollup (line 108) | async getRollup(start: string, end: string): Promise<SharedType.AccountR...
  method sync (line 115) | async sync(id: SharedType.Account['id']) {
  function useAccountApi (line 133) | function useAccountApi() {

FILE: libs/client/shared/src/api/useAccountConnectionApi.ts
  method update (line 11) | async update(id: SharedType.AccountConnection['id'], input: Record<strin...
  method delete (line 16) | async delete(id: SharedType.AccountConnection['id']) {
  method deleteAll (line 21) | async deleteAll() {
  method disconnect (line 26) | async disconnect(id: SharedType.AccountConnection['id']) {
  method reconnect (line 33) | async reconnect(id: SharedType.AccountConnection['id']) {
  method sync (line 40) | async sync(id: SharedType.AccountConnection['id']) {
  function useAccountConnectionApi (line 46) | function useAccountConnectionApi() {

FILE: libs/client/shared/src/api/useAuthUserApi.ts
  method getByEmail (line 8) | async getByEmail(email: string) {
  function useAuthUserApi (line 18) | function useAuthUserApi() {

FILE: libs/client/shared/src/api/useHoldingApi.ts
  method getHolding (line 12) | async getHolding(id: Holding['id']) {
  method getInsights (line 17) | async getInsights(id: Holding['id']) {
  method update (line 22) | async update(id: Holding['id'], input: Record<string, any>) {
  function useHoldingApi (line 28) | function useHoldingApi() {

FILE: libs/client/shared/src/api/useInstitutionApi.ts
  method getInstitutions (line 10) | async getInstitutions(page: number, search?: string) {
  method sync (line 17) | async sync() {
  method deduplicate (line 22) | async deduplicate() {
  function useInstitutionApi (line 32) | function useInstitutionApi() {

FILE: libs/client/shared/src/api/usePlanApi.ts
  method getPlans (line 10) | async getPlans() {
  method get (line 15) | async get(id: SharedType.Plan['id']) {
  method create (line 20) | async create(input: Record<string, any>) {
  method createTemplate (line 25) | async createTemplate(input: Record<string, any>) {
  method update (line 30) | async update(id: SharedType.Plan['id'], input: Record<string, any>) {
  method updateTemplate (line 35) | async updateTemplate(
  method delete (line 46) | async delete(id: SharedType.Plan['id']) {
  method projections (line 51) | async projections(id: SharedType.Plan['id']) {
  function usePlanApi (line 64) | function usePlanApi() {

FILE: libs/client/shared/src/api/useSecurityApi.ts
  method getAllSecurities (line 11) | async getAllSecurities() {
  method getSecurity (line 16) | async getSecurity(id: Security['id']) {
  method getSecurityDetails (line 21) | async getSecurityDetails(id: Security['id']) {
  method syncUSStockTickers (line 26) | async syncUSStockTickers() {
  method syncSecurityPricing (line 31) | async syncSecurityPricing() {
  function useSecurityApi (line 42) | function useSecurityApi() {

FILE: libs/client/shared/src/api/useTellerApi.ts
  type TellerInstitution (line 10) | type TellerInstitution = {
  method handleEnrollment (line 16) | async handleEnrollment(input: {
  function useTellerApi (line 28) | function useTellerApi() {

FILE: libs/client/shared/src/api/useTransactionApi.ts
  method getAll (line 11) | async getAll(pageIndex: number, pageSize: number) {
  method get (line 18) | async get(id: SharedType.Transaction['id']): Promise<SharedType.Transact...
  method update (line 25) | async update(id: SharedType.Transaction['id'], input: Record<string, any...
  function useTransactionApi (line 31) | function useTransactionApi() {

FILE: libs/client/shared/src/api/useUserApi.ts
  method getNetWorthSeries (line 12) | async getNetWorthSeries(start: string, end: string) {
  method getInsights (line 22) | async getInsights() {
  method getNetWorth (line 27) | async getNetWorth(date: string) {
  method update (line 34) | async update(userData: SharedType.UpdateUser) {
  method get (line 39) | async get() {
  method delete (line 44) | async delete() {
  method getOnboarding (line 48) | async getOnboarding(flow: SharedType.OnboardingFlow) {
  method updateOnboarding (line 53) | async updateOnboarding(input: {
  method getAuthProfile (line 62) | async getAuthProfile() {
  method getSubscription (line 67) | async getSubscription() {
  method changePassword (line 72) | async changePassword(newPassword: SharedType.PasswordReset) {
  method resendEmailVerification (line 80) | async resendEmailVerification(authId?: string) {
  method createCheckoutSession (line 89) | async createCheckoutSession(plan: string) {
  method createCustomerPortalSession (line 95) | async createCustomerPortalSession(plan: string) {
  method getMemberCardDetails (line 103) | async getMemberCardDetails(memberId?: string) {
  method sendTestEmail (line 111) | async sendTestEmail(input: SharedType.SendTestEmail) {
  function useUserApi (line 126) | function useUserApi() {

FILE: libs/client/shared/src/api/useValuationApi.ts
  method create (line 14) | async create(accountId: SharedType.Account['id'], input: Record<string, ...
  method update (line 22) | async update(id: SharedType.Valuation['id'], input: Record<string, any>) {
  method delete (line 27) | async delete(id: SharedType.Valuation['id']) {
  method getValuations (line 32) | async getValuations(
  function useValuationApi (line 52) | function useValuationApi() {

FILE: libs/client/shared/src/components/cards/MaybeCard.tsx
  type MaybeCardProps (line 14) | type MaybeCardProps = {
  function MaybeCard (line 22) | function MaybeCard({ variant = 'default', details, flipped }: MaybeCardP...

FILE: libs/client/shared/src/components/cards/MaybeCardShareModal.tsx
  type MaybeCardShareModalProps (line 8) | type MaybeCardShareModalProps = {
  function MaybeCardShareModal (line 15) | function MaybeCardShareModal({ isOpen, onClose, cardUrl, card }: MaybeCa...

FILE: libs/client/shared/src/components/charts/time-series/AxisBottom.tsx
  type Props (line 10) | type Props = {
  function AxisBottom (line 15) | function AxisBottom({

FILE: libs/client/shared/src/components/charts/time-series/AxisLeft.tsx
  function AxisLeft (line 8) | function AxisLeft(props: Omit<SharedAxisProps<ValidYScaleTypes>, 'scale'...

FILE: libs/client/shared/src/components/charts/time-series/BaseChart.tsx
  function BaseChart (line 24) | function BaseChart<TDatum extends Datum>({

FILE: libs/client/shared/src/components/charts/time-series/Chart.tsx
  function Chart (line 14) | function Chart<TDatum extends Datum>({

FILE: libs/client/shared/src/components/charts/time-series/DefaultTooltip.tsx
  type Props (line 10) | type Props = {
  function DefaultTooltip (line 19) | function DefaultTooltip({ title: _title }: Props) {

FILE: libs/client/shared/src/components/charts/time-series/FloatingIcon.tsx
  type Props (line 6) | interface Props extends SVGProps<SVGCircleElement> {
  function FloatingIcon (line 19) | function FloatingIcon({ left, top, stackIdx, icon: Icon, iconColor, ...r...

FILE: libs/client/shared/src/components/charts/time-series/Line.tsx
  function Line (line 13) | function Line({

FILE: libs/client/shared/src/components/charts/time-series/LineRange.tsx
  function LineRange (line 14) | function LineRange({

FILE: libs/client/shared/src/components/charts/time-series/LoadingChart.tsx
  type Props (line 13) | type Props = {
  function LoadingChart (line 36) | function LoadingChart({ margin, animate = true, isError = false, renderO...

FILE: libs/client/shared/src/components/charts/time-series/MultiColorGradient.tsx
  type Props (line 7) | type Props = {
  function MultiColorGradient (line 13) | function MultiColorGradient({ id, dataKey, accessorFn }: Props) {

FILE: libs/client/shared/src/components/charts/time-series/PlusCircleGlyph.tsx
  type Props (line 7) | interface Props extends SVGProps<SVGGElement> {
  function PlusCircleGlyph (line 12) | function PlusCircleGlyph({ left, top, ...rest }: Props) {

FILE: libs/client/shared/src/components/charts/time-series/ZeroPointGradient.tsx
  type Props (line 4) | type Props = {
  function ZeroPointGradient (line 10) | function ZeroPointGradient({ id, opacity }: Props) {

FILE: libs/client/shared/src/components/charts/time-series/types.ts
  type Spacing (line 14) | type Spacing = {
  type Datum (line 21) | type Datum = Record<string, any>
  type TSeriesDatum (line 23) | type TSeriesDatum<TDatum extends Datum = any> = {
  type TSeriesDatumEnhanced (line 28) | type TSeriesDatumEnhanced<TDatum extends Datum = any> = TSeriesDatum<TDa...
  type AccessorFn (line 32) | type AccessorFn<TDatum extends Datum, TValue = number> = (
  type Series (line 36) | type Series<TDatum extends Datum = any, TValue = number> = {
  type SeriesEnhanced (line 49) | type SeriesEnhanced<TDatum extends Datum = any> = O.Required<
  type SeriesDatum (line 54) | type SeriesDatum = Omit<Series, 'color'> & { color: string } & {
  type TooltipOptions (line 59) | type TooltipOptions = {
  type ValidXScaleTypes (line 76) | type ValidXScaleTypes = ScaleTypeToD3Scale<number>['utc']
  type ValidYScaleTypes (line 77) | type ValidYScaleTypes = ScaleTypeToD3Scale<number>['linear']
  type ChartData (line 79) | type ChartData<TDatum extends Datum> =
  type ChartDataEnhanced (line 83) | type ChartDataEnhanced<TDatum extends Datum> =
  type RenderOverlay (line 87) | type RenderOverlay = () => ReactNode
  type ChartPropsBase (line 89) | type ChartPropsBase<TDatum extends Datum> = {
  type TooltipSeriesData (line 108) | type TooltipSeriesData<TDatum extends Datum = any> =
  type TooltipData (line 119) | type TooltipData<TDatum extends Datum = any> = {
  type ChartContext (line 126) | type ChartContext<TDatum extends Datum = any> = {
  type TooltipContext (line 138) | type TooltipContext<TDatum extends Datum = any> = {
  type ChartDataContext (line 145) | type ChartDataContext<TDatum extends Datum = any> = ChartContext<TDatum> &
  type ChartProps (line 148) | type ChartProps<TDatum extends Datum> = WithChildrenRenderProps<

FILE: libs/client/shared/src/components/charts/time-series/useSeries.ts
  function useSeries (line 7) | function useSeries(seriesKey: string) {

FILE: libs/client/shared/src/components/charts/time-series/useTooltip.ts
  function getClosestDatum (line 15) | function getClosestDatum(data: TSeriesDatumEnhanced[], date: Date) {
  function useTooltip (line 23) | function useTooltip(

FILE: libs/client/shared/src/components/dialogs/NonUSDDialog.tsx
  type NonUSDDialogProps (line 3) | interface NonUSDDialogProps {
  function NonUSDDialog (line 8) | function NonUSDDialog({ isOpen, onClose }: NonUSDDialogProps) {

FILE: libs/client/shared/src/components/explainers/ExplainerExternalLink.tsx
  type ExplainerExternalLinkProps (line 5) | type ExplainerExternalLinkProps = {
  function ExplainerExternalLink (line 11) | function ExplainerExternalLink({

FILE: libs/client/shared/src/components/explainers/ExplainerInfoBlock.tsx
  type ExplainerInfoBlockProps (line 3) | type ExplainerInfoBlockProps = {
  function ExplainerInfoBlock (line 8) | function ExplainerInfoBlock({ title, children }: ExplainerInfoBlockProps...

FILE: libs/client/shared/src/components/explainers/ExplainerPerformanceBlock.tsx
  type ExplainerPerformanceBlockProps (line 19) | type ExplainerPerformanceBlockProps = {
  function ExplainerPerformanceBlock (line 24) | function ExplainerPerformanceBlock({

FILE: libs/client/shared/src/components/explainers/ExplainerSection.tsx
  type ExplainerSectionProps (line 5) | type ExplainerSectionProps = {
  function ExplainerSection (line 11) | function ExplainerSection(

FILE: libs/client/shared/src/components/generic/BoxIcon.tsx
  type BoxIconVariant (line 23) | type BoxIconVariant = keyof typeof Variant
  type BoxIconSize (line 24) | type BoxIconSize = keyof typeof Size
  type BoxIconProps (line 26) | type BoxIconProps = {
  function BoxIcon (line 32) | function BoxIcon({ icon: Icon, size = 'lg', variant = 'cyan' }: BoxIconP...

FILE: libs/client/shared/src/components/generic/Confetti.tsx
  type Particle (line 6) | type Particle = {
  type ConfettiProps (line 18) | type ConfettiProps = {
  function ConfettiBase (line 49) | function ConfettiBase({

FILE: libs/client/shared/src/components/generic/InfiniteScroll.tsx
  type InfiniteScrollProps (line 11) | type InfiniteScrollProps = {

FILE: libs/client/shared/src/components/generic/InsightGroup.tsx
  type InsightCardOption (line 13) | type InsightCardOption = {
  type InsightGroupProps (line 24) | type InsightGroupProps = PropsWithChildren<{
  function InsightGroup (line 30) | function InsightGroup({ id, options, initialInsights, children }: Insigh...
  type InsightCardProps (line 89) | type InsightCardProps = PropsWithChildren<{
  function Card (line 98) | function Card({

FILE: libs/client/shared/src/components/generic/InsightPopout.tsx
  type InsightPopoutProps (line 6) | type InsightPopoutProps = {
  function InsightPopout (line 10) | function InsightPopout({ children }: InsightPopoutProps) {

FILE: libs/client/shared/src/components/generic/ProfileCircle.tsx
  type ProfileCircleProps (line 13) | type ProfileCircleProps = {
  function ProfileCircle (line 18) | function ProfileCircle({ interactive = true, className }: ProfileCircleP...

FILE: libs/client/shared/src/components/generic/RelativeTime.tsx
  function RelativeTime (line 4) | function RelativeTime({ time }: { time: Date | DateTime }) {

FILE: libs/client/shared/src/components/generic/TakeoverBackground.tsx
  function TakeoverBackground (line 1) | function TakeoverBackground({ className }: { className: string }) {

FILE: libs/client/shared/src/components/generic/Toaster.tsx
  type ToasterProps (line 11) | interface ToasterProps {
  function Toaster (line 16) | function Toaster({ mobile, sidebarOffset }: ToasterProps) {

FILE: libs/client/shared/src/components/generic/TrendBadge.tsx
  type TrendBadgeProps (line 6) | type TrendBadgeProps = {
  function TrendBadge (line 34) | function TrendBadge({

FILE: libs/client/shared/src/components/generic/small-decimals/SmallDecimals.tsx
  type SmallDecimalsProps (line 1) | type SmallDecimalsProps = {

FILE: libs/client/shared/src/components/loaders/MainContentLoader.tsx
  type MainContentLoaderProps (line 4) | interface MainContentLoaderProps {
  function MainContentLoader (line 8) | function MainContentLoader({ message }: MainContentLoaderProps) {

FILE: libs/client/shared/src/components/overlays/BlurredContentOverlay.tsx
  type BlurredContentOverlayProps (line 7) | type BlurredContentOverlayProps = PropsWithChildren<{
  function BlurredContentOverlay (line 13) | function BlurredContentOverlay({

FILE: libs/client/shared/src/components/overlays/ErrorFallbackOverlay.tsx
  function ErrorFallback (line 5) | function ErrorFallback({ resetErrorBoundary: _ }: FallbackProps) {

FILE: libs/client/shared/src/components/overlays/MainContentOverlay.tsx
  type MainContentOverlayProps (line 5) | type MainContentOverlayProps = PropsWithChildren<{
  function MainContentOverlay (line 11) | function MainContentOverlay({

FILE: libs/client/shared/src/components/overlays/Overlay.tsx
  function Overlay (line 5) | function Overlay({ children }: { children: ReactNode }) {

FILE: libs/client/shared/src/components/tables/data-table/DataTable.tsx
  type DataTableProps (line 9) | interface DataTableProps {
  function DataTable (line 22) | function DataTable({

FILE: libs/client/shared/src/components/tables/data-table/DefaultCell.tsx
  function DefaultCell (line 3) | function DefaultCell({ getValue }: CellProps) {

FILE: libs/client/shared/src/components/tables/data-table/EditableBooleanCell.tsx
  type EditableBooleanCellProps (line 3) | type EditableBooleanCellProps = {
  function EditableBooleanCell (line 8) | function EditableBooleanCell({ initialValue, onSubmit }: EditableBoolean...

FILE: libs/client/shared/src/components/tables/data-table/EditableCell.tsx
  function EditableCell (line 8) | function EditableCell({ table, row, column, getValue }: CellProps) {

FILE: libs/client/shared/src/components/tables/data-table/EditableDateCell.tsx
  type EditableDateCellProps (line 9) | type EditableDateCellProps = {
  function EditableDateCell (line 14) | function EditableDateCell({ initialValue, onSubmit }: EditableDateCellPr...

FILE: libs/client/shared/src/components/tables/data-table/EditableDropdownCell.tsx
  type EditableDropdownCellProps (line 8) | type EditableDropdownCellProps = {
  function EditableDropdownCell (line 15) | function EditableDropdownCell({

FILE: libs/client/shared/src/components/tables/data-table/EditableStringCell.tsx
  type EditableStringCellProps (line 4) | type EditableStringCellProps = {
  function EditableStringCell (line 9) | function EditableStringCell({ initialValue, onSubmit }: EditableStringCe...

FILE: libs/client/shared/src/components/tables/data-table/types.ts
  type TableMeta (line 3) | type TableMeta<TData extends {} = any> = {
  type ColumnMeta (line 7) | type ColumnMeta<TData extends {} = any> =
  type CellProps (line 18) | type CellProps = {

FILE: libs/client/shared/src/hooks/useAccountNotifications.ts
  function useAccountNotifications (line 4) | function useAccountNotifications() {

FILE: libs/client/shared/src/hooks/useDebounce.ts
  function useDebounce (line 6) | function useDebounce<T>(value: T, delayMilliseconds: number) {

FILE: libs/client/shared/src/hooks/useFrame.ts
  function useFrame (line 3) | function useFrame(callback: (time: DOMHighResTimeStamp, deltaTime: numbe...

FILE: libs/client/shared/src/hooks/useInterval.ts
  function useInterval (line 3) | function useInterval(callback: () => any, delay?: number | false | null) {

FILE: libs/client/shared/src/hooks/useLocalStorage.ts
  function useLocalStorage (line 4) | function useLocalStorage<T>(key: string, initialValue: T): [T, Dispatch<...

FILE: libs/client/shared/src/hooks/useModalManager.ts
  type ModalKey (line 3) | type ModalKey = 'linkAccounts'
  type ModalManagerAction (line 4) | type ModalManagerAction =
  type ModalManagerContext (line 7) | type ModalManagerContext = {
  function useModalManager (line 12) | function useModalManager() {

FILE: libs/client/shared/src/hooks/useProviderStatus.ts
  function useProviderStatus (line 3) | function useProviderStatus() {

FILE: libs/client/shared/src/hooks/useQueryParam.ts
  function useQueryParam (line 9) | function useQueryParam(

FILE: libs/client/shared/src/hooks/useScreenSize.ts
  type SCREEN (line 4) | enum SCREEN {

FILE: libs/client/shared/src/hooks/useTeller.ts
  type TellerEnvironment (line 14) | type TellerEnvironment = 'sandbox' | 'development' | 'production' | unde...
  type TellerAccountSelection (line 15) | type TellerAccountSelection = 'disabled' | 'single' | 'multiple' | undef...
  constant TC_JS (line 16) | const TC_JS = 'https://cdn.teller.io/connect/connect.js'
  type ManagerState (line 134) | interface ManagerState {

FILE: libs/client/shared/src/providers/AccountContextProvider.tsx
  type AccountValuationFields (line 8) | type AccountValuationFields = {
  type StockValuationFields (line 15) | type StockValuationFields = {
  type StockMetadataValues (line 21) | type StockMetadataValues = {
  type UpdateStockFields (line 26) | type UpdateStockFields = StockMetadataValues & StockValuationFields
  type PropertyMetadataValues (line 29) | type PropertyMetadataValues = {
  type CreatePropertyFields (line 36) | type CreatePropertyFields = PropertyMetadataValues & AccountValuationFields
  type UpdatePropertyFields (line 37) | type UpdatePropertyFields = PropertyMetadataValues
  type VehicleValues (line 40) | type VehicleValues = { make: string; model: string; year: string }
  type CreateVehicleFields (line 42) | type CreateVehicleFields = VehicleValues & AccountValuationFields
  type UpdateVehicleFields (line 43) | type UpdateVehicleFields = VehicleValues
  type AssetValues (line 46) | type AssetValues = { name: string; categoryUser: AccountCategory }
  type CreateAssetFields (line 47) | type CreateAssetFields = AssetValues & AccountValuationFields
  type UpdateAssetFields (line 48) | type UpdateAssetFields = AssetValues
  type LiabilityValues (line 51) | type LiabilityValues = { name: string; categoryUser: AccountCategory }
  type LoanValues (line 52) | type LoanValues = {
  type CreateLiabilityFields (line 59) | type CreateLiabilityFields = LiabilityValues & LoanValues & AccountValua...
  type UpdateLiabilityFields (line 60) | type UpdateLiabilityFields = CreateLiabilityFields
  type AccountManager (line 62) | type AccountManager =
  type AccountContext (line 76) | interface AccountContext {
  function useAccountContext (line 88) | function useAccountContext() {
  function AccountContextProvider (line 98) | function AccountContextProvider({ children }: PropsWithChildren<{}>) {

FILE: libs/client/shared/src/providers/AxiosProvider.tsx
  type CreateInstanceOptions (line 7) | type CreateInstanceOptions = {
  type AxiosContextValue (line 14) | type AxiosContextValue = {
  function createInstance (line 23) | function createInstance(options?: CreateInstanceOptions) {
  function AxiosProvider (line 70) | function AxiosProvider({ children, baseUrl }: PropsWithChildren<{ baseUr...

FILE: libs/client/shared/src/providers/LayoutContextProvider.tsx
  function useLayoutContext (line 8) | function useLayoutContext() {
  function LayoutContextProvider (line 12) | function LayoutContextProvider({

FILE: libs/client/shared/src/providers/LogProvider.tsx
  type Logger (line 4) | type Logger = Pick<Console, 'log' | 'info' | 'error' | 'warn' | 'debug'>
  function LogProvider (line 8) | function LogProvider({ logger, children }: PropsWithChildren<{ logger: L...

FILE: libs/client/shared/src/providers/PopoutProvider.tsx
  type PopoutContext (line 4) | interface PopoutContext {
  function usePopoutContext (line 12) | function usePopoutContext() {
  function PopoutProvider (line 20) | function PopoutProvider({ children }: PropsWithChildren<{}>) {

FILE: libs/client/shared/src/providers/QueryProvider.tsx
  type QueryClientProviderProps (line 6) | interface QueryClientProviderProps {
  function QueryProvider (line 38) | function QueryProvider({ children }: QueryClientProviderProps) {

FILE: libs/client/shared/src/providers/UserAccountContextProvider.tsx
  type UserAccountContext (line 11) | interface UserAccountContext {
  function useUserAccountContext (line 27) | function useUserAccountContext() {
  function UserAccountContextProvider (line 37) | function UserAccountContextProvider({ children }: PropsWithChildren<{}>) {

FILE: libs/client/shared/src/types/client-side-feature-flags.ts
  type MetricStatus (line 1) | type MetricStatus = 'coming-soon' | 'under-construction' | 'active'

FILE: libs/client/shared/src/types/react-types.ts
  type WithChildrenRenderProps (line 3) | type WithChildrenRenderProps<Props, RenderProps> = Props & {

FILE: libs/client/shared/src/utils/account-utils.ts
  function getCategoryColorClassName (line 17) | function getCategoryColorClassName(category: AccountCategory) {
  function getCategoryIcon (line 35) | function getCategoryIcon(category: AccountCategory) {
  function invalidateAccountQueries (line 56) | function invalidateAccountQueries(queryClient: QueryClient, aggregates =...
  function formatLoanTerm (line 66) | function formatLoanTerm({

FILE: libs/client/shared/src/utils/browser-utils.ts
  function copyToClipboard (line 1) | async function copyToClipboard(text: string) {
  function getLocalStorageSession (line 9) | function getLocalStorageSession<TData>(key: string, initialValue: TData) {

FILE: libs/client/shared/src/utils/form-utils.ts
  type ValidateFormDateOpts (line 7) | type ValidateFormDateOpts = {
  function validateFormDate (line 13) | function validateFormDate(date: string | null, opts?: ValidateFormDateOp...

FILE: libs/client/shared/src/utils/image-loaders.ts
  function isJSON (line 3) | function isJSON(str: string): boolean {
  function enhancerizerLoader (line 12) | function enhancerizerLoader({ src, width }: ImageLoaderProps): string {

FILE: libs/design-system/docs/util/Swatch.tsx
  type SwatchProps (line 4) | interface SwatchProps {
  function Swatch (line 9) | function Swatch({ color, className }: SwatchProps): JSX.Element {

FILE: libs/design-system/docs/util/SwatchGroup.tsx
  type SwatchGroupProps (line 3) | interface SwatchGroupProps {
  function SwatchGroup (line 9) | function SwatchGroup({ heading, description, children }: SwatchGroupProp...

FILE: libs/design-system/src/lib/AccordionRow/AccordionRow.tsx
  type AccordionRowProps (line 14) | interface AccordionRowProps extends HTMLAttributes<HTMLElement> {
  function AccordionRow (line 45) | function AccordionRow({

FILE: libs/design-system/src/lib/Alert/Alert.tsx
  type AlertVariant (line 11) | type AlertVariant = 'info' | 'error' | 'success'
  type AlertProps (line 25) | interface AlertProps {
  function Alert (line 39) | function Alert({

FILE: libs/design-system/src/lib/Badge/Badge.tsx
  type BadgeVariant (line 31) | type BadgeVariant = keyof typeof BadgeVariants
  type BadgeProps (line 38) | interface BadgeProps extends HTMLAttributes<HTMLElement> {
  function Badge (line 57) | function Badge({

FILE: libs/design-system/src/lib/Breadcrumb/Breadcrumb.tsx
  type BreadcrumbProps (line 7) | interface BreadcrumbProps {
  function Breadcrumb (line 13) | function Breadcrumb({ href, className, children }: BreadcrumbProps): JSX...
  type BreadcrumbGroupProps (line 26) | interface BreadcrumbGroupProps extends HTMLAttributes<HTMLDivElement> {
  function Group (line 31) | function Group({ className, children, ...rest }: BreadcrumbGroupProps): ...

FILE: libs/design-system/src/lib/Button/Button.tsx
  type ButtonVariant (line 18) | type ButtonVariant = keyof typeof ButtonVariants
  type ButtonProps (line 20) | type ButtonProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, '...
  function Button (line 51) | function Button(
  type SpinnerProps (line 100) | interface SpinnerProps {
  function Spinner (line 104) | function Spinner({ fill }: SpinnerProps): JSX.Element {

FILE: libs/design-system/src/lib/Checkbox/Checkbox.tsx
  type CheckboxProps (line 5) | interface CheckboxProps {
  function Checkbox (line 15) | function Checkbox({

FILE: libs/design-system/src/lib/DatePicker/DatePicker.tsx
  constant INPUT_DATE_FORMAT (line 14) | const INPUT_DATE_FORMAT = 'MM / dd / yyyy'
  type DatePickerProps (line 16) | interface DatePickerProps {
  function toFormattedStr (line 30) | function toFormattedStr(date: string | null) {
  function DatePicker (line 35) | function DatePicker(

FILE: libs/design-system/src/lib/DatePicker/DatePickerCalendar.tsx
  type DatePickerCalendarProps (line 10) | interface DatePickerCalendarProps {
  function DatePickerCalendar (line 18) | function DatePickerCalendar({

FILE: libs/design-system/src/lib/DatePicker/DatePickerInput.tsx
  type DatePickerInput (line 6) | interface DatePickerInput {
  function DatePickerInput (line 17) | function DatePickerInput({

FILE: libs/design-system/src/lib/DatePicker/DatePickerMonth.tsx
  type DatePickerMonthProps (line 7) | interface DatePickerMonthProps {
  function DatePickerMonth (line 14) | function DatePickerMonth({

FILE: libs/design-system/src/lib/DatePicker/DatePickerQuickSelect.tsx
  type DatePickerQuickSelectProps (line 7) | interface DatePickerQuickSelectProps {
  function DatePickerQuickSelect (line 13) | function DatePickerQuickSelect({ ranges, value, onChange }: DatePickerQu...

FILE: libs/design-system/src/lib/DatePicker/DatePickerRange/DatePickerRange.tsx
  type DatePickerRangeProps (line 18) | interface DatePickerRangeProps {
  function DatePickerRange (line 30) | function DatePickerRange({

FILE: libs/design-system/src/lib/DatePicker/DatePickerRange/DatePickerRangeButton.tsx
  type DatePickerRangeButtonProps (line 6) | interface DatePickerRangeButtonProps {
  function DatePickerRangeButton (line 12) | function DatePickerRangeButton({

FILE: libs/design-system/src/lib/DatePicker/DatePickerRange/DatePickerRangeCalendar.tsx
  type DatePickerRangeCalendarProps (line 12) | interface DatePickerRangeCalendarProps {
  function DatePickerRangeCalendar (line 21) | function DatePickerRangeCalendar({

FILE: libs/design-system/src/lib/DatePicker/DatePickerRange/DatePickerRangeTabs.tsx
  type DatePickerRangeTabsProps (line 8) | type DatePickerRangeTabsProps =
  function DefaultTab (line 24) | function DefaultTab({ value, selected }: { value: string; selected: bool...
  constant NOT_SELECTED_TAB_INDEX (line 37) | const NOT_SELECTED_TAB_INDEX = 999
  function DatePickerRangeTabs (line 40) | function DatePickerRangeTabs(props: DatePickerRangeTabsProps) {

FILE: libs/design-system/src/lib/DatePicker/DatePickerYear.tsx
  type DatePickerYearProps (line 7) | interface DatePickerYearProps {
  function DatePickerYear (line 16) | function DatePickerYear({

FILE: libs/design-system/src/lib/DatePicker/selectableRanges.ts
  type DateRange (line 3) | type DateRange = {
  type SelectableRangeKeys (line 8) | type SelectableRangeKeys =
  type SelectableDateRange (line 22) | type SelectableDateRange = DateRange & {

FILE: libs/design-system/src/lib/DatePicker/utils.tsx
  type DisabledProps (line 4) | type DisabledProps = {
  constant MIN_SUPPORTED_DATE (line 44) | const MIN_SUPPORTED_DATE = DateTime.utc().minus({ years: 30 }).startOf('...
  constant MAX_SUPPORTED_DATE (line 45) | const MAX_SUPPORTED_DATE = DateTime.utc().startOf('day')

FILE: libs/design-system/src/lib/Dialog/Dialog.tsx
  type DialogProps (line 16) | interface DialogProps {
  function DialogRoot (line 32) | function DialogRoot({
  type DialogChildProps (line 153) | type DialogChildProps = {
  function Title (line 158) | function Title({ className, children, ...rest }: DialogChildProps) {
  function Content (line 166) | function Content({ className, children, ...rest }: DialogChildProps) {
  function Description (line 174) | function Description({ className, children, ...rest }: DialogChildProps) {
  function Actions (line 182) | function Actions({ className, children, ...rest }: DialogChildProps) {

FILE: libs/design-system/src/lib/Dialog/DialogV2.tsx
  type ExtractProps (line 7) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  type Size (line 18) | type Size = keyof typeof DialogSize
  type DialogProps (line 20) | type DialogProps = {
  function DialogV2 (line 31) | function DialogV2({

FILE: libs/design-system/src/lib/FormGroup/FormGroup.tsx
  type FormGroupProps (line 4) | interface FormGroupProps {
  function FormGroup (line 9) | function FormGroup({ className, children, ...rest }: FormGroupProps): JS...

FILE: libs/design-system/src/lib/FractionalCircle/FractionalCircle.tsx
  type CircleProps (line 3) | type CircleProps = {
  function Circle (line 11) | function Circle({ radius, stroke, className, percent = 100 }: CircleProp...
  type FractionalCircleProps (line 32) | type FractionalCircleProps = {
  function FractionalCircle (line 58) | function FractionalCircle({

FILE: libs/design-system/src/lib/IndexTabs/IndexTabs.tsx
  type IndexTabsProps (line 7) | interface IndexTabsProps extends HTMLAttributes<HTMLElement> {
  function IndexTabs (line 16) | function IndexTabs({

FILE: libs/design-system/src/lib/Listbox/Listbox.tsx
  type ExtractProps (line 11) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  type ListboxButtonVariant (line 21) | type ListboxButtonVariant = keyof typeof ListboxButtonVariants
  type ListboxButtonProps (line 23) | interface ListboxButtonProps extends React.ButtonHTMLAttributes<HTMLButt...
  function Listbox (line 55) | function Listbox({
  function Button (line 76) | function Button({
  type ListboxOptionsProps (line 155) | type ListboxOptionsProps = ExtractProps<typeof HeadlessListbox.Options>
  function Options (line 157) | function Options({
  type Position (line 212) | type Position = 'left' | 'right'
  type ListboxOptionProps (line 214) | type ListboxOptionProps = {
  function Option (line 220) | function Option({

FILE: libs/design-system/src/lib/LoadingPlaceholder/LoadingPlaceholder.tsx
  function LoadingPlaceholder (line 4) | function LoadingPlaceholder({

FILE: libs/design-system/src/lib/LoadingSpinner/LoadingSpinner.tsx
  type LoadingSpinnerProps (line 5) | interface LoadingSpinnerProps extends React.SVGAttributes<SVGElement> {
  function LoadingSpinner (line 9) | function LoadingSpinner({

FILE: libs/design-system/src/lib/Menu/Menu.tsx
  type ExtractProps (line 10) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  function Menu (line 16) | function Menu({ className, ...rest }: ExtractProps<typeof HeadlessMenu>) {
  function Button (line 26) | function Button({
  type ItemsProps (line 34) | type ItemsProps = ExtractProps<typeof HeadlessMenu.Items>
  function Items (line 36) | function Items({
  type ItemProps (line 89) | type ItemProps<T extends React.ElementType | React.ComponentType> = Prop...
  function Item (line 97) | function Item<T extends React.ElementType | React.ComponentType = 'butto...
  function ItemNextLink (line 156) | function ItemNextLink(props: Omit<ItemProps<typeof NextLink>, 'as'>) {

FILE: libs/design-system/src/lib/Popover/Popover.tsx
  type ExtractProps (line 10) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  function Popover (line 16) | function Popover({ className, ...rest }: ExtractProps<typeof HeadlessPop...
  function Button (line 30) | function Button({
  function PanelButton (line 54) | function PanelButton(
  type PopoverPanelProps (line 60) | type PopoverPanelProps = ExtractProps<typeof HeadlessPopover.Panel>
  function Panel (line 62) | function Panel({

FILE: libs/design-system/src/lib/RTEditor/RTEditor.tsx
  type RTEditorProps (line 14) | type RTEditorProps = {
  function RTEditor (line 20) | function RTEditor({ hideControls = false, editor, className }: RTEditorP...
  function RichTextEditorMenuBar (line 35) | function RichTextEditorMenuBar({ editor }: { editor: Editor | null }) {
  function MenuButton (line 76) | function MenuButton({

FILE: libs/design-system/src/lib/RadioGroup/RadioGroup.tsx
  type ExtractProps (line 5) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  function RadioGroup (line 7) | function RadioGroup(props: ExtractProps<typeof HeadlessRadio>) {
  function RadioOption (line 11) | function RadioOption({

FILE: libs/design-system/src/lib/Slider/Slider.tsx
  type SliderProps (line 23) | type SliderProps = {
  function Slider (line 33) | function Slider({

FILE: libs/design-system/src/lib/Step/Step.tsx
  type ExtractProps (line 8) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  function Step (line 20) | function Step({
  function registerStepReducer (line 98) | function registerStepReducer(state: HTMLElement[], stepElement: HTMLElem...
  function Group (line 106) | function Group({
  function List (line 143) | function List({ className, ...rest }: ExtractProps<typeof HeadlessTab.Li...
  function Panels (line 152) | function Panels({ className, ...rest }: ExtractProps<typeof HeadlessTab....
  function Panel (line 156) | function Panel({ className, ...rest }: ExtractProps<typeof HeadlessTab.P...

FILE: libs/design-system/src/lib/Tab/Tab.tsx
  type ExtractProps (line 5) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  function Tab (line 7) | function Tab({
  function Group (line 33) | function Group(props: ExtractProps<typeof HeadlessTab.Group>): JSX.Eleme...
  function List (line 37) | function List({ className, ...rest }: ExtractProps<typeof HeadlessTab.Li...
  function Panels (line 49) | function Panels({ className, ...rest }: ExtractProps<typeof HeadlessTab....
  function Panel (line 53) | function Panel({ className, ...rest }: ExtractProps<typeof HeadlessTab.P...

FILE: libs/design-system/src/lib/Takeover/Takeover.tsx
  type ExtractProps (line 5) | type ExtractProps<T> = T extends React.ComponentType<infer P> ? P : T
  type TakeoverProps (line 7) | type TakeoverProps = ExtractProps<typeof Dialog> & {
  function Takeover (line 11) | function Takeover({

FILE: libs/design-system/src/lib/Toast/Toast.tsx
  type ToastVariant (line 27) | type ToastVariant = keyof typeof ToastVariants
  type ToastProps (line 29) | interface ToastProps extends HTMLAttributes<HTMLDivElement> {
  function Toast (line 39) | function Toast({ variant = 'info', children, className, ...rest }: Toast...

FILE: libs/design-system/src/lib/Toggle/Toggle.tsx
  type ToggleSize (line 17) | type ToggleSize = keyof typeof ToggleSizes
  type ToggleProps (line 19) | interface ToggleProps {
  function Toggle (line 28) | function Toggle({

FILE: libs/design-system/src/lib/Tooltip/Tooltip.tsx
  type TooltipProps (line 5) | type TooltipProps = TippyProps
  function Tooltip (line 7) | function Tooltip({ content, children, className, ...rest }: TooltipProps) {

FILE: libs/design-system/src/lib/TrendLine/TrendLine.tsx
  constant CIRCLE_RADIUS (line 8) | const CIRCLE_RADIUS = 1
  type TrendLineProps (line 10) | interface TrendLineProps extends React.HTMLAttributes<HTMLDivElement> {
  function TrendLine (line 19) | function TrendLine({

FILE: libs/design-system/src/lib/inputs/Input/Input.tsx
  type InputVariant (line 13) | type InputVariant = keyof typeof InputVariants
  type InputProps (line 15) | interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
  function Input (line 47) | function Input(

FILE: libs/design-system/src/lib/inputs/InputColorHint/InputColorHint.tsx
  type InputColorHintColor (line 14) | type InputColorHintColor = keyof typeof InputColorHintColors
  type InputColorHintProps (line 16) | interface InputColorHintProps extends HTMLAttributes<HTMLSpanElement> {
  function InputColorHint (line 21) | function InputColorHint({

FILE: libs/design-system/src/lib/inputs/InputCurrency/InputCurrency.spec.tsx
  function ControlledInputCurrency (line 5) | function ControlledInputCurrency(props: { [key: string]: unknown }): JSX...

FILE: libs/design-system/src/lib/inputs/InputCurrency/InputCurrency.tsx
  type InputCurrencyProps (line 5) | type InputCurrencyProps = Omit<InputProps, 'value' | 'defaultValue' | 'o...
  function InputCurrency (line 17) | function InputCurrency(

FILE: libs/design-system/src/lib/inputs/InputHint/InputHint.tsx
  type InputHintProps (line 4) | interface InputHintProps {
  function InputHint (line 10) | function InputHint({

FILE: libs/design-system/src/lib/inputs/InputPassword/InputPassword.tsx
  type PasswordValidation (line 15) | interface PasswordValidation {
  type PasswordValidator (line 20) | interface PasswordValidator {
  type InputPasswordProps (line 24) | interface InputPasswordProps extends Omit<InputProps, 'type'> {
  constant COMPLEXITY_SCORE_NAMES (line 41) | const COMPLEXITY_SCORE_NAMES = ['very weak', 'weak', 'fair', 'strong', '...
  function InputPassword (line 48) | function InputPassword({

FILE: libs/server/features/src/account-balance/balance-sync.strategy.ts
  type IBalanceSyncStrategy (line 5) | interface IBalanceSyncStrategy {
  method constructor (line 10) | constructor(protected readonly prisma: PrismaClient) {}
  method syncAccountBalances (line 12) | async syncAccountBalances(account: Account) {
  type IBalanceSyncStrategyFactory (line 28) | interface IBalanceSyncStrategyFactory {
  class BalanceSyncStrategyFactory (line 32) | class BalanceSyncStrategyFactory implements IBalanceSyncStrategyFactory {
    method constructor (line 33) | constructor(private readonly strategies: Record<Account['type'], IBala...
    method for (line 35) | for(account: Account): IBalanceSyncStrategy {

FILE: libs/server/features/src/account-balance/investment-transaction-balance-sync.strategy.ts
  class InvestmentTransactionBalanceSyncStrategy (line 7) | class InvestmentTransactionBalanceSyncStrategy extends BalanceSyncStrate...
    method constructor (line 8) | constructor(private readonly logger: Logger, prisma: PrismaClient) {
    method syncBalances (line 12) | async syncBalances(account: Account, startDate: DateTime) {

FILE: libs/server/features/src/account-balance/loan-balance-sync.strategy.ts
  class LoanBalanceSyncStrategy (line 7) | class LoanBalanceSyncStrategy extends BalanceSyncStrategyBase {
    method constructor (line 8) | constructor(private readonly logger: Logger, prisma: PrismaClient) {
    method syncBalances (line 12) | async syncBalances(account: Account, startDate: DateTime) {

FILE: libs/server/features/src/account-balance/transaction-balance-sync.strategy.ts
  class TransactionBalanceSyncStrategy (line 6) | class TransactionBalanceSyncStrategy extends BalanceSyncStrategyBase {
    method constructor (line 7) | constructor(private readonly logger: Logger, prisma: PrismaClient) {
    method syncBalances (line 11) | async syncBalances(account: Account, startDate: DateTime) {

FILE: libs/server/features/src/account-balance/valuation-balance-sync.strategy.ts
  class ValuationBalanceSyncStrategy (line 6) | class ValuationBalanceSyncStrategy extends BalanceSyncStrategyBase {
    method constructor (line 7) | constructor(private readonly logger: Logger, prisma: PrismaClient) {
    method syncBalances (line 11) | async syncBalances(account: Account, startDate: DateTime) {

FILE: libs/server/features/src/account-connection/account-connection.processor.ts
  type IAccountConnectionProcessor (line 11) | interface IAccountConnectionProcessor {
  class AccountConnectionProcessor (line 18) | class AccountConnectionProcessor implements IAccountConnectionProcessor {
    method constructor (line 19) | constructor(
    method sync (line 26) | async sync(

FILE: libs/server/features/src/account-connection/account-connection.provider.ts
  type AccountConnectionSyncEvent (line 4) | type AccountConnectionSyncEvent = { type: 'error'; error: unknown } | { ...
  type IAccountConnectionProvider (line 6) | interface IAccountConnectionProvider {
  type IAccountConnectionProviderFactory (line 12) | interface IAccountConnectionProviderFactory {
  class AccountConnectionProviderFactory (line 16) | class AccountConnectionProviderFactory implements IAccountConnectionProv...
    method constructor (line 17) | constructor(
    method for (line 21) | for(connection: AccountConnection): IAccountConnectionProvider {

FILE: libs/server/features/src/account-connection/account-connection.service.ts
  type IAccountConnectionService (line 10) | interface IAccountConnectionService {
  class AccountConnectionService (line 25) | class AccountConnectionService implements IAccountConnectionService {
    method constructor (line 26) | constructor(
    method get (line 35) | async get(id: AccountConnection['id']) {
    method getAll (line 42) | async getAll(userId: User['id']) {
    method sync (line 50) | async sync(id: AccountConnection['id'], options?: SyncConnectionOption...
    method syncBalances (line 67) | async syncBalances(id: AccountConnection['id']) {
    method syncSecurities (line 83) | async syncSecurities(id: AccountConnection['id']) {
    method disconnect (line 140) | async disconnect(id: AccountConnection['id']) {
    method reconnect (line 163) | async reconnect(id: AccountConnection['id']) {
    method update (line 186) | async update(id: AccountConnection['id'], data: Prisma.AccountConnecti...
    method delete (line 193) | async delete(id: AccountConnection['id']) {

FILE: libs/server/features/src/account/account-query.service.ts
  type PaginationOptions (line 17) | type PaginationOptions = { page: number; pageSize: number }
  type ValuationTrend (line 19) | type ValuationTrend = {
  type BalanceSeries (line 29) | type BalanceSeries = {
  type ReturnSeries (line 35) | type ReturnSeries = {
  type NetWorthSeries (line 43) | type NetWorthSeries = {
  type AccountRollup (line 51) | type AccountRollup = {
  type IAccountQueryService (line 67) | interface IAccountQueryService {
  class AccountQueryService (line 109) | class AccountQueryService implements IAccountQueryService {
    method constructor (line 110) | constructor(private readonly logger: Logger, private readonly pg: PgSe...
    method getHoldingsEnriched (line 112) | async getHoldingsEnriched(accountId: Account['id'], { page, pageSize }...
    method getValuationTrends (line 152) | async getValuationTrends(accountId: Account['id'], start?: DateTime, e...
    method getReturnSeries (line 216) | async getReturnSeries(accountId: Account['id'], start: string, end: st...
    method getBalanceSeries (line 297) | async getBalanceSeries(
    method getNetWorthSeries (line 331) | async getNetWorthSeries(
    method getRollup (line 440) | async getRollup(

FILE: libs/server/features/src/account/account.processor.ts
  type IAccountProcessor (line 8) | interface IAccountProcessor {
  class AccountProcessor (line 12) | class AccountProcessor implements IAccountProcessor {
    method constructor (line 13) | constructor(
    method sync (line 19) | async sync(jobData: SyncAccountQueueJobData) {

FILE: libs/server/features/src/account/account.provider.ts
  type IAccountProvider (line 4) | interface IAccountProvider {
  class NoOpAccountProvider (line 9) | class NoOpAccountProvider implements IAccountProvider {
    method sync (line 10) | sync(_account: Account) {
    method delete (line 14) | delete(_account: Account) {
  type IAccountProviderFactory (line 19) | interface IAccountProviderFactory {
  class AccountProviderFactory (line 23) | class AccountProviderFactory implements IAccountProviderFactory {
    method constructor (line 24) | constructor(
    method for (line 28) | for(account: Account): IAccountProvider {

FILE: libs/server/features/src/account/account.service.ts
  type IAccountService (line 19) | interface IAccountService {
  class AccountService (line 38) | class AccountService implements IAccountService {
    method constructor (line 39) | constructor(
    method get (line 48) | async get(id: Account['id']) {
    method getAll (line 60) | async getAll(userId: User['id']): Promise<SharedType.AccountsResponse> {
    method getAccountDetails (line 101) | async getAccountDetails(id: Account['id']) {
    method create (line 125) | async create(
    method update (line 137) | async update(id: Account['id'], data: Prisma.AccountUncheckedUpdateInp...
    method sync (line 145) | async sync(id: Account['id']) {
    method syncBalances (line 151) | async syncBalances(id: Account['id']) {
    method delete (line 162) | async delete(id: Account['id']) {
    method getTransactions (line 166) | async getTransactions(accountId: Account['id'], page = 0, start?: Date...
    method getHoldings (line 197) | async getHoldings(
    method getInvestmentTransactions (line 234) | async getInvestmentTransactions(
    method getBalance (line 273) | async getBalance(
    method getBalances (line 285) | async getBalances(
    method getReturns (line 315) | async getReturns(
    method getAccountRollup (line 339) | async getAccountRollup(
    method getOldestBalanceDate (line 423) | private async getOldestBalanceDate(accountId: Account['id']): Promise<...

FILE: libs/server/features/src/account/insight.service.ts
  type UserInsightOptions (line 16) | type UserInsightOptions = {
  type AccountInsightOptions (line 22) | type AccountInsightOptions = {
  type HoldingInsightOptions (line 27) | type HoldingInsightOptions = {
  type PlanInsightOptions (line 32) | type PlanInsightOptions = {
  type IInsightService (line 37) | interface IInsightService {
  class InsightService (line 44) | class InsightService implements IInsightService {
    method constructor (line 45) | constructor(private readonly logger: Logger, private readonly prisma: ...
    method getUserInsights (line 47) | async getUserInsights({
    method getAccountInsights (line 227) | async getAccountInsights({
    method getHoldingInsights (line 295) | async getHoldingInsights({
    method getPlanInsights (line 337) | async getPlanInsights({ userId, now = DateTime.utc() }: PlanInsightOpt...
    method _accountSummary (line 377) | private _accountSummary(accountIds: Prisma.Sql | number[], now: DateTi...
    method _assetSummary (line 460) | private _assetSummary(accountIds: Prisma.Sql | number[], now: DateTime) {
    method _transactionSummary (line 541) | private _transactionSummary(accountIds: Prisma.Sql | number[], now: Da...
    method _holdingSummary (line 606) | private _holdingSummary(accountId: Account['id']) {
    method _holdingBreakdown (line 650) | private _holdingBreakdown(accountIds: Prisma.Sql | number[]) {
    method _investmentTransactionSummary (line 704) | private _investmentTransactionSummary(accountId: Account['id'], now: D...
    method _portfolioReturn (line 735) | private _portfolioReturn(accountId: Account['id'], now: DateTime) {
    method _projectionAssetBreakdown (line 768) | private _projectionAssetBreakdown(accountIds: Prisma.Sql, now: DateTim...
    method _projectionLiabilityBreakdown (line 833) | private _projectionLiabilityBreakdown(accountIds: Prisma.Sql, now: Dat...

FILE: libs/server/features/src/auth-user/auth-user.service.ts
  type IAuthUserService (line 5) | interface IAuthUserService {
  class AuthUserService (line 10) | class AuthUserService implements IAuthUserService {
    method constructor (line 11) | constructor(private readonly logger: Logger, private readonly prisma: ...
    method get (line 13) | async get(id: AuthUser['id']) {
    method getByEmail (line 19) | async getByEmail(email: AuthUser['email']) {
    method updatePassword (line 26) | async updatePassword(id: AuthUser['id'], oldPassword: string, newPassw...
    method create (line 40) | async create(data: Prisma.AuthUserCreateInput & { firstName: string; l...
    method delete (line 45) | async delete(id: AuthUser['id']) {

FILE: libs/server/features/src/email/email.processor.ts
  type IEmailProcessor (line 7) | interface IEmailProcessor {
  class EmailProcessor (line 12) | class EmailProcessor implements IEmailProcessor {
    method constructor (line 13) | constructor(
    method send (line 19) | async send(jobData: SendEmailQueueJobData) {
    method sendTrialEndReminders (line 51) | async sendTrialEndReminders() {

FILE: libs/server/features/src/email/email.service.ts
  type IEmailProvider (line 7) | interface IEmailProvider {
  class EmailService (line 24) | class EmailService implements IEmailProvider {
    method constructor (line 26) | constructor(
    method send (line 60) | async send(
    method sendTemplate (line 79) | async sendTemplate(

FILE: libs/server/features/src/email/providers/postmark.provider.ts
  class PostmarkEmailProvider (line 9) | class PostmarkEmailProvider implements IEmailProvider {
    method constructor (line 10) | constructor(
    method send (line 23) | async send(
    method sendTemplate (line 47) | async sendTemplate(
    method sendEmailWithTemplate (line 67) | private async sendEmailWithTemplate(
    method sendEmail (line 83) | private async sendEmail(message: Message): Promise<MessageSendingRespo...
    method sendEmailBatchWithTemplate (line 97) | private async sendEmailBatchWithTemplate(
    method sendEmailBatch (line 119) | private async sendEmailBatch(messages: Message[]): Promise<MessageSend...

FILE: libs/server/features/src/email/providers/smtp.provider.ts
  type NodemailerMessage (line 7) | type NodemailerMessage = {
  class SmtpProvider (line 19) | class SmtpProvider implements IEmailProvider {
    method constructor (line 20) | constructor(
    method send (line 34) | async send(
    method sendEmail (line 51) | private async sendEmail(message: NodemailerMessage): Promise<void> {
    method sendEmailBatch (line 65) | private async sendEmailBatch(messages: NodemailerMessage[]): Promise<S...

FILE: libs/server/features/src/holding/holding.service.ts
  class HoldingService (line 7) | class HoldingService {
    method constructor (line 8) | constructor(private readonly logger: Logger, private readonly prisma: ...
    method get (line 10) | async get(id: Holding['id']) {
    method getHoldingDetails (line 17) | async getHoldingDetails(id: Holding['id']): Promise<SharedType.Account...
    method update (line 63) | async update(id: Holding['id'], data: Prisma.HoldingUncheckedUpdateInp...

FILE: libs/server/features/src/institution/institution.provider.ts
  type IInstitutionProvider (line 3) | interface IInstitutionProvider {
  type IInstitutionProviderFactory (line 7) | interface IInstitutionProviderFactory {
  class InstitutionProviderFactory (line 11) | class InstitutionProviderFactory implements IInstitutionProviderFactory {
    method constructor (line 12) | constructor(private readonly providers: Record<Provider, IInstitutionP...
    method for (line 14) | for(p: Provider): IInstitutionProvider {

FILE: libs/server/features/src/institution/institution.service.ts
  type IInstitutionService (line 10) | interface IInstitutionService {
  class InstitutionService (line 16) | class InstitutionService implements IInstitutionService {
    method constructor (line 17) | constructor(
    method getAll (line 24) | async getAll({
    method sync (line 189) | async sync(provider: Provider) {
    method deduplicateInstitutions (line 234) | async deduplicateInstitutions() {

FILE: libs/server/features/src/plan/plan.schema.ts
  type RetirementTemplate (line 27) | type RetirementTemplate = z.infer<typeof RetirementTemplateSchema>
  type PlanTemplate (line 28) | type PlanTemplate = z.infer<typeof PlanTemplateSchema>

FILE: libs/server/features/src/plan/plan.service.ts
  constant PERCENTILES (line 13) | const PERCENTILES: Decimal[] = ['0.1', '0.9'].map((p) => new Decimal(p))
  constant MONTE_CARLO_N (line 14) | const MONTE_CARLO_N = 1_000
  type PlanWithEventsMilestones (line 16) | type PlanWithEventsMilestones = Plan & { events: PlanEvent[]; milestones...
  type PlanWithEventsMilestonesUser (line 17) | type PlanWithEventsMilestonesUser = PlanWithEventsMilestones & { user: U...
  type ValueRefMap (line 19) | type ValueRefMap = Record<string, Prisma.Decimal>
  function resolveValueRef (line 21) | function resolveValueRef(valueRef: string, valueRefMap: ValueRefMap): Pr...
  function yearToDate (line 25) | function yearToDate(year: number) {
  constant PROJECTION_ASSET_PARAMS (line 32) | const PROJECTION_ASSET_PARAMS: {
  type IPlanService (line 43) | interface IPlanService {
  class PlanService (line 58) | class PlanService implements IPlanService {
    method constructor (line 59) | constructor(
    method get (line 65) | async get(id: Plan['id']): Promise<SharedType.Plan> {
    method getAll (line 78) | async getAll(userId: User['id']): Promise<SharedType.PlansResponse> {
    method create (line 99) | async create(data: Prisma.PlanUncheckedCreateInput) {
    method createWithTemplate (line 105) | async createWithTemplate(user: User, template: PlanTemplate) {
    method update (line 117) | async update(id: Plan['id'], data: Prisma.PlanUncheckedUpdateInput) {
    method updateWithTemplate (line 131) | async updateWithTemplate(planId: Plan['id'], template: PlanTemplate, r...
    method delete (line 147) | async delete(id: Plan['id']) {
    method projections (line 151) | async projections(id: Plan['id']) {
    method _connectTemplate (line 205) | private async _connectTemplate(
    method _connectRetirementTemplate (line 237) | private async _connectRetirementTemplate(
    method _toProjectionInput (line 312) | private _toProjectionInput(
    method _toValueRefMap (line 382) | private _toValueRefMap(insights: SharedType.PlanInsights): ValueRefMap {
    method _getValueRefMap (line 389) | private async _getValueRefMap(userId: User['id']): Promise<ValueRefMap> {
    method _mapToSharedPlan (line 397) | private _mapToSharedPlan(
    method _mapToProjectionTimeSeries (line 415) | private _mapToProjectionTimeSeries(
    method _mapToSimulationTimeSeries (line 449) | private _mapToSimulationTimeSeries(

FILE: libs/server/features/src/plan/projection/monte-carlo.ts
  type MonteCarloOptions (line 3) | type MonteCarloOptions = {
  function monteCarlo (line 7) | function monteCarlo<T>(

FILE: libs/server/features/src/plan/projection/projection-calculator.spec.ts
  method toEqualDecimal (line 7) | toEqualDecimal(
  type CustomMatchers (line 23) | interface CustomMatchers<R = unknown> {
  type Expect (line 30) | interface Expect extends CustomMatchers {}
  type Matchers (line 31) | interface Matchers<R> extends CustomMatchers<R> {}
  type InverseAsymmetricMatchers (line 32) | interface InverseAsymmetricMatchers extends CustomMatchers {}

FILE: libs/server/features/src/plan/projection/projection-calculator.ts
  type ProjectionAsset (line 7) | type ProjectionAsset = {
  type ProjectionLiability (line 12) | type ProjectionLiability = {
  type ProjectionMilestone (line 17) | type ProjectionMilestone = {
  type ProjectionEvent (line 31) | type ProjectionEvent = {
  type ProjectionInput (line 38) | type ProjectionInput = {
  type ProjectionSeriesData (line 46) | type ProjectionSeriesData = {
  type IProjectionCalculator (line 55) | interface IProjectionCalculator {
  class ProjectionCalculator (line 59) | class ProjectionCalculator implements IProjectionCalculator {
    method calculate (line 60) | calculate(input: ProjectionInput, now = DateTime.now()): ProjectionSer...
    method isActive (line 179) | private isActive(

FILE: libs/server/features/src/plan/projection/projection-value.ts
  type ProjectionValue (line 4) | type ProjectionValue = {
  class AssetValue (line 16) | class AssetValue implements ProjectionValue {
    method constructor (line 26) | constructor(initialValue: Decimal.Value, rate: Decimal.Value = 0, stdd...
    method next (line 32) | next(previousValue: Decimal.Value = this.initialValue): Decimal {

FILE: libs/server/features/src/providers/property/property.service.ts
  type PropertyData (line 7) | type PropertyData = {
  class PropertyService (line 11) | class PropertyService implements IAccountProvider, IETL<Account, Propert...
    method constructor (line 12) | public constructor(private readonly logger: Logger) {}
    method sync (line 14) | async sync(account: Account, _options?: SyncAccountOptions) {
    method delete (line 18) | async delete(_account: Account) {
    method extract (line 22) | async extract(_account: Account) {
    method transform (line 29) | transform(_account: Account, data: PropertyData) {
    method load (line 33) | async load(_account: Account, _data: PropertyData) {

FILE: libs/server/features/src/providers/teller/teller.etl.ts
  type TellerRawData (line 11) | type TellerRawData = {
  type TellerData (line 17) | type TellerData = {
  type Connection (line 23) | type Connection = Pick<
  class TellerETL (line 62) | class TellerETL implements IETL<Connection, TellerRawData, TellerData> {
    method constructor (line 63) | public constructor(
    method extract (line 73) | async extract(connection: Connection): Promise<TellerRawData> {
    method transform (line 117) | async transform(_connection: Connection, data: TellerData): Promise<Te...
    method load (line 123) | async load(connection: Connection, data: TellerData): Promise<void> {
    method _extractAccounts (line 134) | private async _extractAccounts(accessToken: string) {
    method _loadAccounts (line 139) | private _loadAccounts(connection: Connection, { accounts }: Pick<Telle...
    method _extractTransactions (line 196) | private async _extractTransactions(
    method _loadTransactions (line 227) | private _loadTransactions(

FILE: libs/server/features/src/providers/teller/teller.service.ts
  class TellerService (line 15) | class TellerService implements IAccountConnectionProvider, IInstitutionP...
    method constructor (line 16) | constructor(
    method sync (line 26) | async sync(connection: AccountConnection, options?: SyncConnectionOpti...
    method onSyncEvent (line 32) | async onSyncEvent(connection: AccountConnection, event: AccountConnect...
    method delete (line 61) | async delete(connection: AccountConnection) {
    method getInstitutions (line 82) | async getInstitutions() {
    method handleEnrollment (line 130) | async handleEnrollment(

FILE: libs/server/features/src/providers/teller/teller.webhook.ts
  type ITellerWebhookHandler (line 6) | interface ITellerWebhookHandler {
  class TellerWebhookHandler (line 10) | class TellerWebhookHandler implements ITellerWebhookHandler {
    method constructor (line 11) | constructor(
    method handleWebhook (line 22) | async handleWebhook(data: TellerTypes.WebhookData) {

FILE: libs/server/features/src/providers/vehicle/vehicle.service.ts
  type VehicleData (line 7) | type VehicleData = {
  class VehicleService (line 11) | class VehicleService implements IAccountProvider, IETL<Account, VehicleD...
    method constructor (line 12) | public constructor(private readonly logger: Logger) {}
    method sync (line 14) | async sync(account: Account, _options?: SyncAccountOptions) {
    method delete (line 18) | async delete(_account: Account) {
    method extract (line 25) | async extract(_account: Account) {
    method transform (line 31) | transform(_account: Account, data: VehicleData) {
    method load (line 35) | async load(_account: Account, _data: VehicleData) {

FILE: libs/server/features/src/security-pricing/security-pricing.processor.ts
  type ISecurityPricingProcessor (line 5) | interface ISecurityPricingProcessor {
  class SecurityPricingProcessor (line 10) | class SecurityPricingProcessor implements ISecurityPricingProcessor {
    method constructor (line 11) | constructor(
    method syncAll (line 16) | async syncAll(_jobData?: SyncSecurityQueueJobData) {
    method syncUSStockTickers (line 20) | async syncUSStockTickers(_jobData?: SyncSecurityQueueJobData) {

FILE: libs/server/features/src/security-pricing/security-pricing.service.ts
  type ISecurityPricingService (line 15) | interface ISecurityPricingService {
  class SecurityPricingService (line 24) | class SecurityPricingService implements ISecurityPricingService {
    method constructor (line 25) | constructor(
    method syncSecurity (line 31) | async syncSecurity(
    method syncSecuritiesPricing (line 80) | async syncSecuritiesPricing() {
    method syncUSStockTickers (line 194) | async syncUSStockTickers() {

FILE: libs/server/features/src/stripe/stripe.webhook.ts
  type IStripeWebhookHandler (line 6) | interface IStripeWebhookHandler {
  class StripeWebhookHandler (line 10) | class StripeWebhookHandler implements IStripeWebhookHandler {
    method constructor (line 11) | constructor(
    method handleWebhook (line 17) | async handleWebhook(event: Stripe.Event) {

FILE: libs/server/features/src/transaction/transaction.service.ts
  type TransactionWithConnection (line 7) | type TransactionWithConnection = Transaction & {
  type ITransactionService (line 13) | interface ITransactionService {
  class TransactionService (line 27) | class TransactionService implements ITransactionService {
    method constructor (line 28) | constructor(private readonly logger: Logger, private readonly prisma: ...
    method getAll (line 30) | async getAll(
    method get (line 56) | async get(id: Transaction['id']) {
    method update (line 63) | async update(id: Transaction['id'], data: Prisma.TransactionUncheckedU...
    method markTransfers (line 74) | async markTransfers(

FILE: libs/server/features/src/user/onboarding.service.ts
  type RegisteredStep (line 3) | type RegisteredStep = {
  type OnboardingState (line 9) | type OnboardingState = {
  type CallbackFn (line 16) | type CallbackFn<TData = unknown, T = boolean> = (user: TData, step: Step...
  class Step (line 18) | class Step<TData = unknown> {
    method constructor (line 32) | constructor(readonly key: string) {}
    method addToGroup (line 34) | addToGroup(group: string) {
    method setCTAPath (line 40) | setCTAPath(path: string) {
    method setTitle (line 45) | setTitle(fn: CallbackFn<TData, string>) {
    method completeIf (line 50) | completeIf(fn: CallbackFn<TData>) {
    method markedCompleteIf (line 55) | markedCompleteIf(fn: CallbackFn<TData>) {
    method excludeIf (line 60) | excludeIf(fn: CallbackFn<TData>) {
    method optional (line 65) | optional() {
  class Onboarding (line 71) | class Onboarding<TData = unknown> {
    method constructor (line 74) | constructor(
    method isComplete (line 83) | get isComplete() {
    method isMarkedComplete (line 89) | get isMarkedComplete() {
    method progress (line 94) | get progress() {
    method steps (line 106) | get steps() {
    method currentStep (line 120) | get currentStep() {
    method addStep (line 125) | addStep(key: string) {

FILE: libs/server/features/src/user/user.processor.ts
  type IUserProcessor (line 12) | interface IUserProcessor {
  class UserProcessor (line 17) | class UserProcessor implements IUserProcessor {
    method constructor (line 18) | constructor(
    method sync (line 27) | async sync(jobData: SyncUserQueueJobData) {
    method delete (line 46) | async delete(jobData: SyncUserQueueJobData) {

FILE: libs/server/features/src/user/user.service.ts
  type MainOnboardingUser (line 14) | type MainOnboardingUser = Pick<
  type SidebarOnboardingUser (line 25) | type SidebarOnboardingUser = {
  type IUserService (line 42) | interface IUserService {
  class UserService (line 49) | class UserService implements IUserService {
    method constructor (line 50) | constructor(
    method get (line 60) | async get(id: User['id']) {
    method getAuthProfile (line 66) | async getAuthProfile(id: User['id']): Promise<SharedType.AuthUser> {
    method sync (line 73) | async sync(id: User['id']) {
    method syncBalances (line 79) | async syncBalances(id: User['id']) {
    method update (line 110) | async update(id: User['id'], data: SharedType.UpdateUser) {
    method delete (line 117) | async delete(id: User['id']) {
    method getNetWorth (line 133) | async getNetWorth(
    method getNetWorthSeries (line 142) | async getNetWorthSeries(
    method getOldestBalanceDate (line 172) | private async getOldestBalanceDate(userId: User['id']): Promise<string> {
    method getSubscription (line 195) | async getSubscription(userId: User['id']): Promise<SharedType.UserSubs...
    method getMemberCard (line 231) | async getMemberCard(memberId: string, clientUrl: string) {
    method buildMainOnboarding (line 268) | async buildMainOnboarding(userId: User['id']): Promise<SharedType.Onbo...
    method buildSidebarOnboarding (line 371) | async buildSidebarOnboarding(userId: User['id']): Promise<SharedType.O...

FILE: libs/server/features/src/valuation/valuation.service.ts
  class ValuationService (line 10) | class ValuationService {
    method constructor (line 11) | constructor(
    method getValuations (line 17) | async getValuations(
    method getValuation (line 60) | async getValuation(id: Valuation['id']) {
    method createValuation (line 67) | async createValuation(data: Prisma.ValuationUncheckedCreateInput) {
    method updateValuation (line 71) | async updateValuation(
    method deleteValuation (line 81) | async deleteValuation(id: Valuation['id']) {

FILE: libs/server/shared/src/endpoint.ts
  type EndpointSchema (line 4) | type EndpointSchema<TInput = unknown> = {
  type EndpointResolverArgs (line 8) | type EndpointResolverArgs<TContext, TInput> = {
  type EndpointOnSuccess (line 14) | type EndpointOnSuccess = <TOutput>(req: Request, res: Response, output: ...
  type EndpointWithInput (line 16) | type EndpointWithInput<TContext, TInput, TOutput> = {
  type EndpointWithoutInput (line 23) | type EndpointWithoutInput<TContext, TOutput> = Omit<
  class EndpointFactory (line 28) | class EndpointFactory<TContext> {
    method constructor (line 29) | constructor(
    method create (line 38) | create<TInput, TOutput>(

FILE: libs/server/shared/src/etl.ts
  type IETL (line 1) | interface IETL<TInput, TExtracted = any, TTransformed = TExtracted> {
  function etl (line 7) | async function etl<TInput, TExtracted, TTransformed>(

FILE: libs/server/shared/src/services/cache.service.ts
  type ICacheBackend (line 6) | interface ICacheBackend {
  class MemoryCacheBackend (line 11) | class MemoryCacheBackend implements ICacheBackend {
    method constructor (line 12) | constructor(private readonly cache: Record<string, { value: any; exp: ...
    method getItem (line 14) | async getItem<TValue>(key: string): Promise<TValue | null> {
    method setItem (line 20) | async setItem<TValue>(key: string, value: TValue, exp: Duration): Prom...
  class RedisCacheBackend (line 25) | class RedisCacheBackend implements ICacheBackend {
    method constructor (line 26) | constructor(private readonly redis: Redis) {}
    method getItem (line 28) | async getItem<TValue>(key: string): Promise<TValue | null> {
    method setItem (line 33) | async setItem<TValue>(key: string, value: TValue, exp: Duration): Prom...
    method key (line 37) | private key(key: string) {
  class CacheService (line 42) | class CacheService {
    method constructor (line 43) | constructor(
    method getOrAdd (line 49) | async getOrAdd<K extends string, V>(

FILE: libs/server/shared/src/services/crypto.service.ts
  type ICryptoService (line 3) | interface ICryptoService {
  class CryptoService (line 8) | class CryptoService implements ICryptoService {
    method constructor (line 9) | constructor(private readonly secret: string) {}
    method encrypt (line 11) | encrypt(plainText: string) {
    method decrypt (line 15) | decrypt(encrypted: string) {

FILE: libs/server/shared/src/services/market-data.service.ts
  type DailyPricing (line 15) | type DailyPricing = {
  type TSecurity (line 20) | type TSecurity = Pick<Security, 'assetClass' | 'currencyCode' | 'id' | '...
  type LivePricing (line 22) | type LivePricing<TSecurity> = {
  type EndOfDayPricing (line 33) | type EndOfDayPricing<TSecurity> = {
  type OptionDetails (line 44) | type OptionDetails = {
  type IMarketDataService (line 48) | interface IMarketDataService {
  class PolygonMarketDataService (line 109) | class PolygonMarketDataService implements IMarketDataService {
    method constructor (line 115) | constructor(
    method getDailyPricing (line 123) | async getDailyPricing<
    method getEndOfDayPricing (line 150) | async getEndOfDayPricing<
    method getAllDailyPricing (line 195) | async getAllDailyPricing(): Promise<IAggs> {
    method getLivePricing (line 204) | async getLivePricing<
    method getOptionDetails (line 281) | async getOptionDetails(symbol: Security['symbol']): Promise<OptionDeta...
    method getSecurityDetails (line 300) | async getSecurityDetails(security: Pick<Security, 'assetClass' | 'curr...
    method getUSStockTickers (line 384) | async getUSStockTickers(): Promise<
    method _snapshotStocks (line 449) | private async _snapshotStocks(tickers: string[]) {
    method _snapshotOption (line 510) | private async _snapshotOption(ticker: string) {
    method _snapshotCrypto (line 546) | private async _snapshotCrypto(tickers: string[]) {
  class PolygonTicker (line 605) | class PolygonTicker {
    method constructor (line 606) | constructor(readonly market: 'stocks' | 'options' | 'fx' | 'crypto', r...
    method key (line 608) | get key() {
    method toString (line 613) | toString() {
  function getPolygonTicker (line 618) | function getPolygonTicker({

FILE: libs/server/shared/src/services/pg.service.ts
  class PgService (line 18) | class PgService {
    method constructor (line 21) | constructor(private readonly logger: Logger, databaseUrl = process.env...
    method pool (line 31) | get pool() {

FILE: libs/server/shared/src/services/queue.service.ts
  type IJob (line 6) | type IJob<T> = Pick<Job<T>, 'id' | 'name' | 'data' | 'progress'>
  type IQueue (line 10) | type IQueue<TData extends Record<string, any> = {}, TJobName extends str...
  type SyncUserOptions (line 28) | type SyncUserOptions = {}
  type SyncUserQueueJobData (line 29) | type SyncUserQueueJobData = {
  type SyncAccountOptions (line 34) | type SyncAccountOptions = {}
  type SyncAccountQueueJobData (line 35) | type SyncAccountQueueJobData = {
  type SyncConnectionOptions (line 40) | type SyncConnectionOptions = { type: 'teller'; initialSync?: boolean }
  type SyncConnectionQueueJobData (line 42) | type SyncConnectionQueueJobData = {
  type SyncSecurityQueueJobData (line 47) | type SyncSecurityQueueJobData = {}
  type SendEmailQueueJobData (line 49) | type SendEmailQueueJobData =
  type SyncUserQueue (line 62) | type SyncUserQueue = IQueue<SyncUserQueueJobData, 'sync-user'>
  type SyncAccountQueue (line 63) | type SyncAccountQueue = IQueue<SyncAccountQueueJobData, 'sync-account'>
  type SyncConnectionQueue (line 64) | type SyncConnectionQueue = IQueue<SyncConnectionQueueJobData, 'sync-conn...
  type SyncSecurityQueue (line 65) | type SyncSecurityQueue = IQueue<
  type PurgeUserQueue (line 69) | type PurgeUserQueue = IQueue<{ userId: User['id'] }, 'purge-user'>
  type SyncInstitutionQueue (line 70) | type SyncInstitutionQueue = IQueue<{}, 'sync-teller-institutions'>
  type SendEmailQueue (line 71) | type SendEmailQueue = IQueue<SendEmailQueueJobData, 'send-email'>
  type QueueName (line 73) | type QueueName =
  type IQueueFactory (line 82) | interface IQueueFactory {
  class QueueService (line 93) | class QueueService {
    method constructor (line 96) | constructor(private readonly logger: Logger, private readonly queueFac...
    method allQueues (line 106) | get allQueues() {
    method getQueue (line 117) | getQueue<TData extends Record<string, any> = any>(name: QueueName): IQ...
    method cancelAllJobs (line 121) | async cancelAllJobs() {
    method createQueue (line 125) | private createQueue(name: QueueName) {

FILE: libs/server/shared/src/services/queue/bull-queue.ts
  constant TRACE_ID_KEY (line 7) | const TRACE_ID_KEY = '__SENTRY_TRACE_ID__'
  constant PARENT_SPAN_ID_KEY (line 8) | const PARENT_SPAN_ID_KEY = '__SENTRY_PARENT_SPAN_ID__'
  class BullQueue (line 10) | class BullQueue<TData extends Record<string, any> = any, TJobName extend...
    method constructor (line 13) | constructor(readonly logger: Logger, readonly queue: Queue.Queue<TData...
    method name (line 15) | get name() {
    method isHealthy (line 19) | async isHealthy() {
    method add (line 24) | async add(name: TJobName, data: TData, options?: Queue.JobOptions | un...
    method addBulk (line 54) | async addBulk(jobs: { name: TJobName; data: TData; options?: Queue.Job...
    method process (line 79) | async process(
    method getActiveJobs (line 119) | async getActiveJobs() {
    method getRepeatableJobs (line 123) | async getRepeatableJobs(): Promise<Queue.JobInformation[]> {
    method removeRepeatableByKey (line 127) | async removeRepeatableByKey(key: string) {
    method cancelJobs (line 131) | async cancelJobs() {
    method on (line 146) | on(event: string, callback: (...args: any[]) => void) {
  type IBullQueueEventHandler (line 151) | interface IBullQueueEventHandler {
  class BullQueueFactory (line 160) | class BullQueueFactory implements IQueueFactory {
    method constructor (line 161) | constructor(
    method createQueue (line 167) | createQueue(name: QueueName) {

FILE: libs/server/shared/src/services/queue/in-memory-queue.ts
  class InMemoryQueue (line 8) | class InMemoryQueue<
    method constructor (line 18) | constructor(readonly name: string, private readonly ignoreJobNames: st...
    method isHealthy (line 20) | async isHealthy() {
    method add (line 24) | async add(name: TJobName, data: TData, _options?: JobOptions | undefin...
    method addBulk (line 44) | async addBulk(jobs: { name: TJobName; data: TData; options?: JobOption...
    method process (line 48) | async process(name: TJobName, fn: (job: IJob<TData>) => Promise<void>) {
    method getActiveJobs (line 52) | async getActiveJobs() {
    method getRepeatableJobs (line 56) | async getRepeatableJobs() {
    method removeRepeatableByKey (line 60) | async removeRepeatableByKey(_key: string) {
    method cancelJobs (line 64) | async cancelJobs() {
  class InMemoryQueueFactory (line 69) | class InMemoryQueueFactory implements IQueueFactory {
    method constructor (line 70) | constructor(
    method createQueue (line 79) | createQueue(name: QueueName) {

FILE: libs/server/shared/src/sql-template-tag.ts
  type Value (line 5) | type Value =
  type RawValue (line 15) | type RawValue = Value | Sql
  class Sql (line 20) | class Sql {
    method constructor (line 24) | constructor(rawStrings: ReadonlyArray<string>, rawValues: ReadonlyArra...
    method text (line 78) | get text() {
    method sql (line 82) | get sql() {
    method inspect (line 86) | inspect() {
  function join (line 98) | function join(values: RawValue[], separator = ',') {
  function raw (line 111) | function raw(value: string) {
  function sql (line 123) | function sql(strings: ReadonlyArray<string>, ...values: RawValue[]) {

FILE: libs/server/shared/src/utils/db-utils.ts
  function slowQueryMiddleware (line 7) | function slowQueryMiddleware(logger: Logger, cutoffDuration = 1_000): Pr...
  function toPgInterval (line 32) | function toPgInterval(interval: SharedType.TimeSeriesInterval): string {
  type NumberOrDecimal (line 49) | type NumberOrDecimal = Prisma.Decimal | number
  function getTrendDirection (line 51) | function getTrendDirection(_amount: NumberOrDecimal | null): SharedType....
  function calculateTrend (line 57) | function calculateTrend(_from: NumberOrDecimal, _to: NumberOrDecimal): S...
  function toTrend (line 71) | function toTrend(
  function toDecimal (line 87) | function toDecimal(x?: NumberOrDecimal | null): Prisma.Decimal | null {

FILE: libs/server/shared/src/utils/error-utils.ts
  type PrismaError (line 6) | type PrismaError =
  function isPrismaError (line 14) | function isPrismaError(error: unknown): error is PrismaError {
  function isTellerError (line 24) | function isTellerError(err: unknown): err is SharedType.AxiosTellerError {
  function parseError (line 33) | function parseError(error: unknown): SharedType.ParsedError {
  function parseAxiosError (line 64) | function parseAxiosError(error: AxiosError): SharedType.ParsedError {
  function parseJSError (line 76) | function parseJSError(error: Error): SharedType.ParsedError {
  function parsePrismaError (line 83) | function parsePrismaError(error: PrismaError): SharedType.ParsedError {

FILE: libs/server/shared/src/utils/server-utils.ts
  function redisRetryStrategy (line 4) | function redisRetryStrategy({
  function useSync (line 22) | function useSync<TEntity>({
  function tryCatchElseFinally (line 47) | async function tryCatchElseFinally(
  type SignerConfig (line 72) | type SignerConfig = {

FILE: libs/server/shared/src/utils/teller-utils.ts
  constant TELLER_WINDOW_MAX (line 10) | const TELLER_WINDOW_MAX = Duration.fromObject({ years: 2 })
  function getAccountBalanceData (line 12) | function getAccountBalanceData(
  function getType (line 34) | function getType(type: TellerTypes.AccountTypes): AccountType {
  function tellerTypesToCategory (line 45) | function tellerTypesToCategory(tellerType: TellerTypes.AccountTypes): Ac...

FILE: libs/shared/src/types/account-types.ts
  type Loan (line 35) | type Loan = {
  type Credit (line 43) | type Credit = {
  type AccountSyncProgress (line 52) | type AccountSyncProgress = {
  type AccountDetail (line 57) | type AccountDetail = Omit<Account, 'loan' | 'credit'> & {
  type AccountWithConnection (line 67) | type AccountWithConnection = Account & { accountConnection?: AccountConn...
  type AccountsResponse (line 69) | type AccountsResponse = {
  type PageSize (line 74) | enum PageSize {
  type NormalizedCategory (line 82) | type NormalizedCategory = {
  type ConnectionWithAccounts (line 94) | type ConnectionWithAccounts = AccountConnection & {
  type ConnectionWithSyncProgress (line 98) | type ConnectionWithSyncProgress = AccountConnection & {
  type AccountBalanceTimeSeriesData (line 108) | type AccountBalanceTimeSeriesData = {
  type AccountBalanceResponse (line 113) | type AccountBalanceResponse = TimeSeriesResponseWithDetail<
  type AccountReturnTimeSeriesData (line 117) | type AccountReturnTimeSeriesData = {
  type AccountReturnResponse (line 129) | type AccountReturnResponse = TimeSeries<AccountReturnTimeSeriesData>
  type AccountTransactionResponse (line 131) | type AccountTransactionResponse = {
  type AccountHolding (line 136) | type AccountHolding = Pick<
  type AccountHoldingResponse (line 155) | type AccountHoldingResponse = {
  type AccountInvestmentTransaction (line 160) | type AccountInvestmentTransaction = InvestmentTransaction & { security?:...
  type AccountInvestmentTransactionResponse (line 162) | type AccountInvestmentTransactionResponse = {
  type AccountRollupTimeSeries (line 167) | type AccountRollupTimeSeries = TimeSeries<
  type AccountRollupGroup (line 174) | type AccountRollupGroup<TKey, TItem> = {
  type AccountRollup (line 181) | type AccountRollup = AccountRollupGroup<
  type AccountValuationsResponse (line 193) | type AccountValuationsResponse = {
  type AccountInsights (line 208) | type AccountInsights = {

FILE: libs/shared/src/types/api-types.ts
  type ErrorResponse (line 2) | interface ErrorResponse {
  type SuccessResponse (line 6) | interface SuccessResponse {
  type ApiResponse (line 16) | interface ApiResponse<T = any> {
  type BaseResponse (line 22) | type BaseResponse = SuccessResponse | ErrorResponse

FILE: libs/shared/src/types/email-types.ts
  type EmailCommon (line 4) | type EmailCommon = {
  type EmailTemplate (line 10) | type EmailTemplate = { alias: string; model: Record<string, any> }
  type PlainMessageContent (line 12) | type PlainMessageContent = { subject: string; textBody?: string; htmlBod...
  type PlainEmailMessage (line 14) | type PlainEmailMessage = EmailCommon & PlainMessageContent
  type TemplateEmailMessage (line 15) | type TemplateEmailMessage = EmailCommon & { template: EmailTemplate }
  type EmailSendingResponse (line 16) | type EmailSendingResponse = MessageSendingResponse | SentMessageInfo
  type SendTestEmail (line 18) | type SendTestEmail = {

FILE: libs/shared/src/types/general-types.ts
  type Decimal (line 8) | type Decimal = DecimalJS | Prisma.Decimal
  type DateRange (line 10) | type DateRange<TDate = string> = {
  type TimeSeriesInterval (line 20) | type TimeSeriesInterval = 'days' | 'weeks' | 'months' | 'quarters' | 'ye...
  type TimeSeries (line 22) | type TimeSeries<
  type TimeSeriesResponseWithDetail (line 32) | type TimeSeriesResponseWithDetail<TSeries> = TSeries extends TimeSeries<
  type Trend (line 50) | type Trend = {
  type FormatString (line 56) | type FormatString = 'currency' | 'short-currency' | 'percent' | 'decimal...
  type ParsedError (line 63) | type ParsedError = {
  type AxiosTellerError (line 80) | type AxiosTellerError = O.Required<
  type StatusPageResponse (line 85) | type StatusPageResponse = {

FILE: libs/shared/src/types/holding-types.ts
  type HoldingInsights (line 3) | type HoldingInsights = {
  type HoldingEnriched (line 9) | type HoldingEnriched = Pick<Holding, 'id' | 'quantity' | 'value' | 'excl...

FILE: libs/shared/src/types/institution-types.ts
  type ProviderInstitution (line 6) | type ProviderInstitution = Pick<
  type Institution (line 11) | type Institution = Pick<
  type InstitutionsResponse (line 19) | type InstitutionsResponse = {

FILE: libs/shared/src/types/plan-types.ts
  type PlanEvent (line 10) | type PlanEvent = O.NonNullable<PrismaPlanEvent, 'initialValue'>
  type PlanMilestone (line 11) | type PlanMilestone = PrismaPlanMilestone
  type Plan (line 13) | type Plan = PrismaPlan & {
  type PlansResponse (line 18) | type PlansResponse = {
  type PlanProjectionEvent (line 22) | type PlanProjectionEvent = {
  type PlanProjectionMilestone (line 27) | type PlanProjectionMilestone = PlanMilestone
  type PlanProjectionData (line 29) | type PlanProjectionData = {
  type PlanSimulationData (line 41) | type PlanSimulationData = {
  type PlanProjectionResponse (line 51) | type PlanProjectionResponse = {
  type ProjectionAssetType (line 59) | type ProjectionAssetType =
  type ProjectionLiabilityType (line 66) | type ProjectionLiabilityType = 'credit' | 'loan' | 'other'
  type PlanInsights (line 68) | type PlanInsights = {

FILE: libs/shared/src/types/security-types.ts
  type SecurityWithPricing (line 6) | type SecurityWithPricing = Security & {
  type SecuritySymbolExchange (line 10) | type SecuritySymbolExchange = {
  type SecurityDetails (line 15) | type SecurityDetails = {
  type DailyPricing (line 34) | type DailyPricing = {

FILE: libs/shared/src/types/transaction-types.ts
  type TransactionEnriched (line 13) | type TransactionEnriched = Transaction & {
  type TransactionWithAccountDetail (line 20) | type TransactionWithAccountDetail = Transaction & {
  type TransactionsResponse (line 26) | type TransactionsResponse = {

FILE: libs/shared/src/types/user-types.ts
  type User (line 19) | type User = Omit<PrismaUser, 'riskAnswers'> & { riskAnswers: RiskAnswer[] }
  type UpdateUser (line 20) | type UpdateUser = Partial<
  type NetWorthTimeSeriesData (line 41) | type NetWorthTimeSeriesData = {
  type NetWorthTimeSeriesResponse (line 49) | type NetWorthTimeSeriesResponse = TimeSeriesResponseWithDetail<
  type UserInsights (line 59) | type UserInsights = {
  type Auth0CustomNamespace (line 151) | enum Auth0CustomNamespace {
  type MaybeUserMetadata (line 163) | type MaybeUserMetadata = Partial<{
  type MaybeAppMetadata (line 170) | type MaybeAppMetadata = {}
  type PrimaryAuth0Identity (line 172) | type PrimaryAuth0Identity = Partial<{
  type MaybeCustomClaims (line 179) | type MaybeCustomClaims = {
  type PasswordReset (line 187) | interface PasswordReset {
  type UserSubscription (line 192) | type UserSubscription = {
  type UserMemberCardDetails (line 203) | type UserMemberCardDetails = {
  type RiskQuestionChoice (line 213) | type RiskQuestionChoice = {
  type RiskQuestion (line 219) | type RiskQuestion = {
  type RiskAnswer (line 225) | type RiskAnswer = {
  type OnboardingFlow (line 234) | type OnboardingFlow = 'main' | 'sidebar'
  type OnboardingStep (line 236) | type OnboardingStep = {
  type OnboardingResponse (line 245) | type OnboardingResponse = {

FILE: libs/shared/src/utils/account-utils.ts
  constant ACCOUNT_TYPES (line 7) | const ACCOUNT_TYPES: AccountType[] = [
  constant CATEGORIES (line 18) | const CATEGORIES: Record<AccountCategory, SharedType.NormalizedCategory>...
  constant LIABILITY_CATEGORIES (line 66) | const LIABILITY_CATEGORIES = [CATEGORIES.loan, CATEGORIES.credit, CATEGO...
  constant ASSET_CATEGORIES (line 67) | const ASSET_CATEGORIES = [
  constant CATEGORY_MAP_SIMPLE (line 77) | const CATEGORY_MAP_SIMPLE: Record<AccountType, AccountCategory[]> = {
  constant CATEGORY_MAP (line 88) | const CATEGORY_MAP = mapValues(keyBy(ACCOUNT_TYPES), (accountType) =>
  function getClassification (line 96) | function getClassification(type: AccountType): AccountClassification {
  function groupAccountsByCategory (line 107) | function groupAccountsByCategory<TAccount extends Pick<SharedType.Accoun...
  function getAccountTypeName (line 124) | function getAccountTypeName(category: string, subcategory: string): stri...

FILE: libs/shared/src/utils/date-utils.ts
  function generateDailySeries (line 7) | function generateDailySeries(start: string, end: string, zone = 'utc'): ...
  function isToday (line 15) | function isToday(date: Date | string | null | undefined, today = DateTim...
  function isSameDate (line 20) | function isSameDate(date: DateTime, as: DateTime): boolean {
  function datetimeTransform (line 27) | function datetimeTransform(
  function dateTransform (line 44) | function dateTransform(val: Date | string | null | undefined): string | ...
  function strToDate (line 55) | function strToDate(val: string, zone = 'utc'): Date {
  function dateToStr (line 59) | function dateToStr(val: Date, zone = 'utc'): string {
  function calculateTimeSeriesInterval (line 63) | function calculateTimeSeriesInterval(
  function toD3Interval (line 93) | function toD3Interval(interval: TimeSeriesInterval): NiceTime {
  function yearToAge (line 113) | function yearToAge(year: number, currentAge = 30, currentYear = DateTime...
  function ageToYear (line 120) | function ageToYear(age: number, currentAge = 30, currentYear = DateTime....
  function dobToAge (line 125) | function dobToAge(dob: string | Date | DateTime | null | undefined, now ...
  constant MIN_SUPPORTED_DATE (line 139) | const MIN_SUPPORTED_DATE = DateTime.now().minus({ years: 30 })
  constant MAX_SUPPORTED_DATE (line 140) | const MAX_SUPPORTED_DATE = DateTime.now()

FILE: libs/shared/src/utils/market-utils.ts
  function isOptionTicker (line 3) | function isOptionTicker(ticker: string): boolean {
  function getUnderlyingTicker (line 7) | function getUnderlyingTicker(ticker: string): string | null {

FILE: libs/shared/src/utils/number-utils.ts
  function calculatePercentChange (line 6) | function calculatePercentChange(
  function format (line 24) | function format(
  function sumBy (line 116) | function sumBy<T>(a: T[] | null | undefined, by: (item: T) => DecimalJS)...

FILE: libs/shared/src/utils/plan-utils.ts
  constant DEFAULT_AGE (line 4) | const DEFAULT_AGE = 30
  constant DEFAULT_LIFE_EXPECTANCY (line 5) | const DEFAULT_LIFE_EXPECTANCY = 85
  constant CONFIDENCE_INTERVAL (line 6) | const CONFIDENCE_INTERVAL = 0.9
  constant RETIREMENT_MILESTONE_AGE (line 7) | const RETIREMENT_MILESTONE_AGE = 65
  type PlanEventCategory (line 9) | enum PlanEventCategory {}
  type PlanMilestoneCategory (line 10) | enum PlanMilestoneCategory {
  function resolveMilestoneYear (line 15) | function resolveMilestoneYear(

FILE: libs/shared/src/utils/shared-utils.spec.ts
  method [Symbol.asyncIterator] (line 80) | async *[Symbol.asyncIterator]() {

FILE: libs/shared/src/utils/shared-utils.ts
  function isNull (line 1) | function isNull<T>(value: T | null | undefined): value is null | undefin...
  function nonNull (line 5) | function nonNull<T>(value: T | null | undefined): value is NonNullable<T> {
  function isFullfilled (line 9) | function isFullfilled<T>(p: PromiseSettledResult<T>): p is PromiseFulfil...
  function stringToArray (line 15) | function stringToArray(s: string | null | undefined, sep = ','): string[...
  function paginate (line 22) | async function paginate<TData>({
  function paginateWithNextUrl (line 57) | async function paginateWithNextUrl<TData>({
  function withRetry (line 141) | async function withRetry<TResult>(
  function normalizeUrl (line 184) | function normalizeUrl(url: string) {

FILE: libs/shared/src/utils/stats-utils.ts
  function mean (line 4) | function mean(x: Decimal.Value[]): Decimal {
  function variance (line 9) | function variance(x: Decimal.Value[]): Decimal {
  function stddev (line 14) | function stddev(x: Decimal.Value[]): Decimal {
  function confidenceInterval (line 18) | function confidenceInterval(
  function boxMullerTransform (line 27) | function boxMullerTransform(): [z0: number, z1: number] {
  function randomNormal (line 40) | function randomNormal(mean: Decimal.Value, std: Decimal.Value): Decimal {
  function countIf (line 45) | function countIf<T>(data: T[], fn: (item: T) => boolean): number {
  function rateOf (line 56) | function rateOf<T>(data: T[], fn: (item: T) => boolean): Decimal {
  function quantiles (line 60) | function quantiles(data: Decimal.Value[], p: Decimal.Value[]): Decimal[] {
  function quantilesBy (line 67) | function quantilesBy<T>(data: T[], by: (item: T) => Decimal, p: Decimal....
  function _quantileSorted (line 74) | function _quantileSorted<T>(x: T[], p: Decimal, avg: (data: [T, T]) => T...
  function _toDecimal (line 100) | function _toDecimal(x: Decimal.Value): Decimal {

FILE: libs/shared/src/utils/test-utils.ts
  function axiosSuccess (line 1) | function axiosSuccess<T>(data: T) {
  function axios400Error (line 11) | function axios400Error<T>(data: T) {

FILE: libs/shared/src/utils/transaction-utils.ts
  constant CATEGORIES (line 2) | const CATEGORIES = [

FILE: libs/shared/src/utils/user-utils.ts
  constant MAX_MAYBE_LENGTH (line 1) | const MAX_MAYBE_LENGTH = 180

FILE: libs/teller-api/src/teller-api.ts
  class TellerApi (line 27) | class TellerApi {
    method getAccounts (line 36) | async getAccounts({ accessToken }: AuthenticatedRequest): Promise<GetA...
    method getAccount (line 59) | async getAccount({ accountId, accessToken }: GetAccountRequest): Promi...
    method deleteAccount (line 69) | async deleteAccount({
    method getAccountDetails (line 82) | async getAccountDetails({
    method getAccountBalances (line 95) | async getAccountBalances({
    method getTransactions (line 108) | async getTransactions({
    method getTransaction (line 121) | async getTransaction({
    method getIdentity (line 138) | async getIdentity({ accessToken }: AuthenticatedRequest): Promise<GetI...
    method getInstitutions (line 148) | async getInstitutions(): Promise<GetInstitutionsResponse> {
    method getApi (line 152) | private async getApi(accessToken: string): Promise<AxiosInstance> {
    method get (line 185) | private async get<TResponse>(
    method post (line 196) | private async post<TResponse>(
    method delete (line 207) | private async delete<TResponse>(

FILE: libs/teller-api/src/types/account-balance.ts
  type AccountBalance (line 4) | type AccountBalance = {
  type GetAccountBalancesResponse (line 14) | type GetAccountBalancesResponse = AccountBalance
  type GetAccountBalancesRequest (line 15) | interface GetAccountBalancesRequest extends AuthenticatedRequest {

FILE: libs/teller-api/src/types/account-details.ts
  type AccountDetails (line 5) | type AccountDetails = {
  type GetAccountDetailsResponse (line 19) | type GetAccountDetailsResponse = AccountDetails
  type GetAccountDetailsRequest (line 20) | interface GetAccountDetailsRequest extends AuthenticatedRequest {

FILE: libs/teller-api/src/types/accounts.ts
  type AccountTypes (line 5) | type AccountTypes = 'depository' | 'credit'
  type AccountType (line 7) | enum AccountType {
  type DepositorySubtypes (line 12) | type DepositorySubtypes =
  type CreditSubtype (line 20) | type CreditSubtype = 'credit_card'
  type AccountStatus (line 22) | type AccountStatus = 'open' | 'closed'
  type BaseAccount (line 24) | interface BaseAccount {
  type DepositoryAccount (line 42) | interface DepositoryAccount extends BaseAccount {
  type CreditAccount (line 47) | interface CreditAccount extends BaseAccount {
  type Account (line 52) | type Account = DepositoryAccount | CreditAccount
  type AccountWithBalances (line 54) | type AccountWithBalances = Account & {
  type GetAccountsResponse (line 58) | type GetAccountsResponse = AccountWithBalances[]
  type GetAccountResponse (line 59) | type GetAccountResponse = Account
  type DeleteAccountResponse (line 60) | type DeleteAccountResponse = void
  type GetAccountRequest (line 62) | interface GetAccountRequest extends AuthenticatedRequest {
  type DeleteAccountRequest (line 66) | type DeleteAccountRequest = GetAccountRequest

FILE: libs/teller-api/src/types/authentication.ts
  type AuthenticationResponse (line 3) | type AuthenticationResponse = {
  type AuthenticatedRequest (line 7) | type AuthenticatedRequest = {

FILE: libs/teller-api/src/types/enrollment.ts
  type Enrollment (line 1) | type Enrollment = {

FILE: libs/teller-api/src/types/error.ts
  type TellerError (line 1) | type TellerError = {

FILE: libs/teller-api/src/types/identity.ts
  type Identity (line 5) | type Identity = {
  type Name (line 14) | type Name = {
  type Address (line 18) | type Address = {
  type Email (line 27) | type Email = {
  type PhoneNumber (line 31) | type PhoneNumber = {
  type GetIdentityResponse (line 36) | type GetIdentityResponse = {

FILE: libs/teller-api/src/types/institutions.ts
  type Institution (line 4) | type Institution = {
  type Capability (line 10) | type Capability = 'detail' | 'balance' | 'transaction' | 'identity'
  type GetInstitutionsResponse (line 12) | type GetInstitutionsResponse = Institution[]

FILE: libs/teller-api/src/types/transactions.ts
  type DetailCategory (line 5) | type DetailCategory =
  type DetailProcessingStatus (line 35) | type DetailProcessingStatus = 'pending' | 'complete'
  type Transaction (line 37) | type Transaction = {
  type GetTransactionsResponse (line 60) | type GetTransactionsResponse = Transaction[]
  type GetTransactionResponse (line 61) | type GetTransactionResponse = Transaction
  type GetTransactionsRequest (line 62) | interface GetTransactionsRequest extends AuthenticatedRequest {
  type GetTransactionRequest (line 65) | interface GetTransactionRequest extends AuthenticatedRequest {

FILE: libs/teller-api/src/types/webhooks.ts
  type WebhookData (line 3) | type WebhookData = {

FILE: prisma/migrations/20211005200319_init/migration.sql
  type "account_balance" (line 2) | CREATE TABLE "account_balance" (
  type "account_connection" (line 15) | CREATE TABLE "account_connection" (
  type "account" (line 30) | CREATE TABLE "account" (
  type "transaction" (line 51) | CREATE TABLE "transaction" (
  type "user" (line 73) | CREATE TABLE "user" (
  type "account_balance" (line 84) | CREATE INDEX "account_balances_account_id_index" ON "account_balance"("a...
  type "account_connection" (line 87) | CREATE INDEX "account_connections_user_id_index" ON "account_connection"...
  type "account" (line 90) | CREATE INDEX "accounts_account_connection_id_index" ON "account"("accoun...
  type "transaction" (line 93) | CREATE INDEX "transactions_account_id_index" ON "transaction"("account_id")
  type "user" (line 96) | CREATE UNIQUE INDEX "users_auth0_id_unique" ON "user"("auth0_id")

FILE: prisma/migrations/20211019194924_unique_constraint_on_account_balances/migration.sql
  type "account_balance" (line 8) | CREATE UNIQUE INDEX "account_balance_snapshot_date_account_id_key" ON "a...

FILE: prisma/migrations/20211102165759_account_status/migration.sql
  type "account_connection" (line 21) | CREATE UNIQUE INDEX "account_connection_plaid_item_id_key" ON "account_c...
  type "transaction" (line 24) | CREATE UNIQUE INDEX "transaction_plaid_transaction_id_key" ON "transacti...

FILE: prisma/migrations/20211102183151_add_account_types_and_subtypes/migration.sql
  type "account_type" (line 5) | CREATE TABLE "account_type" (
  type "account_subtype" (line 15) | CREATE TABLE "account_subtype" (
  type "account_type" (line 42) | CREATE UNIQUE INDEX "account_type_name_key" ON "account_type"("name")
  type "account_subtype" (line 45) | CREATE UNIQUE INDEX "account_subtype_name_key" ON "account_subtype"("name")
  type "account" (line 57) | CREATE INDEX "accounts_type_id_index" ON "account"("type_id")
  type "account" (line 60) | CREATE INDEX "accounts_subtype_id_index" ON "account"("subtype_id")

FILE: prisma/migrations/20211104155259_account_uniqueness/migration.sql
  type "account" (line 8) | CREATE UNIQUE INDEX "account_account_connection_id_plaid_account_id_key"...

FILE: prisma/migrations/20211110044559_manual_accounts_rename_fk/migration.sql
  type "valuation" (line 12) | CREATE TABLE "valuation" (
  type "valuation" (line 25) | CREATE INDEX "valuation_account_id_idx" ON "valuation"("account_id")

FILE: prisma/migrations/20211116235652_investment_data/migration.sql
  type "holding" (line 22) | CREATE TABLE "holding" (
  type "investment_transaction" (line 40) | CREATE TABLE "investment_transaction" (
  type "security" (line 61) | CREATE TABLE "security" (
  type "holding" (line 77) | CREATE UNIQUE INDEX "holding_plaid_holding_id_key" ON "holding"("plaid_h...
  type "holding" (line 80) | CREATE UNIQUE INDEX "holding_account_id_security_id_key" ON "holding"("a...
  type "investment_transaction" (line 83) | CREATE UNIQUE INDEX "investment_transaction_plaid_investment_transaction...
  type "investment_transaction" (line 86) | CREATE INDEX "investment_transaction_account_id_idx" ON "investment_tran...
  type "security" (line 89) | CREATE UNIQUE INDEX "security_plaid_security_id_key" ON "security"("plai...

FILE: prisma/migrations/20211117233026_add_date_indices/migration.sql
  type "investment_transaction" (line 11) | CREATE INDEX "investment_transaction_account_id_date_idx" ON "investment...
  type "transaction" (line 14) | CREATE INDEX "transaction_account_id_effective_date_idx" ON "transaction...
  type "valuation" (line 17) | CREATE INDEX "valuation_account_id_date_idx" ON "valuation"("account_id"...

FILE: prisma/migrations/20211118160716_account_balance_update/migration.sql
  type "account_balance" (line 23) | CREATE UNIQUE INDEX "account_balance_account_id_date_key" ON "account_ba...

FILE: prisma/migrations/20211118194940_account_functions/migration.sql
  function account_value_type (line 2) | CREATE OR REPLACE FUNCTION account_value_type(p_account_id int) RETURNS ...
  function account_value_start_date (line 13) | CREATE OR REPLACE FUNCTION account_value_start_date(p_account_id int) RE...
  function calculate_account_balances (line 24) | CREATE OR REPLACE FUNCTION calculate_account_balances(p_account_id int) ...

FILE: prisma/migrations/20211203180216_security_pricing/migration.sql
  type "security_pricing" (line 8) | CREATE TABLE "security_pricing" (

FILE: prisma/migrations/20211208162929_transaction_date/migration.sql
  type "transaction" (line 14) | CREATE INDEX "transaction_account_id_date_idx" ON "transaction"("account...

FILE: prisma/migrations/20211209050532_update_fns/migration.sql
  function account_value_start_date (line 5) | CREATE OR REPLACE FUNCTION account_value_start_date(p_account_id integer...

FILE: prisma/migrations/20211213211517_account_user_index/migration.sql
  type "account" (line 2) | CREATE INDEX "account_user_id_idx" ON "account"("user_id")

FILE: prisma/migrations/20220107170334_hypertable_chunk_size_tuning/migration.sql
  type account_balance_data (line 4) | CREATE TEMP TABLE account_balance_data ON COMMIT DROP AS (
  type security_pricing_data (line 18) | CREATE TEMP TABLE security_pricing_data ON COMMIT DROP AS (

FILE: prisma/migrations/20220112171128_update_fn/migration.sql
  function account_value_start_date (line 3) | CREATE OR REPLACE FUNCTION account_value_start_date(p_account_id integer...

FILE: prisma/migrations/20220125211038_add_unique_constraint_to_valuations/migration.sql
  type "valuation" (line 15) | CREATE UNIQUE INDEX "valuation_account_id_source_date_key" ON "valuation...

FILE: prisma/migrations/20220202184342_account_balances_gapfilled_fn/migration.sql
  function account_balances_gapfilled (line 4) | CREATE OR REPLACE FUNCTION account_balances_gapfilled(p_start date, p_en...

FILE: prisma/migrations/20220203234737_update_fn/migration.sql
  function account_balances_gapfilled (line 1) | CREATE OR REPLACE FUNCTION account_balances_gapfilled(p_start date, p_en...

FILE: prisma/migrations/20220215212216_add_transaction_indexes/migration.sql
  type "transaction" (line 2) | CREATE INDEX "transaction_amount_idx" ON "transaction"("amount")
  type "transaction" (line 5) | CREATE INDEX "transaction_category_idx" ON "transaction"("category")

FILE: prisma/migrations/20220228233043_change_money_type/migration.sql
  function public (line 37) | CREATE OR REPLACE FUNCTION public.account_balances_gapfilled(p_start dat...

FILE: prisma/migrations/20220307211701_valuation_trigger/migration.sql
  function valuation_changed (line 2) | CREATE OR REPLACE FUNCTION valuation_changed() RETURNS TRIGGER LANGUAGE ...

FILE: prisma/migrations/20220315172110_institution/migration.sql
  type "institution" (line 5) | CREATE TABLE "institution" (
  type "institution" (line 20) | CREATE UNIQUE INDEX "institution_provider_provider_id_key" ON "instituti...

FILE: prisma/migrations/20220323203441_multi_provider_updates/migration.sql
  type "account" (line 121) | CREATE UNIQUE INDEX "account_account_connection_id_finicity_account_id_k...
  type "holding" (line 124) | CREATE UNIQUE INDEX "holding_finicity_holding_id_key" ON "holding"("fini...
  type "investment_transaction" (line 127) | CREATE UNIQUE INDEX "investment_transaction_finicity_transaction_id_key"...
  type "transaction" (line 130) | CREATE UNIQUE INDEX "transaction_finicity_transaction_id_key" ON "transa...

FILE: prisma/migrations/20220323212807_fix_function/migration.sql
  function public (line 1) | CREATE OR REPLACE FUNCTION public.account_value_start_date(p_account_id ...
  function valuation_changed (line 17) | CREATE OR REPLACE FUNCTION valuation_changed() RETURNS TRIGGER LANGUAGE ...

FILE: prisma/migrations/20220504231954_finicity_updates/migration.sql
  type "holding" (line 16) | CREATE UNIQUE INDEX "holding_finicity_position_id_key" ON "holding"("fin...
  type "security" (line 23) | CREATE UNIQUE INDEX "security_finicity_security_id_finicity_security_id_...

FILE: prisma/migrations/20220518005502_finicity_customer_id_uniqueness/migration.sql
  type "user" (line 8) | CREATE UNIQUE INDEX "user_finicity_customer_id_key" ON "user"("finicity_...

FILE: prisma/migrations/20220519192445_institution_refactor/migration.sql
  type "provider_institution" (line 10) | CREATE TABLE "provider_institution" (
  type "provider_institution" (line 29) | CREATE UNIQUE INDEX "provider_institution_provider_provider_id_key" ON "...

FILE: prisma/migrations/20220520161223_institution_search_algo/migration.sql
  function edge_ngram_tsvector (line 1) | CREATE OR REPLACE FUNCTION edge_ngram_tsvector(text text, config regconf...
  type institution_name_ngram_idx (line 12) | CREATE INDEX institution_name_ngram_idx ON institution USING GIN (edge_n...
  type provider_institution_name_ngram_idx (line 13) | CREATE INDEX provider_institution_name_ngram_idx ON provider_institution...

FILE: prisma/migrations/20220606160203_add_finicity_username_to_user/migration.sql
  type "user" (line 11) | CREATE UNIQUE INDEX "user_finicity_username_key" ON "user"("finicity_use...

FILE: prisma/migrations/20220608190342_add_unique_constraint_to_institution/migration.sql
  type "institution" (line 8) | CREATE UNIQUE INDEX "institution_name_url_key" ON "institution"("name", ...

FILE: prisma/migrations/20220701013813_merge_updates/migration.sql
  type "transaction" (line 8) | CREATE INDEX "transaction_category_idx" ON "transaction"("category")

FILE: prisma/migrations/20220714180514_update_account_start_date_fn/migration.sql
  function public (line 1) | CREATE OR REPLACE FUNCTION public.account_value_start_date(p_account_id ...
  function valuation_changed (line 16) | CREATE OR REPLACE FUNCTION valuation_changed() RETURNS TRIGGER LANGUAGE ...

FILE: prisma/migrations/20220726003918_reset_loan_account_balances/migration.sql
  function public (line 10) | CREATE OR REPLACE FUNCTION public.account_value_start_date(p_account_id ...

FILE: prisma/migrations/20220804180126_holdings_view/migration.sql
  type holdings_enriched (line 9) | CREATE OR REPLACE VIEW holdings_enriched AS (

FILE: prisma/migrations/20220808174032_update_holdings_view/migration.sql
  type holdings_enriched (line 2) | CREATE OR REPLACE VIEW holdings_enriched AS (

FILE: prisma/migrations/20220915200544_add_plans/migration.sql
  type "plan" (line 2) | CREATE TABLE "plan" (

FILE: prisma/migrations/20221017145454_plan_events_milestones/migration.sql
  type "plan_event" (line 15) | CREATE TABLE "plan_event" (
  type "plan_milestone" (line 38) | CREATE TABLE "plan_milestone" (

FILE: prisma/migrations/20221109192536_add_stripe_fields/migration.sql
  type "user" (line 10) | CREATE UNIQUE INDEX "user_stripe_customer_id_key" ON "user"("stripe_cust...
  type "user" (line 13) | CREATE UNIQUE INDEX "user_stripe_subscription_id_key" ON "user"("stripe_...

FILE: prisma/migrations/20221111192223_ata/migration.sql
  type "advisor" (line 8) | CREATE TABLE "advisor" (
  type "conversation" (line 20) | CREATE TABLE "conversation" (
  type "conversation_advisor" (line 32) | CREATE TABLE "conversation_advisor" (
  type "message" (line 43) | CREATE TABLE "message" (
  type "advisor" (line 57) | CREATE UNIQUE INDEX "advisor_user_id_key" ON "advisor"("user_id")

FILE: prisma/migrations/20221129201601_conversation_advisor_unique_key/migration.sql
  type "conversation_advisor" (line 8) | CREATE UNIQUE INDEX "conversation_advisor_conversation_id_advisor_id_key...

FILE: prisma/migrations/20221214145140_add_audit_table_and_trigger/migration.sql
  type "audit_event" (line 5) | CREATE TABLE "audit_event" (
  function log_conversation_messages (line 17) | CREATE OR REPLACE FUNCTION log_conversation_messages()

FILE: prisma/migrations/20230105210810_add_member_number/migration.sql
  type "user" (line 21) | CREATE UNIQUE INDEX "user_member_number_key" ON "user"("member_number")

FILE: prisma/migrations/20230105221446_user_audit/migration.sql
  function log_user (line 8) | CREATE OR REPLACE FUNCTION log_user() RETURNS TRIGGER AS $$

FILE: prisma/migrations/20230110173017_add_user_member_id/migration.sql
  type "user" (line 5) | CREATE UNIQUE INDEX "user_member_id_key" ON "user"("member_id")

FILE: prisma/migrations/20230112163100_add_agreements_table/migration.sql
  type "agreement" (line 9) | CREATE TABLE "agreement" (
  type "signed_agreement" (line 20) | CREATE TABLE "signed_agreement" (
  type "agreement" (line 30) | CREATE UNIQUE INDEX "agreement_src_key" ON "agreement"("src")
  type "agreement" (line 33) | CREATE UNIQUE INDEX "agreement_type_revision_key" ON "agreement"("type",...

FILE: prisma/migrations/20230117192734_update_agreement_types/migration.sql
  type "agreement" (line 17) | CREATE UNIQUE INDEX "agreement_type_revision_active_key" ON "agreement"(...

FILE: prisma/migrations/20230130161915_account_value_start_date/migration.sql
  function public (line 2) | CREATE OR REPLACE FUNCTION public.account_value_start_date(p_account_id ...

FILE: prisma/migrations/20230207230108_account_balance_strategy/migration.sql
  function valuation_changed (line 45) | CREATE OR REPLACE FUNCTION valuation_changed() RETURNS TRIGGER LANGUAGE ...

FILE: prisma/migrations/20230211134603_advisor_crm/migration.sql
  type "conversation_note" (line 11) | CREATE TABLE "conversation_note" (
  type "conversation_note" (line 23) | CREATE UNIQUE INDEX "conversation_note_user_id_conversation_id_key" ON "...

FILE: prisma/migrations/20230223020847_txn_view/migration.sql
  type transactions_enriched (line 9) | CREATE OR REPLACE VIEW transactions_enriched AS (

FILE: prisma/migrations/20240111031553_remove_advisor_and_related_data/migration.sql
  type "account_balance" (line 91) | CREATE INDEX "account_balance_date_idx" ON "account_balance"("date")
  type "security_pricing" (line 94) | CREATE INDEX "security_pricing_date_idx" ON "security_pricing"("date")

FILE: prisma/migrations/20240111213125_next_auth_models/migration.sql
  type "auth_account" (line 12) | CREATE TABLE "auth_account" (
  type "auth_user" (line 30) | CREATE TABLE "auth_user" (
  type "auth_session" (line 41) | CREATE TABLE "auth_session" (
  type "auth_verification_token" (line 51) | CREATE TABLE "auth_verification_token" (
  type "auth_account" (line 58) | CREATE UNIQUE INDEX "auth_account_provider_provider_account_id_key" ON "...
  type "auth_user" (line 61) | CREATE UNIQUE INDEX "auth_user_email_key" ON "auth_user"("email")
  type "auth_session" (line 64) | CREATE UNIQUE INDEX "auth_session_session_token_key" ON "auth_session"("...
  type "auth_verification_token" (line 67) | CREATE UNIQUE INDEX "auth_verification_token_token_key" ON "auth_verific...
  type "auth_verification_token" (line 70) | CREATE UNIQUE INDEX "auth_verification_token_identifier_token_key" ON "a...
  type "user" (line 73) | CREATE UNIQUE INDEX "user_auth_id_key" ON "user"("auth_id")

FILE: prisma/migrations/20240115222631_add_fields_for_teller/migration.sql
  type "account" (line 31) | CREATE UNIQUE INDEX "account_account_connection_id_teller_account_id_key...
  type "transaction" (line 34) | CREATE UNIQUE INDEX "transaction_teller_transaction_id_key" ON "transact...
  type "user" (line 37) | CREATE UNIQUE INDEX "user_teller_user_id_key" ON "user"("teller_user_id")

FILE: prisma/migrations/20240117191553_categories_for_teller/migration.sql
  type transactions_enriched (line 163) | CREATE

FILE: prisma/migrations/20240118234302_remove_finicity_investment_transaction_categories/migration.sql
  type holdings_enriched (line 22) | CREATE OR REPLACE VIEW holdings_enriched AS (

FILE: prisma/migrations/20240118234302_remove_finicity_transaction_categories/migration.sql
  type transactions_enriched (line 37) | CREATE OR REPLACE VIEW transactions_enriched AS (

FILE: prisma/migrations/20240120213022_remove_transaction_category_generation/migration.sql
  type transactions_enriched (line 10) | CREATE OR REPLACE VIEW transactions_enriched AS (

FILE: prisma/migrations/20240120215821_remove_investment_transaction_category_generation/migration.sql
  type holdings_enriched (line 10) | CREATE OR REPLACE VIEW holdings_enriched AS (

FILE: prisma/seed.ts
  function main (line 8) | async function main() {

FILE: tools/generators/tellerGenerator.ts
  function generateSubType (line 6) | function generateSubType(
  type GenerateAccountsParams (line 23) | type GenerateAccountsParams = {
  function generateAccounts (line 32) | function generateAccounts({
  function generateBalance (line 91) | function generateBalance(account_id: string): TellerTypes.AccountBalance {
  type GenerateAccountsWithBalancesParams (line 104) | type GenerateAccountsWithBalancesParams = {
  function generateAccountsWithBalances (line 113) | function generateAccountsWithBalances({
  function generateTransactions (line 140) | function generateTransactions(count: number, accountId: string): TellerT...
  function generateEnrollment (line 204) | function generateEnrollment(): TellerTypes.Enrollment & { institutionId:...
  type GenerateConnectionsResponse (line 223) | type GenerateConnectionsResponse = {
  function generateConnection (line 230) | function generateConnection(): GenerateConnectionsResponse {
  function calculateDailyBalances (line 282) | function calculateDailyBalances(startingBalance, transactions, dateInter...

FILE: tools/scripts/vercelBuildIgnore.js
  constant VERCEL_GIT_COMMIT_REF (line 3) | const VERCEL_GIT_COMMIT_REF = process.env.VERCEL_GIT_COMMIT_REF
  constant CI_PROJECT_NAME (line 4) | const CI_PROJECT_NAME = process.env.CI_PROJECT_NAME
  constant CI_TEAM_ID (line 5) | const CI_TEAM_ID = process.env.CI_TEAM_ID
  constant CI_PROJECT_ID (line 6) | const CI_PROJECT_ID = process.env.CI_PROJECT_ID
  constant CI_DEPLOY_HOOK_ID (line 7) | const CI_DEPLOY_HOOK_ID = process.env.CI_DEPLOY_HOOK_ID
  constant CI_VERCEL_TOKEN (line 8) | const CI_VERCEL_TOKEN = process.env.CI_VERCEL_TOKEN
Condensed preview — 1004 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,857K chars).
[
  {
    "path": ".dockerignore",
    "chars": 99,
    "preview": "# Ignores everything except dist/ prisma/ apps/\n*\n!dist/\n!prisma/\n!package.json\n!apps/client/env.sh"
  },
  {
    "path": ".editorconfig",
    "chars": 245,
    "preview": "# Editor configuration, see http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = "
  },
  {
    "path": ".eslintrc.json",
    "chars": 3464,
    "preview": "{\n    \"root\": true,\n    \"ignorePatterns\": [\"**/*\", \"**/*.png\"],\n    \"plugins\": [\"@nrwl/nx\", \"eslint-plugin-json\"],\n    \""
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 845,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request-or-improvement.md",
    "chars": 606,
    "preview": "---\nname: Feature request or improvement\nabout: Suggest a new feature or improvement\ntitle: ''\nlabels: ''\nassignees: ''\n"
  },
  {
    "path": ".github/workflows/docker-publish.yml",
    "chars": 3475,
    "preview": "name: Docker\n\non:\n  push:\n    branches: [ \"main\" ]\n    tags: [ 'v*.*.*' ]\n  pull_request:\n    branches: [ \"main\" ]\n\nenv:"
  },
  {
    "path": ".gitignore",
    "chars": 728,
    "preview": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n**/dist\n**/tmp\n**/out-tsc\n\n"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 59,
    "preview": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\npnpm lint-staged\n"
  },
  {
    "path": ".prettierignore",
    "chars": 73,
    "preview": "# Add files here to ignore them from prettier formatting\n/dist\n/coverage\n"
  },
  {
    "path": ".prettierrc",
    "chars": 117,
    "preview": "{\n    \"trailingComma\": \"es5\",\n    \"printWidth\": 100,\n    \"tabWidth\": 4,\n    \"semi\": false,\n    \"singleQuote\": true\n}\n"
  },
  {
    "path": ".storybook/main.js",
    "chars": 398,
    "preview": "module.exports = {\n    stories: [],\n    addons: ['@storybook/addon-essentials'],\n    // uncomment the property below if "
  },
  {
    "path": ".storybook/tsconfig.json",
    "chars": 166,
    "preview": "{\n    \"extends\": \"../tsconfig.base.json\",\n    \"exclude\": [\"../**/*.spec.js\", \"../**/*.spec.ts\", \"../**/*.spec.tsx\", \"../"
  },
  {
    "path": ".vscode/extensions.json",
    "chars": 199,
    "preview": "{\n    \"recommendations\": [\n        \"nrwl.angular-console\",\n        \"esbenp.prettier-vscode\",\n        \"firsttris.vscode-j"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 1519,
    "preview": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"type\": \"pwa-node\",\n            \"request\": \"laun"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 432,
    "preview": "{\n    \"css.customData\": [\".vscode/css_custom_data.json\"],\n    \"[typescript]\": {\n        \"editor.defaultFormatter\": \"esbe"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 887,
    "preview": "# Contributing to Maybe\nIt means so much that you're interested in contributing to Maybe! Seriously. Thank you. The enti"
  },
  {
    "path": "LICENSE",
    "chars": 34523,
    "preview": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C)"
  },
  {
    "path": "README.md",
    "chars": 6267,
    "preview": "**🚨 NOTE: This codebase is no longer being maintained. The repo we're actively working on is located at [maybe-finance/m"
  },
  {
    "path": "apps/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "apps/client/.babelrc.json",
    "chars": 53,
    "preview": "{\n    \"presets\": [\"next/babel\"],\n    \"plugins\": []\n}\n"
  },
  {
    "path": "apps/client/.eslintrc.json",
    "chars": 878,
    "preview": "{\n    \"extends\": [\n        \"plugin:@nrwl/nx/react-typescript\",\n        \"../../.eslintrc.json\",\n        \"next\",\n        \""
  },
  {
    "path": "apps/client/.storybook/main.js",
    "chars": 658,
    "preview": "const rootMain = require('../../../.storybook/main')\n\nmodule.exports = {\n    ...rootMain,\n    core: { ...rootMain.core, "
  },
  {
    "path": "apps/client/.storybook/manager.js",
    "chars": 105,
    "preview": "import { addons } from '@storybook/addons'\nimport theme from './theme'\n\naddons.setConfig({\n    theme,\n})\n"
  },
  {
    "path": "apps/client/.storybook/preview.js",
    "chars": 117,
    "preview": "import '../styles.css'\n\nimport theme from './theme'\n\nexport const parameters = {\n    docs: {\n        theme,\n    },\n}\n"
  },
  {
    "path": "apps/client/.storybook/theme.js",
    "chars": 368,
    "preview": "import { create } from '@storybook/theming'\nimport logo from '../assets/logo.svg'\n\nexport default create({\n    base: 'da"
  },
  {
    "path": "apps/client/.storybook/tsconfig.json",
    "chars": 182,
    "preview": "{\n    \"extends\": \"../tsconfig.json\",\n    \"compilerOptions\": {\n        \"allowImportingTsExtensions\": true\n    },\n    \"inc"
  },
  {
    "path": "apps/client/Dockerfile",
    "chars": 857,
    "preview": "# ------------------------------------------\n#                BUILD STAGE              \n# ------------------------------"
  },
  {
    "path": "apps/client/components/APM.tsx",
    "chars": 500,
    "preview": "import { useEffect } from 'react'\nimport * as Sentry from '@sentry/react'\nimport { useSession } from 'next-auth/react'\n\n"
  },
  {
    "path": "apps/client/components/Maintenance.stories.tsx",
    "chars": 359,
    "preview": "import type { Story, Meta } from '@storybook/react'\nimport Maintenance from './Maintenance'\nimport React from 'react'\n\ne"
  },
  {
    "path": "apps/client/components/Maintenance.tsx",
    "chars": 2622,
    "preview": "export default function Maintenance() {\n    return (\n        <div className=\"h-screen flex flex-col items-center justify"
  },
  {
    "path": "apps/client/components/Meta.tsx",
    "chars": 1962,
    "preview": "import Head from 'next/head'\nimport React from 'react'\nimport env from '../env'\n\nexport default function Meta() {\n    re"
  },
  {
    "path": "apps/client/components/account-views/DefaultView.tsx",
    "chars": 3837,
    "preview": "import type { ReactNode } from 'react'\nimport type { Account } from '@prisma/client'\nimport type { SharedType } from '@m"
  },
  {
    "path": "apps/client/components/account-views/InvestmentView.tsx",
    "chars": 25711,
    "preview": "import {\n    type InsightCardOption,\n    InsightPopout,\n    usePopoutContext,\n    useAccountApi,\n    InsightGroup,\n    T"
  },
  {
    "path": "apps/client/components/account-views/LoanView.tsx",
    "chars": 5378,
    "preview": "import type { SharedType } from '@maybe-finance/shared'\nimport { AccountMenu, LoanDetail, PageTitle, TransactionList } f"
  },
  {
    "path": "apps/client/components/account-views/index.ts",
    "chars": 104,
    "preview": "export { default as DefaultView } from './DefaultView'\nexport { default as LoanView } from './LoanView'\n"
  },
  {
    "path": "apps/client/env.sh",
    "chars": 1540,
    "preview": "#!/bin/bash\n# https://github.com/vercel/next.js/discussions/17641#discussioncomment-5919914\n\n# Config\nENVSH_ENV=\"${ENVSH"
  },
  {
    "path": "apps/client/env.ts",
    "chars": 887,
    "preview": "declare global {\n    interface Window {\n        __appenv: any\n    }\n}\n\nfunction isBrowser() {\n    return Boolean(typeof "
  },
  {
    "path": "apps/client/jest.config.ts",
    "chars": 349,
    "preview": "/* eslint-disable */\nexport default {\n    displayName: 'client',\n    preset: '../../jest.preset.js',\n    transform: {\n  "
  },
  {
    "path": "apps/client/next-env.d.ts",
    "chars": 201,
    "preview": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\n\n// NOTE: This file should not be edite"
  },
  {
    "path": "apps/client/next.config.js",
    "chars": 596,
    "preview": "// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst withNx = require('@nrwl/next/plugins/with-nx')\ncons"
  },
  {
    "path": "apps/client/pages/404.tsx",
    "chars": 145,
    "preview": "import { NotFoundPage } from '@maybe-finance/client/features'\n\nexport function Page404() {\n    return <NotFoundPage />\n}"
  },
  {
    "path": "apps/client/pages/_app.tsx",
    "chars": 3280,
    "preview": "import { useEffect, type PropsWithChildren, type ReactElement } from 'react'\nimport type { AppProps } from 'next/app'\nim"
  },
  {
    "path": "apps/client/pages/_document.tsx",
    "chars": 477,
    "preview": "import { Html, Head, Main, NextScript } from 'next/document'\n\nexport default function Document() {\n    return (\n        "
  },
  {
    "path": "apps/client/pages/accounts/[accountId].tsx",
    "chars": 4831,
    "preview": "import type { ReactElement } from 'react'\nimport type { SharedType } from '@maybe-finance/shared'\n\nimport { useEffect, u"
  },
  {
    "path": "apps/client/pages/accounts/index.tsx",
    "chars": 4196,
    "preview": "import type { ReactElement } from 'react'\nimport { RiAddLine } from 'react-icons/ri'\n\nimport {\n    AccountGroupContainer"
  },
  {
    "path": "apps/client/pages/api/auth/[...nextauth].ts",
    "chars": 5357,
    "preview": "import NextAuth from 'next-auth'\nimport type { SessionStrategy, NextAuthOptions } from 'next-auth'\nimport CredentialsPro"
  },
  {
    "path": "apps/client/pages/api/card.tsx",
    "chars": 3756,
    "preview": "import { ImageResponse } from '@vercel/og'\nimport { DateTime } from 'luxon'\nimport type { NextRequest } from 'next/serve"
  },
  {
    "path": "apps/client/pages/card/[id].tsx",
    "chars": 2884,
    "preview": "import { MaybeCard } from '@maybe-finance/client/shared'\nimport { type SharedType, superjson } from '@maybe-finance/shar"
  },
  {
    "path": "apps/client/pages/data-editor.tsx",
    "chars": 2219,
    "preview": "import type { ReactElement } from 'react'\nimport { useMemo } from 'react'\nimport {\n    WithSidebarLayout,\n    AccountEdi"
  },
  {
    "path": "apps/client/pages/index.tsx",
    "chars": 9080,
    "preview": "import type { ReactElement } from 'react'\nimport { useState } from 'react'\nimport {\n    WithSidebarLayout,\n    NetWorthI"
  },
  {
    "path": "apps/client/pages/login.tsx",
    "chars": 4756,
    "preview": "import { useState, type ReactElement } from 'react'\nimport { FullPageLayout } from '@maybe-finance/client/features'\nimpo"
  },
  {
    "path": "apps/client/pages/onboarding.tsx",
    "chars": 4353,
    "preview": "import type { ReactElement } from 'react'\nimport { Transition } from '@headlessui/react'\nimport {\n    AddFirstAccount,\n "
  },
  {
    "path": "apps/client/pages/plans/[planId].tsx",
    "chars": 17093,
    "preview": "import type { ReactElement } from 'react'\nimport {\n    WithSidebarLayout,\n    AccountSidebar,\n    RetirementPlanChart,\n "
  },
  {
    "path": "apps/client/pages/plans/create.tsx",
    "chars": 1103,
    "preview": "import type { ReactElement } from 'react'\nimport { useRouter } from 'next/router'\nimport { WithSidebarLayout, AccountSid"
  },
  {
    "path": "apps/client/pages/plans/index.tsx",
    "chars": 1963,
    "preview": "import type { ReactElement } from 'react'\nimport { useEffect } from 'react'\n\nimport { WithSidebarLayout, AccountSidebar "
  },
  {
    "path": "apps/client/pages/register.tsx",
    "chars": 6785,
    "preview": "import { useState, type ReactElement } from 'react'\nimport { Input, InputPassword, Button } from '@maybe-finance/design-"
  },
  {
    "path": "apps/client/pages/settings.tsx",
    "chars": 2195,
    "preview": "import type { ReactElement } from 'react'\nimport { useQueryParam } from '@maybe-finance/client/shared'\nimport {\n    Acco"
  },
  {
    "path": "apps/client/pages/upgrade.tsx",
    "chars": 639,
    "preview": "import { UpgradeTakeover } from '@maybe-finance/client/features'\nimport { useUserApi } from '@maybe-finance/client/share"
  },
  {
    "path": "apps/client/postcss.config.js",
    "chars": 138,
    "preview": "module.exports = {\n    plugins: {\n        tailwindcss: { config: './apps/client/tailwind.config.js' },\n        autoprefi"
  },
  {
    "path": "apps/client/public/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "apps/client/public/__appenv.js",
    "chars": 20,
    "preview": "window.__appenv = {}"
  },
  {
    "path": "apps/client/public/assets/browserconfig.xml",
    "chars": 354,
    "preview": "<!-- This is just another favicon config for Windows OS, generated by https://realfavicongenerator.net/ -->\n<?xml versio"
  },
  {
    "path": "apps/client/public/assets/site.webmanifest",
    "chars": 508,
    "preview": "{\n    \"name\": \"Maybe\",\n    \"short_name\": \"Maybe\",\n    \"description\": \"Modern day financial planning & wealth management\""
  },
  {
    "path": "apps/client/stories/404.stories.tsx",
    "chars": 242,
    "preview": "import React from 'react'\nimport type { Story, Meta } from '@storybook/react'\nimport Page404 from '../pages/404'\n\nexport"
  },
  {
    "path": "apps/client/styles.css",
    "chars": 4694,
    "preview": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n/* https://tailwindcss.com/docs/adding-base-styles#using-css"
  },
  {
    "path": "apps/client/tailwind.config.js",
    "chars": 3758,
    "preview": "const { join } = require('path')\nconst merge = require('lodash/fp/merge')\n\n// https://blog.nrwl.io/setup-next-js-to-use-"
  },
  {
    "path": "apps/client/tsconfig.json",
    "chars": 772,
    "preview": "{\n    \"extends\": \"../../tsconfig.base.json\",\n    \"compilerOptions\": {\n        \"jsx\": \"preserve\",\n        \"allowJs\": true"
  },
  {
    "path": "apps/client/tsconfig.spec.json",
    "chars": 437,
    "preview": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"outDir\": \"../../dist/out-tsc\",\n        \"module\": \""
  },
  {
    "path": "apps/e2e/.eslintrc.json",
    "chars": 434,
    "preview": "{\n    \"extends\": [\"plugin:cypress/recommended\", \"../../.eslintrc.json\"],\n    \"ignorePatterns\": [\"!**/*\"],\n    \"overrides"
  },
  {
    "path": "apps/e2e/cypress.config.ts",
    "chars": 1137,
    "preview": "import { defineConfig } from 'cypress'\nimport { nxE2EPreset } from '@nrwl/cypress/plugins/cypress-preset'\n\nexport defaul"
  },
  {
    "path": "apps/e2e/src/e2e/accounts.cy.ts",
    "chars": 10735,
    "preview": "import { DateTime } from 'luxon'\n\nconst assertSidebarAccounts = (expectedRows: [string, string][]) => {\n    cy.getByTest"
  },
  {
    "path": "apps/e2e/src/e2e/auth.cy.ts",
    "chars": 239,
    "preview": "describe('Auth', () => {\n    beforeEach(() => cy.visit('/'))\n\n    describe('Logging in', () => {\n        it('should show"
  },
  {
    "path": "apps/e2e/src/e2e/subscription.cy.ts",
    "chars": 2261,
    "preview": "import { checkoutSessionCompleted, customerSubscriptionCreated } from '../fixtures/stripe'\nimport Stripe from 'stripe'\ni"
  },
  {
    "path": "apps/e2e/src/fixtures/stripe/checkoutSessionCompleted.ts",
    "chars": 3215,
    "preview": "export function checkoutSessionCompleted(auth0Id: string) {\n    return {\n        id: 'evt_1M7QkDKXgym9ohnqSTEo8Ld7',\n   "
  },
  {
    "path": "apps/e2e/src/fixtures/stripe/customerSubscriptionCreated.ts",
    "chars": 6617,
    "preview": "import { DateTime } from 'luxon'\n\nexport function customerSubscriptionCreated() {\n    const now = DateTime.now()\n\n    re"
  },
  {
    "path": "apps/e2e/src/fixtures/stripe/customerSubscriptionDeleted.ts",
    "chars": 6773,
    "preview": "import { DateTime } from 'luxon'\n\nexport function customerSubscriptionDeleted() {\n    const now = DateTime.now()\n    con"
  },
  {
    "path": "apps/e2e/src/fixtures/stripe/index.ts",
    "chars": 89,
    "preview": "export * from './checkoutSessionCompleted'\nexport * from './customerSubscriptionCreated'\n"
  },
  {
    "path": "apps/e2e/src/support/commands.ts",
    "chars": 1326,
    "preview": "// eslint-disable-next-line @typescript-eslint/no-namespace\ndeclare namespace Cypress {\n    // eslint-disable-next-line "
  },
  {
    "path": "apps/e2e/src/support/e2e.ts",
    "chars": 1468,
    "preview": "import './commands'\n\nbeforeEach(() => {\n    authenticateCIUser()\n    cy.apiRequest({\n        method: 'POST',\n        url"
  },
  {
    "path": "apps/e2e/src/support/index.ts",
    "chars": 35,
    "preview": "import './commands'\nimport './e2e'\n"
  },
  {
    "path": "apps/e2e/tsconfig.json",
    "chars": 276,
    "preview": "{\n    \"extends\": \"../../tsconfig.base.json\",\n    \"compilerOptions\": {\n        \"sourceMap\": false,\n        \"outDir\": \"../"
  },
  {
    "path": "apps/server/.eslintrc.json",
    "chars": 400,
    "preview": "{\n    \"extends\": [\"../../.eslintrc.json\"],\n    \"ignorePatterns\": [\"!**/*\", \"**/*.csv\", \"Dockerfile\"],\n    \"overrides\": ["
  },
  {
    "path": "apps/server/Dockerfile",
    "chars": 736,
    "preview": "# ------------------------------------------\n#                BUILD STAGE              \n# ------------------------------"
  },
  {
    "path": "apps/server/jest.config.ts",
    "chars": 400,
    "preview": "/* eslint-disable */\nexport default {\n    displayName: 'server',\n    preset: '../../jest.preset.js',\n    globals: {\n    "
  },
  {
    "path": "apps/server/src/app/__tests__/account.integration.spec.ts",
    "chars": 10239,
    "preview": "import type { AxiosInstance } from 'axios'\nimport { PrismaClient, type Account, type AccountConnection, type User } from"
  },
  {
    "path": "apps/server/src/app/__tests__/balance-sync.integration.spec.ts",
    "chars": 10673,
    "preview": "import type { User } from '@prisma/client'\nimport { InvestmentTransactionCategory } from '@prisma/client'\nimport { Prism"
  },
  {
    "path": "apps/server/src/app/__tests__/connection.integration.spec.ts",
    "chars": 2897,
    "preview": "import type { AxiosInstance } from 'axios'\nimport type { Prisma, AccountConnection, User } from '@prisma/client'\nimport "
  },
  {
    "path": "apps/server/src/app/__tests__/insights.integration.spec.ts",
    "chars": 17203,
    "preview": "import type { User } from '@prisma/client'\nimport { AssetClass, InvestmentTransactionCategory, Prisma, PrismaClient } fr"
  },
  {
    "path": "apps/server/src/app/__tests__/net-worth.integration.spec.ts",
    "chars": 13050,
    "preview": "import type { AccountCategory, AccountProvider, AccountType, User } from '@prisma/client'\nimport { PrismaClient, Prisma "
  },
  {
    "path": "apps/server/src/app/__tests__/prisma.integration.spec.ts",
    "chars": 5417,
    "preview": "import type { Account, User } from '@prisma/client'\nimport { PrismaClient, Prisma } from '@prisma/client'\nimport { DateT"
  },
  {
    "path": "apps/server/src/app/__tests__/stripe.integration.spec.ts",
    "chars": 2691,
    "preview": "import type { User } from '@prisma/client'\nimport { PrismaClient } from '@prisma/client'\nimport { createLogger, transpor"
  },
  {
    "path": "apps/server/src/app/__tests__/test-data/portfolio-1/holdings.csv",
    "chars": 63,
    "preview": "ticker,qty,costBasis,value\nXYZ,31,178.05,5952\nDEF,60,38.83,2220"
  },
  {
    "path": "apps/server/src/app/__tests__/test-data/portfolio-1/securities.csv",
    "chars": 5275,
    "preview": "date,ticker,price\n2021-12-30,XYZ,198\n2021-12-31,XYZ,198\n2022-01-01,XYZ,198\n2022-01-02,XYZ,200\n2022-01-03,XYZ,205\n2022-01"
  },
  {
    "path": "apps/server/src/app/__tests__/test-data/portfolio-1/transactions.csv",
    "chars": 298,
    "preview": "date,type,ticker,qty\n2021-12-31,DEPOSIT,USD,-5000\n2022-01-02,BUY,ABC,10\n2022-01-04,SELL,ABC,-10\n2022-01-10,BUY,DEF,10\n20"
  },
  {
    "path": "apps/server/src/app/__tests__/test-data/portfolio-2/holdings.csv",
    "chars": 40,
    "preview": "ticker,qty,costBasis,value\nABC,10,50,900"
  },
  {
    "path": "apps/server/src/app/__tests__/test-data/portfolio-2/securities.csv",
    "chars": 485,
    "preview": "date,ticker,price\n2022-08-01,ABC,79.8\n2022-08-02,ABC,80\n2022-08-03,ABC,80.2\n2022-08-04,ABC,80.4\n2022-08-05,ABC,80.6\n2022"
  },
  {
    "path": "apps/server/src/app/__tests__/test-data/portfolio-2/transactions.csv",
    "chars": 166,
    "preview": "date,type,ticker,qty\n2022-08-10,DEPOSIT,USD,-2000\n2022-08-12,DEPOSIT,USD,-5000\n2022-08-15,DEPOSIT,USD,-2000\n2022-08-18,W"
  },
  {
    "path": "apps/server/src/app/__tests__/utils/account.ts",
    "chars": 4696,
    "preview": "import type { PrismaClient, User } from '@prisma/client'\nimport { InvestmentTransactionCategory, Prisma } from '@prisma/"
  },
  {
    "path": "apps/server/src/app/__tests__/utils/axios.ts",
    "chars": 1980,
    "preview": "import type { AxiosResponse } from 'axios'\nimport type { SharedType } from '@maybe-finance/shared'\nimport { superjson } "
  },
  {
    "path": "apps/server/src/app/__tests__/utils/csv.ts",
    "chars": 376,
    "preview": "import * as csv from '@fast-csv/parse'\n\nexport async function parseCsv<Keys extends string>(path: string): Promise<Recor"
  },
  {
    "path": "apps/server/src/app/__tests__/utils/server.ts",
    "chars": 412,
    "preview": "import type { Server } from 'http'\nimport app from '../../app'\n\nlet server: Server\n\nexport const startServer = () => {\n "
  },
  {
    "path": "apps/server/src/app/__tests__/utils/user.ts",
    "chars": 501,
    "preview": "import type { User } from '@prisma/client'\nimport prisma from '../../lib/prisma'\n\nconst EMAIL = 'test@example.com'\n\nexpo"
  },
  {
    "path": "apps/server/src/app/admin/views/pages/dashboard.ejs",
    "chars": 551,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n    <%- include('../partials/head'); %>\n    <body>\n        <div class=\"container\">\n    "
  },
  {
    "path": "apps/server/src/app/admin/views/pages/index.ejs",
    "chars": 703,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n    <%- include('../partials/head'); %>\n    <body>\n        <div class=\"container\">\n    "
  },
  {
    "path": "apps/server/src/app/admin/views/partials/head.ejs",
    "chars": 370,
    "preview": "<head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport"
  },
  {
    "path": "apps/server/src/app/app.ts",
    "chars": 5518,
    "preview": "import type { RequestHandler } from 'express'\nimport express from 'express'\nimport cors from 'cors'\nimport morgan from '"
  },
  {
    "path": "apps/server/src/app/lib/ability.ts",
    "chars": 4348,
    "preview": "import type { Subjects } from '@casl/prisma'\nimport { PrismaAbility, accessibleBy } from '@casl/prisma'\nimport type { Ab"
  },
  {
    "path": "apps/server/src/app/lib/email.ts",
    "chars": 1414,
    "preview": "import { ServerClient as PostmarkServerClient } from 'postmark'\nimport nodemailer from 'nodemailer'\nimport type SMTPTran"
  },
  {
    "path": "apps/server/src/app/lib/endpoint.ts",
    "chars": 8270,
    "preview": "import type { IMarketDataService } from '@maybe-finance/server/shared'\nimport type {\n    IAccountQueryService,\n    IInst"
  },
  {
    "path": "apps/server/src/app/lib/logger.ts",
    "chars": 161,
    "preview": "import { createLogger } from '@maybe-finance/server/shared'\n\nconst logger = createLogger({\n    level: process.env.LOG_LE"
  },
  {
    "path": "apps/server/src/app/lib/prisma.ts",
    "chars": 1674,
    "preview": "import { PrismaClient } from '@prisma/client'\nimport { DbUtil } from '@maybe-finance/server/shared'\nimport globalLogger "
  },
  {
    "path": "apps/server/src/app/lib/stripe.ts",
    "chars": 162,
    "preview": "import Stripe from 'stripe'\nimport env from '../../env'\n\nconst stripe = new Stripe(env.NX_STRIPE_SECRET_KEY, { apiVersio"
  },
  {
    "path": "apps/server/src/app/lib/teller.ts",
    "chars": 290,
    "preview": "import { TellerApi } from '@maybe-finance/teller-api'\nimport { getWebhookUrl } from './webhook'\n\nconst teller = new Tell"
  },
  {
    "path": "apps/server/src/app/lib/types.ts",
    "chars": 798,
    "preview": "import type { Response, Request, NextFunction } from 'express'\n\ninterface TypedRequest<T> extends Omit<Request, 'body'> "
  },
  {
    "path": "apps/server/src/app/lib/webhook.ts",
    "chars": 733,
    "preview": "import axios from 'axios'\nimport isCI from 'is-ci'\nimport env from '../../env'\nimport logger from './logger'\n\nexport asy"
  },
  {
    "path": "apps/server/src/app/middleware/auth-error-handler.ts",
    "chars": 485,
    "preview": "import type { ErrorRequestHandler } from 'express'\nimport { ForbiddenError } from '@casl/ability'\n\nexport const authErro"
  },
  {
    "path": "apps/server/src/app/middleware/dev-only.ts",
    "chars": 230,
    "preview": "import createError from 'http-errors'\n\nexport const devOnly = (_req, _res, next) => {\n    if (process.env.NODE_ENV !== '"
  },
  {
    "path": "apps/server/src/app/middleware/error-handler.ts",
    "chars": 1195,
    "preview": "import type { ErrorRequestHandler } from 'express'\nimport type { SharedType } from '@maybe-finance/shared'\nimport logger"
  },
  {
    "path": "apps/server/src/app/middleware/identify-user.ts",
    "chars": 250,
    "preview": "import type { ErrorRequestHandler } from 'express'\nimport * as Sentry from '@sentry/node'\n\nexport const identifySentryUs"
  },
  {
    "path": "apps/server/src/app/middleware/index.ts",
    "chars": 291,
    "preview": "export * from './dev-only'\nexport * from './error-handler'\nexport * from './auth-error-handler'\nexport * from './superjs"
  },
  {
    "path": "apps/server/src/app/middleware/maintenance.ts",
    "chars": 571,
    "preview": "import type { Express } from 'express'\n\ntype MaintenanceOptions = {\n    statusCode?: number\n    path?: string\n    featur"
  },
  {
    "path": "apps/server/src/app/middleware/superjson.ts",
    "chars": 649,
    "preview": "import type { RequestHandler } from 'express'\nimport type { SharedType } from '@maybe-finance/shared'\nimport { superjson"
  },
  {
    "path": "apps/server/src/app/middleware/validate-auth-jwt.ts",
    "chars": 1930,
    "preview": "import cookieParser from 'cookie-parser'\nimport { decode } from 'next-auth/jwt'\nimport type { Request } from 'express'\n\n"
  },
  {
    "path": "apps/server/src/app/middleware/validate-teller-signature.ts",
    "chars": 1776,
    "preview": "import crypto from 'crypto'\nimport type { RequestHandler } from 'express'\nimport type { TellerTypes } from '@maybe-finan"
  },
  {
    "path": "apps/server/src/app/routes/account-rollup.router.ts",
    "chars": 607,
    "preview": "import { Router } from 'express'\nimport { z } from 'zod'\nimport { DateUtil } from '@maybe-finance/shared'\nimport endpoin"
  },
  {
    "path": "apps/server/src/app/routes/accounts.router.ts",
    "chars": 13988,
    "preview": "import type { Account } from '@prisma/client'\nimport { AssetClass } from '@prisma/client'\nimport type { SharedType } fro"
  },
  {
    "path": "apps/server/src/app/routes/admin.router.ts",
    "chars": 916,
    "preview": "import { Router } from 'express'\nimport { createBullBoard } from '@bull-board/api'\nimport { BullAdapter } from '@bull-bo"
  },
  {
    "path": "apps/server/src/app/routes/connections.router.ts",
    "chars": 3631,
    "preview": "import { Router } from 'express'\nimport { subject } from '@casl/ability'\nimport { z } from 'zod'\nimport endpoint from '."
  },
  {
    "path": "apps/server/src/app/routes/e2e.router.ts",
    "chars": 2683,
    "preview": "import type { OnboardingState } from '@maybe-finance/server/features'\nimport { AuthUserRole } from '@prisma/client'\nimpo"
  },
  {
    "path": "apps/server/src/app/routes/holdings.router.ts",
    "chars": 1406,
    "preview": "import { Router } from 'express'\nimport { subject } from '@casl/ability'\nimport { HoldingUpdateInputSchema } from '@mayb"
  },
  {
    "path": "apps/server/src/app/routes/index.ts",
    "chars": 991,
    "preview": "export { default as accountsRouter } from './accounts.router'\nexport { default as accountRollupRouter } from './account-"
  },
  {
    "path": "apps/server/src/app/routes/institutions.router.ts",
    "chars": 1274,
    "preview": "import { Router } from 'express'\nimport { z } from 'zod'\nimport endpoint from '../lib/endpoint'\n\nconst router = Router()"
  },
  {
    "path": "apps/server/src/app/routes/plans.router.ts",
    "chars": 5082,
    "preview": "import { Router } from 'express'\nimport { subject } from '@casl/ability'\nimport {\n    PlanCreateSchema,\n    PlanTemplate"
  },
  {
    "path": "apps/server/src/app/routes/public.router.ts",
    "chars": 559,
    "preview": "import { Router } from 'express'\nimport env from '../../env'\nimport endpoint from '../lib/endpoint'\n\nconst router = Rout"
  },
  {
    "path": "apps/server/src/app/routes/securities.router.ts",
    "chars": 2967,
    "preview": "import { Router } from 'express'\nimport { DateTime } from 'luxon'\nimport env from '../../env'\nimport endpoint from '../l"
  },
  {
    "path": "apps/server/src/app/routes/teller.router.ts",
    "chars": 1273,
    "preview": "import { Router } from 'express'\nimport { z } from 'zod'\nimport endpoint from '../lib/endpoint'\n\nconst router = Router()"
  },
  {
    "path": "apps/server/src/app/routes/tools.router.ts",
    "chars": 4783,
    "preview": "import { Router } from 'express'\nimport _ from 'lodash'\nimport type Decimal from 'decimal.js'\nimport type { ProjectionIn"
  },
  {
    "path": "apps/server/src/app/routes/transactions.router.ts",
    "chars": 1368,
    "preview": "import { Router } from 'express'\nimport { subject } from '@casl/ability'\nimport endpoint from '../lib/endpoint'\nimport {"
  },
  {
    "path": "apps/server/src/app/routes/users.router.ts",
    "chars": 13596,
    "preview": "import { Router } from 'express'\nimport { subject } from '@casl/ability'\nimport { z } from 'zod'\nimport { DateUtil, type"
  },
  {
    "path": "apps/server/src/app/routes/valuations.router.ts",
    "chars": 1895,
    "preview": "import { Router } from 'express'\nimport { z } from 'zod'\nimport { subject } from '@casl/ability'\nimport endpoint from '."
  },
  {
    "path": "apps/server/src/app/routes/webhooks.router.ts",
    "chars": 2514,
    "preview": "import { Router } from 'express'\nimport { z } from 'zod'\nimport { validateTellerSignature } from '../middleware'\nimport "
  },
  {
    "path": "apps/server/src/app/trpc.ts",
    "chars": 966,
    "preview": "import * as trpc from '@trpc/server'\nimport type * as trpcExpress from '@trpc/server/adapters/express'\nimport { superjso"
  },
  {
    "path": "apps/server/src/assets/script.js",
    "chars": 185,
    "preview": "// eslint-disable-next-line\nfunction login() {\n    window.location.href = '/admin/login'\n}\n\n// eslint-disable-next-line\n"
  },
  {
    "path": "apps/server/src/assets/styles.css",
    "chars": 798,
    "preview": "a {\n    text-decoration: none;\n}\n\n.links {\n    display: flex;\n    justify-content: center;\n    min-width: 350px;\n}\n\n.lin"
  },
  {
    "path": "apps/server/src/env.ts",
    "chars": 2669,
    "preview": "import { z } from 'zod'\n\nconst toOriginArray = (s?: string) => {\n    if (!s) return []\n\n    const originList = (s || '')"
  },
  {
    "path": "apps/server/src/environments/environment.prod.ts",
    "chars": 53,
    "preview": "export const environment = {\n    production: true,\n}\n"
  },
  {
    "path": "apps/server/src/environments/environment.ts",
    "chars": 54,
    "preview": "export const environment = {\n    production: false,\n}\n"
  },
  {
    "path": "apps/server/src/main.ts",
    "chars": 803,
    "preview": "import type { AddressInfo } from 'net'\nimport env from './env'\nimport app from './app/app'\nimport logger from './app/lib"
  },
  {
    "path": "apps/server/tsconfig.app.json",
    "chars": 300,
    "preview": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"outDir\": \"../../dist/out-tsc\",\n        \"module\": \""
  },
  {
    "path": "apps/server/tsconfig.json",
    "chars": 389,
    "preview": "{\n    \"extends\": \"../../tsconfig.base.json\",\n    \"compilerOptions\": {\n        \"esModuleInterop\": true,\n        \"noImplic"
  },
  {
    "path": "apps/server/tsconfig.spec.json",
    "chars": 269,
    "preview": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"outDir\": \"../../dist/out-tsc\",\n        \"module\": \""
  },
  {
    "path": "apps/workers/.eslintrc.json",
    "chars": 570,
    "preview": "{\n    \"extends\": [\"../../.eslintrc.json\"],\n    \"ignorePatterns\": [\"!**/*\", \"Dockerfile\"],\n    \"overrides\": [\n        {\n "
  },
  {
    "path": "apps/workers/Dockerfile",
    "chars": 721,
    "preview": "# ------------------------------------------\n#                BUILD STAGE              \n# ------------------------------"
  },
  {
    "path": "apps/workers/jest.config.ts",
    "chars": 402,
    "preview": "/* eslint-disable */\nexport default {\n    displayName: 'workers',\n    preset: '../../jest.preset.js',\n    globals: {\n   "
  },
  {
    "path": "apps/workers/src/app/__tests__/helpers/user.test-helper.ts",
    "chars": 957,
    "preview": "import type { PrismaClient, User } from '@prisma/client'\nimport { faker } from '@faker-js/faker'\n\nexport async function "
  },
  {
    "path": "apps/workers/src/app/__tests__/queue.integration.spec.ts",
    "chars": 5578,
    "preview": "// =====================================================\n// Keep these imports above the rest to avoid errors\n// ======="
  },
  {
    "path": "apps/workers/src/app/__tests__/security-sync.integration.spec.ts",
    "chars": 6599,
    "preview": "import { PrismaClient, SecurityProvider } from '@prisma/client'\nimport winston from 'winston'\nimport Redis from 'ioredis"
  },
  {
    "path": "apps/workers/src/app/__tests__/teller.integration.spec.ts",
    "chars": 4408,
    "preview": "import type { User } from '@prisma/client'\nimport { TellerGenerator } from '../../../../../tools/generators'\nimport { Te"
  },
  {
    "path": "apps/workers/src/app/lib/di.ts",
    "chars": 7230,
    "preview": "import type {\n    IAccountConnectionProcessor,\n    IAccountProcessor,\n    IAccountQueryService,\n    IAccountService,\n   "
  },
  {
    "path": "apps/workers/src/app/lib/email.ts",
    "chars": 1413,
    "preview": "import { ServerClient as PostmarkServerClient } from 'postmark'\nimport nodemailer from 'nodemailer'\nimport type SMTPTran"
  },
  {
    "path": "apps/workers/src/app/lib/logger.ts",
    "chars": 136,
    "preview": "import { createLogger } from '@maybe-finance/server/shared'\n\nconst logger = createLogger({\n    level: 'info',\n})\n\nexport"
  },
  {
    "path": "apps/workers/src/app/lib/prisma.ts",
    "chars": 1686,
    "preview": "import { PrismaClient } from '@prisma/client'\nimport { DbUtil } from '@maybe-finance/server/shared'\nimport globalLogger "
  },
  {
    "path": "apps/workers/src/app/lib/stripe.ts",
    "chars": 162,
    "preview": "import Stripe from 'stripe'\nimport env from '../../env'\n\nconst stripe = new Stripe(env.NX_STRIPE_SECRET_KEY, { apiVersio"
  },
  {
    "path": "apps/workers/src/app/lib/teller.ts",
    "chars": 109,
    "preview": "import { TellerApi } from '@maybe-finance/teller-api'\n\nconst teller = new TellerApi()\n\nexport default teller\n"
  },
  {
    "path": "apps/workers/src/app/services/bull-queue-event-handler.ts",
    "chars": 3991,
    "preview": "import type { PrismaClient, User } from '@prisma/client'\nimport type { Job } from 'bull'\nimport type { Logger } from 'wi"
  },
  {
    "path": "apps/workers/src/app/services/index.ts",
    "chars": 82,
    "preview": "export * from './worker-error.service'\nexport * from './bull-queue-event-handler'\n"
  },
  {
    "path": "apps/workers/src/app/services/worker-error.service.ts",
    "chars": 850,
    "preview": "import type { Logger } from 'winston'\nimport * as Sentry from '@sentry/node'\nimport { ErrorUtil } from '@maybe-finance/s"
  },
  {
    "path": "apps/workers/src/assets/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "apps/workers/src/env.ts",
    "chars": 1136,
    "preview": "import { z } from 'zod'\n\nconst envSchema = z.object({\n    NX_PORT: z.string().default('3334'),\n\n    NX_DATABASE_URL: z.s"
  },
  {
    "path": "apps/workers/src/environments/environment.prod.ts",
    "chars": 53,
    "preview": "export const environment = {\n    production: true,\n}\n"
  },
  {
    "path": "apps/workers/src/environments/environment.ts",
    "chars": 54,
    "preview": "export const environment = {\n    production: false,\n}\n"
  },
  {
    "path": "apps/workers/src/main.ts",
    "chars": 7626,
    "preview": "import express from 'express'\nimport cors from 'cors'\nimport * as Sentry from '@sentry/node'\nimport * as SentryTracing f"
  },
  {
    "path": "apps/workers/src/utils.ts",
    "chars": 1381,
    "preview": "import type { IQueue } from '@maybe-finance/server/shared'\nimport type { JobInformation } from 'bull'\n\nexport async func"
  },
  {
    "path": "apps/workers/tsconfig.app.json",
    "chars": 312,
    "preview": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"outDir\": \"../../dist/out-tsc\",\n        \"module\": \""
  },
  {
    "path": "apps/workers/tsconfig.json",
    "chars": 389,
    "preview": "{\n    \"extends\": \"../../tsconfig.base.json\",\n    \"compilerOptions\": {\n        \"esModuleInterop\": true,\n        \"noImplic"
  },
  {
    "path": "apps/workers/tsconfig.spec.json",
    "chars": 322,
    "preview": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n        \"outDir\": \"../../dist/out-tsc\",\n        \"module\": \""
  },
  {
    "path": "babel.config.json",
    "chars": 30,
    "preview": "{\n    \"babelrcRoots\": [\"*\"]\n}\n"
  },
  {
    "path": "custom-express.d.ts",
    "chars": 608,
    "preview": "import express, { Send, Response, Request } from 'express'\nimport { SharedType } from '@maybe-finance/shared'\n\n// Becaus"
  },
  {
    "path": "docker-compose.test.yml",
    "chars": 1702,
    "preview": "---\nversion: '3.9'\n\nservices:\n    server:\n        env_file: .env\n        container_name: maybe-server\n        profiles: "
  },
  {
    "path": "docker-compose.yml",
    "chars": 1320,
    "preview": "---\nversion: '3.9'\n\nservices:\n    postgres:\n        container_name: postgres\n        profiles: [services]\n        image:"
  },
  {
    "path": "jest.config.ts",
    "chars": 103,
    "preview": "const { getJestProjects } = require('@nrwl/jest')\n\nexport default {\n    projects: getJestProjects(),\n}\n"
  },
  {
    "path": "jest.preset.js",
    "chars": 88,
    "preview": "const nxPreset = require('@nrwl/jest/preset').default\n\nmodule.exports = { ...nxPreset }\n"
  },
  {
    "path": "libs/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "libs/client/features/.babelrc",
    "chars": 206,
    "preview": "{\n    \"presets\": [\n        [\n            \"@nrwl/react/babel\",\n            {\n                \"runtime\": \"automatic\",\n    "
  },
  {
    "path": "libs/client/features/.eslintrc.json",
    "chars": 402,
    "preview": "{\n    \"extends\": [\"plugin:@nrwl/nx/react\", \"../../../.eslintrc.json\"],\n    \"ignorePatterns\": [\"!**/*\"],\n    \"overrides\":"
  },
  {
    "path": "libs/client/features/jest.config.ts",
    "chars": 336,
    "preview": "/* eslint-disable */\nexport default {\n    displayName: 'client-features',\n    preset: '../../../jest.preset.js',\n    tra"
  },
  {
    "path": "libs/client/features/src/account/AccountMenu.tsx",
    "chars": 1328,
    "preview": "import type { SharedType } from '@maybe-finance/shared'\nimport { useAccountContext } from '@maybe-finance/client/shared'"
  },
  {
    "path": "libs/client/features/src/account/AccountsSidebar.tsx",
    "chars": 14404,
    "preview": "import type { AccordionRowProps } from '@maybe-finance/design-system'\nimport type { SharedType } from '@maybe-finance/sh"
  },
  {
    "path": "libs/client/features/src/account/PageTitle.tsx",
    "chars": 1834,
    "preview": "import type { SharedType } from '@maybe-finance/shared'\nimport { SmallDecimals, TrendBadge } from '@maybe-finance/client"
  },
  {
    "path": "libs/client/features/src/account/index.ts",
    "chars": 120,
    "preview": "export * from './AccountMenu'\nexport { default as AccountSidebar } from './AccountsSidebar'\nexport * from './PageTitle'\n"
  },
  {
    "path": "libs/client/features/src/accounts-list/Account.tsx",
    "chars": 5768,
    "preview": "import type { SharedType } from '@maybe-finance/shared'\nimport cn from 'classnames'\nimport { Button, Menu, Toggle, Toolt"
  },
  {
    "path": "libs/client/features/src/accounts-list/AccountDevTools.tsx",
    "chars": 5264,
    "preview": "import Link from 'next/link'\nimport { useState } from 'react'\nimport {\n    useAccountConnectionApi,\n    useInstitutionAp"
  },
  {
    "path": "libs/client/features/src/accounts-list/AccountGroup.tsx",
    "chars": 1756,
    "preview": "import { Disclosure } from '@headlessui/react'\nimport { Button } from '@maybe-finance/design-system'\nimport classNames f"
  },
  {
    "path": "libs/client/features/src/accounts-list/AccountGroupContainer.tsx",
    "chars": 533,
    "preview": "import type { PropsWithChildren } from 'react'\n\nexport type AccountGroupContainerProps = PropsWithChildren<{\n    title: "
  },
  {
    "path": "libs/client/features/src/accounts-list/ConnectedAccountGroup.tsx",
    "chars": 7703,
    "preview": "import { Button, Menu } from '@maybe-finance/design-system'\nimport type { SharedType } from '@maybe-finance/shared'\nimpo"
  },
  {
    "path": "libs/client/features/src/accounts-list/DeleteConnectionDialog.tsx",
    "chars": 1850,
    "preview": "import { useAccountConnectionApi } from '@maybe-finance/client/shared'\nimport { Alert, Button, Dialog } from '@maybe-fin"
  },
  {
    "path": "libs/client/features/src/accounts-list/DisconnectedAccountGroup.tsx",
    "chars": 2549,
    "preview": "import type { SharedType } from '@maybe-finance/shared'\nimport { Menu } from '@maybe-finance/design-system'\nimport Accou"
  },
  {
    "path": "libs/client/features/src/accounts-list/ManualAccountGroup.tsx",
    "chars": 1317,
    "preview": "import type { SharedType } from '@maybe-finance/shared'\nimport { DateTime } from 'luxon'\nimport maxBy from 'lodash/maxBy"
  },
  {
    "path": "libs/client/features/src/accounts-list/index.ts",
    "chars": 220,
    "preview": "export * from './Account'\nexport * from './AccountGroupContainer'\nexport * from './DisconnectedAccountGroup'\nexport * fr"
  },
  {
    "path": "libs/client/features/src/accounts-manager/AccountTypeGrid.tsx",
    "chars": 2423,
    "preview": "import type { IconType } from 'react-icons'\nimport type { BoxIconVariant } from '@maybe-finance/client/shared'\n\nimport {"
  }
]

// ... and 804 more files (download for full content)

About this extraction

This page contains the full source code of the maybe-finance/maybe-archive GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1004 files (2.6 MB), approximately 729.4k tokens, and a symbol index with 1573 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!