Skip to content

chore: resolve strict TS errors and missing JS extensions for NodeNext ESM resolution - #83

Merged
pramodnarayana merged 1 commit into
developmentfrom
feature/esm-migration-option-a
Mar 7, 2026
Merged

pramodnarayana merged 1 commit into
developmentfrom
feature/esm-migration-option-a

Conversation

@pramodnarayana

@pramodnarayana pramodnarayana commented Mar 7, 2026 •

Copy link
Copy Markdown
Owner

@coderabbitai skip

Summary by CodeRabbit

  • New Features

    • Added PII cleanup job for sessions that automatically anonymizes user IP addresses and user agents for sessions older than 30 days with audit logging.
  • Chores

    • Switched build system to SWC for faster compilation and improved type checking during builds.
    • Upgraded module system infrastructure to ES Modules for better compatibility.

@coderabbitai

coderabbitai Bot commented Mar 7, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR migrates the monorepo from CommonJS to ESM by updating TypeScript/build configurations, appending explicit .js file extensions to all import paths, converting runtime imports to type-only imports where appropriate, adding "type": "module" to package manifests, switching the bundler from Webpack to SWC, and consolidating identity schema re-exports to use @nexiom/database as the source.

Changes

Cohort / File(s) Summary
Build Configuration
apps/api/nest-cli.json, apps/api/tsconfig.json, packages/auth/tsconfig.build.json, packages/identity/tsconfig.json, packages/pieces/quickbooks/tsconfig.json, packages/pieces/salesforce/tsconfig.json, tsconfig.base.json
Switched module system from CommonJS to NodeNext in TypeScript compiler options. Updated apps/api/nest-cli.json to replace Webpack with SWC bundler and enable type checking.
ESM Module Declarations
apps/api/package.json, packages/auth/package.json, packages/cache/package.json, packages/connectors/package.json, packages/database/package.json, packages/dbmanager/package.json, packages/identity/package.json
Added "type": "module" to multiple package.json files to declare packages as ES modules. Reorganized export maps and top-level configuration blocks in packages/connectors and packages/database.
Import Path Extensions (apps/api core)
apps/api/src/app/*, apps/api/src/db/*, apps/api/src/main.ts, apps/api/src/common/utils/headers.util.spec.ts
Updated all relative import statements throughout apps/api to include explicit .js file extensions for ESM-compatible module resolution.
Import Path Extensions (apps/api modules)
apps/api/src/modules/connections/*, apps/api/src/modules/dbmanager/*, apps/api/src/modules/email/*, apps/api/src/modules/identity/*, apps/api/src/modules/storage-resolver/*, apps/api/src/modules/trigger/*
Systematically updated all local module imports to use .js extensions across identity, connections, trigger, email, and storage modules.
Import Path Extensions (packages & scripts)
apps/api/src/scripts/admin-bootstrap.ts, apps/api/test/*, packages/auth/src/*, packages/cache/src/cache.module.ts, packages/connectors/src/*, packages/database/src/*, packages/dbmanager/src/*, packages/identity/src/**/*
Extended .js file extension updates across all package source files, test utilities, and integration test specs.
Type-only Import Conversions
apps/api/src/modules/identity/auth/*, apps/api/src/modules/identity/invitations/*, apps/api/src/modules/identity/roles/*, apps/api/src/modules/identity/system-admin/*, apps/api/src/modules/identity/tenants/*, apps/api/src/modules/identity/users/*, packages/identity/src/adapters/*
Converted value imports to type-only imports for interfaces and types (RequestAuthContext, ITenantProvider, ITenantProvider, IRoleProvider, User, IAuthProvider) to reduce runtime dependencies.
Schema Re-exports & Sources
apps/api/src/db/schema.ts, packages/identity/src/index.ts, packages/identity/src/interfaces/index.ts, packages/identity/src/adapters/*, packages/database/src/index.ts, packages/database/src/client.ts
Changed identity schema re-exports to source from @nexiom/database instead of @nexiom/identity. Updated re-export paths to use .js extensions and consolidated index barrel exports for interfaces.
Interface & Class Signature Updates
packages/identity/src/interfaces/auth-provider.interface.ts, packages/connectors/src/crypto/encryption.service.ts, apps/api/src/modules/identity/users/users.controller.ts
Added createUser(input: CreateUserInput): Promise<User> method to IAuthProvider interface. Removed implements EncryptionService from AesEncryptionService class. Enhanced UserListItem type with explicit typing for invitation entries (id, email, role, status, createdAt, etc.).
Import Source Refactoring
packages/connectors/src/oauth/token-manager.service.ts, apps/api/src/modules/connections/connectors.service.ts, apps/api/src/modules/trigger/trigger-executor.service.ts, apps/api/src/modules/storage-resolver/storage-resolver.service.ts
Replaced value imports of DatabaseManager with type-only imports. Updated token and database connection references to use .js extensions or alternative import sources.
ESLint & Config Annotations
apps/api/src/modules/identity/invitations/invitations.controller.spec.ts, apps/api/src/modules/trigger/dlq-processor.service.spec.ts, apps/api/test/app.e2e-spec.ts, packages/identity/src/adapters/drizzle-user.adapter.spec.ts
Added/repositioned ESLint directives (no-unsafe-argument, no-unsafe-return, unbound-method) and TypeScript comments for type resolution issues in test files.
Technical Debt Documentation
TECHNICAL_DEBT.md
Renamed high-priority item from "Permission Caching Architecture" to "PII Cleanup Job for Sessions" with detailed implementation guidance including anonymizeIp/anonymizeUserAgent functions, @nestjs/schedule integration, daily cleanup of 30+ day old sessions, and Drizzle migration for backfilling.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Hops excitedly

From CommonJS paths we hop along,
To ESM where modules belong!
With .js extensions, shiny and bright,
Type-only imports make the code just right.
SWC replaces Webpack's weighted load,
NodeNext guides us down the modular road! 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore: resolve strict TS errors and missing JS extensions for NodeNext ESM resolution' clearly summarizes the main change—migrating to NodeNext ESM with explicit .js extensions.

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

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

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

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/api/src/main.ts (1)

51-52: 🧹 Nitpick | 🔵 Trivial

Comment may be outdated after ESM migration.

The comment states "Top-level await is not available in CommonJS," but since this PR migrates to ESM, top-level await is now supported. The start() wrapper is still valid but no longer strictly necessary.

♻️ Optional: Simplify bootstrap with top-level await
-// Top-level await is not available in CommonJS.
-const start = async () => {
-  try {
-    await bootstrap();
-  } catch (err) {
-    Logger.error('Bootstrap failed', err);
-    process.exit(1);
-  }
-};
-
-void start();
+try {
+  await bootstrap();
+} catch (err) {
+  Logger.error('Bootstrap failed', err);
+  process.exit(1);
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/main.ts` around lines 51 - 52, The comment "Top-level await is
not available in CommonJS" is outdated after the ESM migration; update or remove
it and either (a) remove the unnecessary async wrapper function start() by
inlining its startup logic at top-level using top-level await, or (b) update the
comment to reflect that ESM supports top-level await while keeping start() if
you prefer the wrapper for clarity; locate the async start() function and adjust
its surrounding comment and usage accordingly.
apps/api/src/db/database-manager.spec.ts (1)

61-61: ⚠️ Potential issue | 🟡 Minor

Align mock path with actual import path.

The mock path '../constants' should match the import path '../constants.js' in database-manager.ts (line 225). With NodeNext module resolution enabled (tsconfig.json), mismatched paths may prevent proper mock interception.

Proposed fix
-vi.mock('../constants', () => constantMocks);
+vi.mock('../constants.js', () => constantMocks);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/db/database-manager.spec.ts` at line 61, The test's mock path
string doesn't match the module import used by DatabaseManager; update the
vi.mock call in database-manager.spec.ts so the mocked module path exactly
matches the import in database-manager.ts (change vi.mock('../constants', () =>
constantMocks) to use '../constants.js'), ensuring the mock intercepts correctly
under NodeNext resolution; also verify any other mocks use the .js suffix to
match their real imports like the one in database-manager.ts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/nest-cli.json`:
- Around line 8-9: The nest-cli configuration sets "builder": "swc" (and
"typeCheck": true) but the required CLI package is missing; add the missing
devDependency `@swc/cli` to package.json devDependencies and install it (e.g., run
npm install -D `@swc/cli`) so the SWC builder in nest-cli.json can run correctly
with type checking enabled.

In `@apps/api/src/db/reset-e2e.ts`:
- Around line 6-9: The runtime error comes from using __dirname in ESM; replace
its usage in the dotEnv.config call (currently: dotEnv.config({ path:
path.resolve(__dirname, '../../.env') })) by deriving a dirname from
import.meta.url (use fileURLToPath(import.meta.url) and path.dirname(...) to
compute the directory) and pass that resolved path into dotEnv.config; also
ensure fileURLToPath is imported from 'url' and remove reliance on the undefined
__dirname symbol.

In `@apps/api/src/modules/connections/connections/callback.controller.spec.ts`:
- Around line 3-7: The import block currently brings Request, Response and
Mocked in as runtime imports; change them to type-only imports so they are
erased in emitted ESM: replace the plain imports of Request and Response from
'express' with type-only imports (type { Request, Response }) and change the
Mocked import from 'vitest' to a type-only import (type { Mocked }), leaving
OAuthCallbackController, ProviderRegistryService, vi, describe, it, expect,
beforeEach and OauthStateService as value imports.

In `@apps/api/src/modules/identity/system-admin/system-admin.controller.spec.ts`:
- Around line 14-15: The test's mock registration uses vi.mock() with the wrong
module specifier — update the mocked path used in the vi.mock call to exactly
match the import ('../../../constants.js') so Vitest intercepts the import;
locate the vi.mock('../../../constants') call in system-admin.controller.spec.ts
and change the specifier to '../../../constants.js' to match the import that
brings in the constants module.

In `@apps/api/src/modules/identity/users/users.controller.ts`:
- Around line 125-145: The mapping for invitedUsers is assigning inv.role (type
string | null) into UserListItem.role which is declared as string; normalize the
nullable value or adjust the type: either change the UserListItem.role
definition to allow string | null, or in the pendingInvitations.map normalize
inv.role to a concrete string (e.g., inv.role ?? 'member' or another default)
before returning the object; update the mapping in the invitedUsers creation
(pendingInvitations, inv) so UserListItem.role receives a non-null string to
satisfy the type.
- Around line 16-17: The import currently brings User as a runtime value; change
it to a type-only import so runtime providers remain separate: keep
USER_PROVIDER and TENANT_PROVIDER as value imports but import User using the
TypeScript type-only form alongside ITenantProvider and IUserProvider, and
update any references in the UserListItem type to use the type import (symbols:
USER_PROVIDER, TENANT_PROVIDER, User, ITenantProvider, IUserProvider,
UserListItem).

In `@apps/api/src/modules/trigger/trigger.module.ts`:
- Around line 12-13: Change the current runtime import of DatabaseManager to a
type-only import: replace the value import of DatabaseManager from
'@nexiom/dbmanager' with a type import so it won't emit a runtime require;
update the import statement that currently sits alongside DB_MANAGER in
trigger.module.ts to use "import type { DatabaseManager }" so the
factory/provider signature (the provider factory that references DatabaseManager
in its parameter type) retains type information without introducing a runtime
dependency.

In `@apps/api/src/scripts/admin-bootstrap.ts`:
- Line 8: Import NodePgDatabase as a type-only import so it is erased from
emitted JS: change the import that currently brings in NodePgDatabase from
'drizzle-orm/node-postgres' to a type import for NodePgDatabase only, leaving
the runtime import for drizzle intact; update the import statement that includes
NodePgDatabase (used in the type annotations at NodePgDatabase references on the
bootstrap functions) to use "import type { NodePgDatabase } ..." while keeping
"import { drizzle } ..." as a normal import.
- Around line 8-18: Replace CommonJS __dirname usage by deriving the directory
from import.meta.url and make NodePgDatabase a type-only import: add an ESM-safe
dirname like "const __filename = fileURLToPath(import.meta.url); const __dirname
= path.dirname(__filename);" (import fileURLToPath from 'url' and path from
'path') and change any path.resolve(__dirname, ...) calls used before
dotenv.config() to use that __dirname variable; also change the drizzle import
to a type-only import (e.g., import { drizzle, type NodePgDatabase } from
'drizzle-orm/node-postgres') so NodePgDatabase is not imported as a runtime
value.

In `@packages/connectors/src/crypto/encryption.service.ts`:
- Line 7: Restore the class inheritance so AesEncryptionService extends the
abstract EncryptionService to re-enable compile-time contract checks; update the
class declaration for AesEncryptionService to explicitly extend
EncryptionService (keeping the existing encrypt and decrypt method
implementations) so DI config that provides EncryptionService via useClass:
AesEncryptionService remains valid and type-safe.

In `@packages/database/package.json`:
- Around line 7-24: Add explicit "types" conditions to the package.json
"exports" subpaths so TypeScript can resolve declarations: update the root
export (".") to include "types": "./dist/index.d.ts" and add "types" entries to
each subpath export such as "./schema/identity", "./schema/tenant" (and the
duplicate "./dist/schema/identity") pointing to their corresponding declaration
files (e.g., "./dist/schema/identity.d.ts" and "./dist/schema/tenant.d.ts");
ensure the file names match the built .d.ts outputs and keep both
"import"/"default" and the new "types" conditions for each export entry.

In `@packages/identity/src/adapters/drizzle-user.adapter.spec.ts`:
- Line 1: Add a file-level ESLint disable for unbound-method to match the
existing file-level no-unsafe-return suppression and remove the inline disable
near the affected assertion; specifically, add "/* eslint-disable
`@typescript-eslint/unbound-method` */" at the top of the test file (same area
where /* eslint-disable `@typescript-eslint/no-unsafe-return` */ lives) so mock
method assertions like expect(db.update).not.toHaveBeenCalled() and other
expect(db.xxx) calls (seen around the inline disable at the current inline
suppression and elsewhere) no longer require inline disables.

In `@packages/identity/src/services/permission-seeder.spec.ts`:
- Around line 197-198: The mocks registered with vi.doMock/vi.doUnmock are using
the wrong module specifier ("../constants") so they don't apply to the ESM
import ("../constants.js"); update every vi.doMock("../constants") and
corresponding vi.doUnmock("../constants") in this test (including the calls
around the vi.doMock at lines shown) to use the exact ESM specifier
"../constants.js" so the mocks match the imports used by rbac-seeding.js.

In `@packages/pieces/salesforce/tsconfig.json`:
- Line 11: Update the tsconfig "module" value from "NodeNext" to the lowercase
"nodenext" for consistency with TypeScript docs and the project's
tsconfig.lib.json; locate the "module" property in the
packages/pieces/salesforce tsconfig and replace "NodeNext" with "nodenext" (the
JSON key is "module") so casing matches the documented convention.

In `@TECHNICAL_DEBT.md`:
- Around line 23-26: Decide and document a single PII retention model and make
the docs and artifacts consistent: either (A) choose immediate minimization —
keep the `anonymizeIp` and `anonymizeUserAgent` helpers and remove the
`runPIICleanup` job, background module, and backfill migration; or (B) choose
time-bounded retention — keep raw IP/user-agent on insert, remove or rename the
pre-insert anonymization helpers, and implement `runPIICleanup` inside the
`background`/`jobs` module (using `@nestjs/schedule`) to anonymize sessions older
than 30 days and add a Drizzle migration to backfill existing old sessions;
update TECHNICAL_DEBT.md so it clearly states which model is chosen and lists
the matching set of tasks (helpers vs job + migration) and references to
`anonymizeIp`, `anonymizeUserAgent`, `runPIICleanup`, and the background/jobs
module.

---

Outside diff comments:
In `@apps/api/src/db/database-manager.spec.ts`:
- Line 61: The test's mock path string doesn't match the module import used by
DatabaseManager; update the vi.mock call in database-manager.spec.ts so the
mocked module path exactly matches the import in database-manager.ts (change
vi.mock('../constants', () => constantMocks) to use '../constants.js'), ensuring
the mock intercepts correctly under NodeNext resolution; also verify any other
mocks use the .js suffix to match their real imports like the one in
database-manager.ts.

In `@apps/api/src/main.ts`:
- Around line 51-52: The comment "Top-level await is not available in CommonJS"
is outdated after the ESM migration; update or remove it and either (a) remove
the unnecessary async wrapper function start() by inlining its startup logic at
top-level using top-level await, or (b) update the comment to reflect that ESM
supports top-level await while keeping start() if you prefer the wrapper for
clarity; locate the async start() function and adjust its surrounding comment
and usage accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c1573f1e-c821-466d-a692-5e827600fa54

📥 Commits

Reviewing files that changed from the base of the PR and between 6516e06 and c76d578.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (138)
  • TECHNICAL_DEBT.md
  • apps/api/nest-cli.json
  • apps/api/package.json
  • apps/api/src/app/app.controller.spec.ts
  • apps/api/src/app/app.controller.ts
  • apps/api/src/app/app.module.ts
  • apps/api/src/app/app.service.spec.ts
  • apps/api/src/common/utils/headers.util.spec.ts
  • apps/api/src/db/database-manager.spec.ts
  • apps/api/src/db/database-manager.ts
  • apps/api/src/db/db-cli.ts
  • apps/api/src/db/db.module.ts
  • apps/api/src/db/db.provider.ts
  • apps/api/src/db/reset-e2e.ts
  • apps/api/src/db/schema.spec.ts
  • apps/api/src/db/schema.ts
  • apps/api/src/main.ts
  • apps/api/src/modules/connections/connections.module.ts
  • apps/api/src/modules/connections/connections/callback.controller.spec.ts
  • apps/api/src/modules/connections/connections/callback.controller.ts
  • apps/api/src/modules/connections/connections/connectors.controller.spec.ts
  • apps/api/src/modules/connections/connections/connectors.controller.ts
  • apps/api/src/modules/connections/connections/token-refresh.service.spec.ts
  • apps/api/src/modules/connections/connections/token-refresh.service.ts
  • apps/api/src/modules/connections/connectors.service.spec.ts
  • apps/api/src/modules/connections/connectors.service.ts
  • apps/api/src/modules/connections/oauth-state.service.spec.ts
  • apps/api/src/modules/dbmanager/dbmanager.module.ts
  • apps/api/src/modules/email/console-email.service.spec.ts
  • apps/api/src/modules/email/console-email.service.ts
  • apps/api/src/modules/email/email.module.ts
  • apps/api/src/modules/email/nodemailer.service.spec.ts
  • apps/api/src/modules/email/nodemailer.service.ts
  • apps/api/src/modules/identity/auth/auth.controller.coverage.spec.ts
  • apps/api/src/modules/identity/auth/auth.controller.spec.ts
  • apps/api/src/modules/identity/auth/auth.controller.ts
  • apps/api/src/modules/identity/auth/auth.module.ts
  • apps/api/src/modules/identity/auth/platform.guard.spec.ts
  • apps/api/src/modules/identity/auth/platform.guard.ts
  • apps/api/src/modules/identity/auth/system-admin.guard.spec.ts
  • apps/api/src/modules/identity/auth/system-admin.guard.ts
  • apps/api/src/modules/identity/invitations/invitations.controller.spec.ts
  • apps/api/src/modules/identity/invitations/invitations.controller.ts
  • apps/api/src/modules/identity/invitations/invitations.module.ts
  • apps/api/src/modules/identity/invitations/invitations.service.spec.ts
  • apps/api/src/modules/identity/invitations/invitations.service.ts
  • apps/api/src/modules/identity/invitations/invitations.validation.spec.ts
  • apps/api/src/modules/identity/roles/roles.controller.spec.ts
  • apps/api/src/modules/identity/roles/roles.controller.ts
  • apps/api/src/modules/identity/roles/roles.controller.visibility.spec.ts
  • apps/api/src/modules/identity/roles/roles.module.ts
  • apps/api/src/modules/identity/system-admin/system-admin.controller.spec.ts
  • apps/api/src/modules/identity/system-admin/system-admin.controller.ts
  • apps/api/src/modules/identity/system-admin/system-admin.module.ts
  • apps/api/src/modules/identity/system-admin/system-admin.validation.spec.ts
  • apps/api/src/modules/identity/system-admin/system-admin.validation.ts
  • apps/api/src/modules/identity/tenants/tenants.controller.spec.ts
  • apps/api/src/modules/identity/tenants/tenants.controller.ts
  • apps/api/src/modules/identity/tenants/tenants.module.ts
  • apps/api/src/modules/identity/tenants/tenants.validation.spec.ts
  • apps/api/src/modules/identity/users/users.controller.spec.ts
  • apps/api/src/modules/identity/users/users.controller.ts
  • apps/api/src/modules/identity/users/users.module.ts
  • apps/api/src/modules/identity/users/users.validation.spec.ts
  • apps/api/src/modules/storage-resolver/storage-resolver.module.ts
  • apps/api/src/modules/storage-resolver/storage-resolver.service.spec.ts
  • apps/api/src/modules/storage-resolver/storage-resolver.service.ts
  • apps/api/src/modules/trigger/dlq-processor.service.spec.ts
  • apps/api/src/modules/trigger/dlq-processor.service.ts
  • apps/api/src/modules/trigger/piece-registry.service.spec.ts
  • apps/api/src/modules/trigger/poller.service.spec.ts
  • apps/api/src/modules/trigger/poller.service.ts
  • apps/api/src/modules/trigger/redis-trigger-store.spec.ts
  • apps/api/src/modules/trigger/trigger-executor.service.spec.ts
  • apps/api/src/modules/trigger/trigger-executor.service.ts
  • apps/api/src/modules/trigger/trigger.module.ts
  • apps/api/src/modules/trigger/webhooks.controller.spec.ts
  • apps/api/src/modules/trigger/webhooks.controller.ts
  • apps/api/src/scripts/admin-bootstrap.ts
  • apps/api/test/app.e2e-spec.ts
  • apps/api/test/invitations.e2e-spec.ts
  • apps/api/test/system-admin.tenants.e2e-spec.ts
  • apps/api/tsconfig.json
  • package.json
  • packages/auth/package.json
  • packages/auth/src/auth.module.ts
  • packages/auth/src/guards/auth.guard.ts
  • packages/auth/src/guards/permissions.guard.ts
  • packages/auth/src/index.ts
  • packages/auth/tsconfig.build.json
  • packages/cache/package.json
  • packages/cache/src/cache.module.ts
  • packages/connectors/package.json
  • packages/connectors/src/crypto/encryption.service.spec.ts
  • packages/connectors/src/crypto/encryption.service.ts
  • packages/connectors/src/oauth/token-manager.service.ts
  • packages/database/package.json
  • packages/database/src/client.ts
  • packages/database/src/database.module.ts
  • packages/database/src/index.ts
  • packages/database/src/schema/storage_registry.ts
  • packages/database/src/schema/tenant.ts
  • packages/dbmanager/package.json
  • packages/dbmanager/src/impl/sql-database-manager.ts
  • packages/dbmanager/src/index.ts
  • packages/identity/package.json
  • packages/identity/src/adapters/better-auth.abac.spec.ts
  • packages/identity/src/adapters/better-auth.adapter.spec.ts
  • packages/identity/src/adapters/better-auth.adapter.ts
  • packages/identity/src/adapters/drizzle-permission.adapter.spec.ts
  • packages/identity/src/adapters/drizzle-permission.adapter.ts
  • packages/identity/src/adapters/drizzle-role.adapter.spec.ts
  • packages/identity/src/adapters/drizzle-role.adapter.ts
  • packages/identity/src/adapters/drizzle-tenant.adapter.spec.ts
  • packages/identity/src/adapters/drizzle-tenant.adapter.ts
  • packages/identity/src/adapters/drizzle-user.adapter.spec.ts
  • packages/identity/src/adapters/drizzle-user.adapter.ts
  • packages/identity/src/background/pii-cleanup.spec.ts
  • packages/identity/src/background/pii-cleanup.ts
  • packages/identity/src/better-auth.config.ts
  • packages/identity/src/identity.module.spec.ts
  • packages/identity/src/identity.module.ts
  • packages/identity/src/index.spec.ts
  • packages/identity/src/index.ts
  • packages/identity/src/interfaces/auth-provider.interface.ts
  • packages/identity/src/interfaces/index.ts
  • packages/identity/src/interfaces/permission-provider.interface.ts
  • packages/identity/src/interfaces/tenant-provider.interface.ts
  • packages/identity/src/interfaces/user-provider.interface.ts
  • packages/identity/src/services/permission-seeder.spec.ts
  • packages/identity/src/services/permission-seeder.ts
  • packages/identity/src/utils/name-generator.spec.ts
  • packages/identity/src/utils/rbac-seeding.ts
  • packages/identity/src/utils/role-visibility.ts
  • packages/identity/tsconfig.json
  • packages/pieces/quickbooks/tsconfig.json
  • packages/pieces/salesforce/tsconfig.json
  • tsconfig.base.json

Comment thread apps/api/nest-cli.json
Comment on lines +8 to +9
"builder": "swc",
"typeCheck": true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if `@swc/cli` and `@swc/core` are in package.json dependencies
fd -t f "package.json" apps/api --exec cat {} \; | jq '.devDependencies | keys | map(select(startswith("@swc")))' 2>/dev/null || echo "Check apps/api/package.json manually"

Repository: pramodnarayana/nexiom

Length of output: 82


🏁 Script executed:

#!/bin/bash
# Get complete list of all `@swc` packages in devDependencies
fd -t f "package.json" apps/api --exec cat {} \; | jq '.devDependencies | with_entries(select(.key | startswith("@swc")))'

Repository: pramodnarayana/nexiom

Length of output: 94


🌐 Web query:

NestJS SWC builder configuration required dependencies packages

💡 Result:

Standard NestJS app (Nest CLI SWC builder)

Install (dev deps):

  • @swc/core
  • @swc/cli [1][2]
npm i -D `@swc/core` `@swc/cli`

Enable in nest-cli.json:

{
  "compilerOptions": { "builder": "swc" }
}

[1]


Monorepo (Nest CLI uses webpack; wire SWC via swc-loader)

Install (dev deps):

  • swc-loader (and keep @swc/core available because the loader relies on SWC) [1]
npm i -D swc-loader `@swc/core`

Then point webpack to Nest’s SWC defaults (example shown in the Nest docs). [1]


If you also want type-checking with SWC

SWC doesn’t type-check; Nest CLI runs tsc in parallel when you enable type checking. [1]
(So make sure typescript is installed in your project, as in a normal Nest setup.)

Enable:

  • CLI: nest start -b swc --type-check, or
  • nest-cli.json: "compilerOptions": { "builder": "swc", "typeCheck": true } [1]

Sources: [1] https://docs.nestjs.com/recipes/swc, [2] https://tessl.io/registry/tessl/npm-nestjs--cli/11.0.0/files/docs/application-building.md


Install @swc/cli to complete SWC builder configuration.

The nest-cli.json configuration specifies "builder": "swc", but the required dependency @swc/cli is missing from devDependencies. According to NestJS documentation, both @swc/core and @swc/cli are required for the SWC builder to function. Currently only @swc/core is installed.

Add @swc/cli to devDependencies:

npm install -D `@swc/cli`

The "typeCheck": true setting is correctly configured and will enable TypeScript type checking during SWC builds once the dependency is installed.

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

In `@apps/api/nest-cli.json` around lines 8 - 9, The nest-cli configuration sets
"builder": "swc" (and "typeCheck": true) but the required CLI package is
missing; add the missing devDependency `@swc/cli` to package.json devDependencies
and install it (e.g., run npm install -D `@swc/cli`) so the SWC builder in
nest-cli.json can run correctly with type checking enabled.

Comment on lines +6 to 9
import { ALL_PERMISSIONS, isSystemPermission } from '../constants.js';

// Load .env from apps/api root
dotEnv.config({ path: path.resolve(__dirname, '../../.env') });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

__dirname is not available in ES modules — this will cause a runtime error.

With the migration to ESM ("type": "module"), the __dirname global is no longer defined. Line 9 will throw ReferenceError: __dirname is not defined at runtime.

🐛 Proposed fix using import.meta.url
 import * as dotEnv from 'dotenv';
-import * as path from 'node:path';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
 import { ALL_PERMISSIONS, isSystemPermission } from '../constants.js';

+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
 // Load .env from apps/api root
 dotEnv.config({ path: path.resolve(__dirname, '../../.env') });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/db/reset-e2e.ts` around lines 6 - 9, The runtime error comes
from using __dirname in ESM; replace its usage in the dotEnv.config call
(currently: dotEnv.config({ path: path.resolve(__dirname, '../../.env') })) by
deriving a dirname from import.meta.url (use fileURLToPath(import.meta.url) and
path.dirname(...) to compute the directory) and pass that resolved path into
dotEnv.config; also ensure fileURLToPath is imported from 'url' and remove
reliance on the undefined __dirname symbol.

Comment on lines +3 to +7
import { OAuthCallbackController } from './callback.controller.js';
import { ProviderRegistryService } from '@nexiom/connectors';
import { Request, Response } from 'express';
import { vi, describe, it, expect, beforeEach, Mocked } from 'vitest';
import { OauthStateService } from '../oauth-state.service';
import { OauthStateService } from '../oauth-state.service.js';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Finish the type-only cleanup in this import block.

Request, Response, and Mocked are only used in type positions here. Keeping them as value imports preserves avoidable runtime imports in the emitted ESM.

♻️ Proposed fix
 import { Test, TestingModule } from '@nestjs/testing';
 import { OAuthCallbackController } from './callback.controller.js';
 import { ProviderRegistryService } from '@nexiom/connectors';
-import { Request, Response } from 'express';
-import { vi, describe, it, expect, beforeEach, Mocked } from 'vitest';
+import type { Request, Response } from 'express';
+import { vi, describe, it, expect, beforeEach } from 'vitest';
+import type { Mocked } from 'vitest';
 import { OauthStateService } from '../oauth-state.service.js';
 import { ConfigService } from '@nestjs/config';
📝 Committable suggestion

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

Suggested change
import { OAuthCallbackController } from './callback.controller.js';
import { ProviderRegistryService } from '@nexiom/connectors';
import { Request, Response } from 'express';
import { vi, describe, it, expect, beforeEach, Mocked } from 'vitest';
import { OauthStateService } from '../oauth-state.service';
import { OauthStateService } from '../oauth-state.service.js';
import { OAuthCallbackController } from './callback.controller.js';
import { ProviderRegistryService } from '@nexiom/connectors';
import type { Request, Response } from 'express';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import type { Mocked } from 'vitest';
import { OauthStateService } from '../oauth-state.service.js';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/modules/connections/connections/callback.controller.spec.ts`
around lines 3 - 7, The import block currently brings Request, Response and
Mocked in as runtime imports; change them to type-only imports so they are
erased in emitted ESM: replace the plain imports of Request and Response from
'express' with type-only imports (type { Request, Response }) and change the
Mocked import from 'vitest' to a type-only import (type { Mocked }), leaving
OAuthCallbackController, ProviderRegistryService, vi, describe, it, expect,
beforeEach and OauthStateService as value imports.

Comment on lines +14 to +15
} from '../../../constants.js';
import { SystemAdminGuard } from '../auth/system-admin.guard.js';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "system-admin.controller.spec.ts" -type f

Repository: pramodnarayana/nexiom

Length of output: 141


🏁 Script executed:

cat -n apps/api/src/modules/identity/system-admin/system-admin.controller.spec.ts | head -35

Repository: pramodnarayana/nexiom

Length of output: 1372


🌐 Web query:

Vitest vi.mock ESM module specifier path matching documentation

💡 Result:

Vitest’s ESM mocking is keyed off the module ID/specifier string Vitest registers for the import, so your vi.mock(...) argument must refer to the same module specifier (i.e., resolve to the same file/module ID) that your code under test imports.

Where this is documented (official docs):

  • vi.mock API (ESM-specific notes):
    • Examples consistently include explicit ESM file extensions (e.g. ./path/to/module.js), and it notes Vitest “still operates on a string” under the hood (even when you pass vi.mock(import(...))). It also warns that if you use TS paths aliases, you may need to use the corresponding relative path instead (e.g. import('./path/to/module.js') instead of import('@/module')). [1]
  • Mocking Modules guide (how Vitest wires ESM mocks):
    • Explains Vitest rewrites ESM imports and uses a wrapper to ensure the mock is resolved before the module import is evaluated—i.e., mocking is tied to the module import/ID Vitest sees. [2]
  • Config deps.moduleDirectories (how Vitest decides what a “module path” matches):
    • States this option affects vi.mock: when no factory is provided and the path you’re mocking matches one of the configured moduleDirectories, Vitest will look for __mocks__ accordingly—reinforcing that matching is based on the mocked path/ID. [3]

Practical takeaway: in ESM, ensure the vi.mock() specifier matches what your code imports (including extension/relative-vs-alias), or use vi.mock(import('./exact/path.js')) to keep it aligned. [1]

References:
[1] Vitest API: vi / vi.mock – https://vitest.dev/api/vi (vitest.dev)
[2] Vitest Guide: Mocking Modules – https://vitest.dev/guide/mocking/modules.html (vitest.dev)
[3] Vitest v2 Config: deps.moduleDirectories (mentions vi.mock path matching) – https://v2.vitest.dev/config/ (v2.vitest.dev)

Citations:


Update the mocked module path to match the import specifier.

Line 14 imports from '../../../constants.js' with the .js extension, but line 23 mocks '../../../constants' without it. In ESM, Vitest's vi.mock() registers mocks by the exact module specifier string—if the paths don't match, the mock won't intercept the import and the real module will load silently instead of the stub. Align the mock path with the import by adding .js:

Proposed fix
-vi.mock('../../../constants', () => ({
+vi.mock('../../../constants.js', () => ({
   getRequiredAdminRoleId: vi.fn(() => 'admin-role-id'),
   getRequiredOwnerRoleId: vi.fn(() => 'owner-role-id'),
   getRequiredSystemTenantId: vi.fn(
     () => '00000000-0000-0000-0000-000000000000',
   ),
   getRequiredMemberRoleId: vi.fn(() => 'member-role-id'),
 }));
📝 Committable suggestion

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

Suggested change
} from '../../../constants.js';
import { SystemAdminGuard } from '../auth/system-admin.guard.js';
vi.mock('../../../constants.js', () => ({
getRequiredAdminRoleId: vi.fn(() => 'admin-role-id'),
getRequiredOwnerRoleId: vi.fn(() => 'owner-role-id'),
getRequiredSystemTenantId: vi.fn(
() => '00000000-0000-0000-0000-000000000000',
),
getRequiredMemberRoleId: vi.fn(() => 'member-role-id'),
}));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/modules/identity/system-admin/system-admin.controller.spec.ts`
around lines 14 - 15, The test's mock registration uses vi.mock() with the wrong
module specifier — update the mocked path used in the vi.mock call to exactly
match the import ('../../../constants.js') so Vitest intercepts the import;
locate the vi.mock('../../../constants') call in system-admin.controller.spec.ts
and change the specifier to '../../../constants.js' to match the import that
brings in the constants module.

Comment on lines +16 to +17
import { USER_PROVIDER, TENANT_PROVIDER, User } from '@nexiom/identity';
import type { ITenantProvider, IUserProvider } from '@nexiom/identity';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n apps/api/src/modules/identity/users/users.controller.ts | head -100

Repository: pramodnarayana/nexiom

Length of output: 3787


🏁 Script executed:

cat -n apps/api/src/modules/identity/users/users.controller.ts | tail -80

Repository: pramodnarayana/nexiom

Length of output: 3229


🏁 Script executed:

# Check TypeScript config for NodeNext and verbatim-module-syntax
find . -name "tsconfig*.json" -type f | head -5

Repository: pramodnarayana/nexiom

Length of output: 204


🏁 Script executed:

cat -n apps/api/tsconfig.json

Repository: pramodnarayana/nexiom

Length of output: 1080


🏁 Script executed:

cat -n tsconfig.json

Repository: pramodnarayana/nexiom

Length of output: 110


🏁 Script executed:

find . -maxdepth 2 -name "tsconfig.json" -type f -exec grep -l "verbatimModuleSyntax" {} \;

Repository: pramodnarayana/nexiom

Length of output: 47


🏁 Script executed:

grep -r "verbatimModuleSyntax" . --include="*.json" 2>/dev/null | head -20

Repository: pramodnarayana/nexiom

Length of output: 191


🏁 Script executed:

# Look for `@nexiom/identity` package location and User export
find . -path "*/node_modules" -prune -o -path "*/@nexiom/identity*" -type f -print | head -20

Repository: pramodnarayana/nexiom

Length of output: 47


🏁 Script executed:

find . -type f -name "*.ts" -o -name "*.d.ts" | xargs grep -l "export.*User" | grep -i identity | head -10

Repository: pramodnarayana/nexiom

Length of output: 604


🏁 Script executed:

cat -n packages/identity/src/interfaces/types.ts

Repository: pramodnarayana/nexiom

Length of output: 1708


🏁 Script executed:

find packages/identity/src -name "index.ts" -o -name "index.js" | xargs cat -n

Repository: pramodnarayana/nexiom

Length of output: 1667


🏁 Script executed:

cat -n packages/identity/src/interfaces/index.ts

Repository: pramodnarayana/nexiom

Length of output: 462


🏁 Script executed:

# Verify all uses of User in the file to be absolutely certain
rg "User" apps/api/src/modules/identity/users/users.controller.ts -n

Repository: pramodnarayana/nexiom

Length of output: 1873


Move User to a type-only import.

User is only used in the UserListItem type definition (line 25) and should be imported as a type alongside ITenantProvider and IUserProvider. This keeps runtime values (USER_PROVIDER, TENANT_PROVIDER) separate from types, improving clarity and consistency.

Suggested fix
-import { USER_PROVIDER, TENANT_PROVIDER, User } from '@nexiom/identity';
-import type { ITenantProvider, IUserProvider } from '@nexiom/identity';
+import { USER_PROVIDER, TENANT_PROVIDER } from '@nexiom/identity';
+import type { User, ITenantProvider, IUserProvider } from '@nexiom/identity';
📝 Committable suggestion

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

Suggested change
import { USER_PROVIDER, TENANT_PROVIDER, User } from '@nexiom/identity';
import type { ITenantProvider, IUserProvider } from '@nexiom/identity';
import { USER_PROVIDER, TENANT_PROVIDER } from '@nexiom/identity';
import type { User, ITenantProvider, IUserProvider } from '@nexiom/identity';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/modules/identity/users/users.controller.ts` around lines 16 -
17, The import currently brings User as a runtime value; change it to a
type-only import so runtime providers remain separate: keep USER_PROVIDER and
TENANT_PROVIDER as value imports but import User using the TypeScript type-only
form alongside ITenantProvider and IUserProvider, and update any references in
the UserListItem type to use the type import (symbols: USER_PROVIDER,
TENANT_PROVIDER, User, ITenantProvider, IUserProvider, UserListItem).

Comment on lines +7 to +24
"exports": {
".": {
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"scripts": {
"build": "tsc",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:studio": "drizzle-kit studio"
"./schema/identity": {
"import": "./dist/schema/identity.js",
"default": "./dist/schema/identity.js"
},
"dependencies": {
"@nestjs/common": "^11.1.11",
"drizzle-orm": "^0.45.1",
"pg": "^8.16.3"
"./schema/tenant": {
"import": "./dist/schema/tenant.js",
"default": "./dist/schema/tenant.js"
},
"devDependencies": {
"@types/pg": "^8.16.0",
"drizzle-kit": "^0.31.8",
"typescript": "^5.7.3"
"./dist/schema/identity": {
"import": "./dist/schema/identity.js",
"default": "./dist/schema/identity.js"
}
} No newline at end of file
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding types conditions to subpath exports for TypeScript consumers.

For better TypeScript support with subpath exports, consider adding explicit types conditions. This ensures TypeScript can correctly resolve type declarations for each subpath.

♻️ Proposed enhancement for type resolution
   "exports": {
     ".": {
+      "types": "./dist/index.d.ts",
       "import": "./dist/index.js",
       "default": "./dist/index.js"
     },
     "./schema/identity": {
+      "types": "./dist/schema/identity.d.ts",
       "import": "./dist/schema/identity.js",
       "default": "./dist/schema/identity.js"
     },
     "./schema/tenant": {
+      "types": "./dist/schema/tenant.d.ts",
       "import": "./dist/schema/tenant.js",
       "default": "./dist/schema/tenant.js"
     }
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/database/package.json` around lines 7 - 24, Add explicit "types"
conditions to the package.json "exports" subpaths so TypeScript can resolve
declarations: update the root export (".") to include "types":
"./dist/index.d.ts" and add "types" entries to each subpath export such as
"./schema/identity", "./schema/tenant" (and the duplicate
"./dist/schema/identity") pointing to their corresponding declaration files
(e.g., "./dist/schema/identity.d.ts" and "./dist/schema/tenant.d.ts"); ensure
the file names match the built .d.ts outputs and keep both "import"/"default"
and the new "types" conditions for each export entry.

@@ -1,14 +1,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-return, @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-unsafe-return */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider consolidating ESLint suppressions for consistency.

The file uses a file-level disable for no-unsafe-return but adds an inline disable for unbound-method only at line 149. However, similar assertions exist throughout the file (e.g., lines 172, 193, 374, 378, etc.) that would also trigger the unbound-method rule when checking mock method calls like expect(db.update).not.toHaveBeenCalled().

For consistency with how invitations.controller.spec.ts handles this, consider using a file-level disable for unbound-method as well:

-/* eslint-disable `@typescript-eslint/no-unsafe-return` */
+/* eslint-disable `@typescript-eslint/no-unsafe-return`, `@typescript-eslint/unbound-method` */

This would eliminate the need for the inline disable at line 149 and preempt any future linting errors on similar assertions.

Also applies to: 149-150

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

In `@packages/identity/src/adapters/drizzle-user.adapter.spec.ts` at line 1, Add a
file-level ESLint disable for unbound-method to match the existing file-level
no-unsafe-return suppression and remove the inline disable near the affected
assertion; specifically, add "/* eslint-disable
`@typescript-eslint/unbound-method` */" at the top of the test file (same area
where /* eslint-disable `@typescript-eslint/no-unsafe-return` */ lives) so mock
method assertions like expect(db.update).not.toHaveBeenCalled() and other
expect(db.xxx) calls (seen around the inline disable at the current inline
suppression and elsewhere) no longer require inline disables.

Comment on lines 197 to +198
vi.doMock("../constants", async (importOriginal) => {
const actual = await importOriginal<typeof import("../constants")>();
const actual = await importOriginal<typeof import("../constants.js")>();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "permission-seeder.spec.ts" | head -5

Repository: pramodnarayana/nexiom

Length of output: 123


🏁 Script executed:

git ls-files | grep -E "(permission-seeder|rbac-seeding|constants)" | head -20

Repository: pramodnarayana/nexiom

Length of output: 444


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '190,205p'

Repository: pramodnarayana/nexiom

Length of output: 695


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '280,295p'

Repository: pramodnarayana/nexiom

Length of output: 720


🏁 Script executed:

head -20 packages/identity/src/utils/rbac-seeding.ts

Repository: pramodnarayana/nexiom

Length of output: 580


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '1,50p'

Repository: pramodnarayana/nexiom

Length of output: 2235


🏁 Script executed:

cat packages/identity/package.json | grep -A 5 '"vitest"'

Repository: pramodnarayana/nexiom

Length of output: 93


🏁 Script executed:

grep -r "vi.doMock" packages/identity/src --include="*.ts" | head -10

Repository: pramodnarayana/nexiom

Length of output: 411


🏁 Script executed:

cat -n packages/identity/src/utils/rbac-seeding.ts | head -15

Repository: pramodnarayana/nexiom

Length of output: 581


🏁 Script executed:

ls -la packages/identity/src/constants* 2>/dev/null || echo "No constants files found"

Repository: pramodnarayana/nexiom

Length of output: 148


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '195,230p'

Repository: pramodnarayana/nexiom

Length of output: 1669


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '283,320p'

Repository: pramodnarayana/nexiom

Length of output: 955


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeding.ts | head -30

Repository: pramodnarayana/nexiom

Length of output: 149


🏁 Script executed:

find . -name "vitest.config.*" -o -name "vite.config.*" | xargs cat 2>/dev/null | head -50

Repository: pramodnarayana/nexiom

Length of output: 1619


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '210,220p'

Repository: pramodnarayana/nexiom

Length of output: 496


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '300,310p'

Repository: pramodnarayana/nexiom

Length of output: 211


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | grep -A 5 -B 5 "doUnmock"

Repository: pramodnarayana/nexiom

Length of output: 688


🏁 Script executed:

rg "vi\.doMock|vi\.doUnmock" packages/identity/src --type ts -A 2 -B 2

Repository: pramodnarayana/nexiom

Length of output: 2289


🌐 Web query:

Vitest doMock ESM module specifier matching .js extension

💡 Result:

In Vitest, vi.doMock() matches the module by its specifier string (the same string your code imports). So for ESM, if your code imports with a .js extension, your mock must use the exact same specifier, including .js:

// production code
import { foo } from './dep.js'

// test
vi.doMock('./dep.js', () => ({ foo: () => 'mocked' }))

If you write vi.doMock('./dep', ...) it won’t match import './dep.js'.

To make this harder to mess up (and friendlier to refactors), Vitest also supports passing a module promise to vi.doMock, e.g.:

vi.doMock(import('./dep.js'), () => ({ foo: () => 'mocked' }))

Vitest documents this “module promise” signature for both vi.mock and vi.doMock. (vitest.dev)

Separately, in Node ESM, relative imports must include a file extension (like .js), which is why your app code often needs ./dep.js in the first place. (nodejs.org)

Citations:


🏁 Script executed:

cat packages/identity/package.json | jq '.devDependencies'

Repository: pramodnarayana/nexiom

Length of output: 628


🏁 Script executed:

find . -name "*.json" -path "*/node_modules/.bin*" -prune -o -type f -name "package.json" -exec grep -l "vitest" {} \; | head -5

Repository: pramodnarayana/nexiom

Length of output: 319


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '195,250p'

Repository: pramodnarayana/nexiom

Length of output: 2475


🏁 Script executed:

cat -n packages/identity/src/services/permission-seeder.spec.ts | sed -n '283,305p'

Repository: pramodnarayana/nexiom

Length of output: 955


🏁 Script executed:

rg "importOriginal" packages/identity/src --type ts -B 2 -A 2

Repository: pramodnarayana/nexiom

Length of output: 1279


Match the mocked specifier to the ESM import exactly: use ../constants.js.

In Vitest ESM mode, vi.doMock() requires the module specifier to match exactly what the code imports. Lines 197 and 285 register mocks for ../constants, but rbac-seeding.js imports from ../constants.js, so the mocks never apply—the real constants module is used instead.

Suggested fix
-    vi.doMock("../constants", async (importOriginal) => {
+    vi.doMock("../constants.js", async (importOriginal) => {
       const actual = await importOriginal<typeof import("../constants.js")>();

Apply the same change to both vi.doMock() calls (lines 197 and 285) and their corresponding vi.doUnmock("../constants") calls (lines 280 and 302).

Also applies to: 285–286 and 280, 302

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

In `@packages/identity/src/services/permission-seeder.spec.ts` around lines 197 -
198, The mocks registered with vi.doMock/vi.doUnmock are using the wrong module
specifier ("../constants") so they don't apply to the ESM import
("../constants.js"); update every vi.doMock("../constants") and corresponding
vi.doUnmock("../constants") in this test (including the calls around the
vi.doMock at lines shown) to use the exact ESM specifier "../constants.js" so
the mocks match the imports used by rbac-seeding.js.

],
"compilerOptions": {
"module": "commonjs",
"module": "NodeNext",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if tsconfig.lib.json exists and has compatible module settings
fd -t f "tsconfig.lib.json" packages/pieces/salesforce --exec cat {}

Repository: pramodnarayana/nexiom

Length of output: 414


🌐 Web query:

TypeScript module option valid values nodenext capitalization

💡 Result:

For tsconfig.json’s compilerOptions.module, the official value is spelled nodenext (along with node16, node18, node20, etc.). TypeScript’s TSConfig reference lists it in lowercase. [1]

Capitalization isn’t significant in practice: TypeScript normalizes these enum-like option values (lowercasing them internally), so "module": "NodeNext" and "module": "nodenext" are treated the same—even though diagnostics often print NodeNext. [2]

Recommendation: use the spelling shown in the TSConfig docs ("module": "nodenext") for consistency. [1]

Sources


Use lowercase nodenext for consistency with TypeScript documentation.

The module system is correctly updated to nodenext for ESM compatibility. While NodeNext is functionally equivalent (TypeScript normalizes the casing internally), the official TypeScript documentation and your referenced tsconfig.lib.json use lowercase nodenext. Align to that convention for consistency.

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

In `@packages/pieces/salesforce/tsconfig.json` at line 11, Update the tsconfig
"module" value from "NodeNext" to the lowercase "nodenext" for consistency with
TypeScript docs and the project's tsconfig.lib.json; locate the "module"
property in the packages/pieces/salesforce tsconfig and replace "NodeNext" with
"nodenext" (the JSON key is "module") so casing matches the documented
convention.

Comment thread TECHNICAL_DEBT.md
Comment on lines +23 to +26
- Update the schema with `anonymizeIp` and `anonymizeUserAgent` helpers to hash/truncate data before insert.
- Create a `background` (or `jobs`) module in `apps/api` using `@nestjs/schedule`.
- Implement `runPIICleanup` to run daily, finding sessions older than 30 days and anonymizing their PII, emitting audit logs.
- Add a Drizzle migration to backfill and anonymize existing old sessions.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Pick one retention model for session PII.

Line 23 conflicts with Lines 25-26: anonymizing IP/user-agent before insert removes the raw data immediately, which undercuts the proposed “retain for 30 days, then anonymize” cleanup flow. Please decide whether the goal is immediate minimization or time-bounded retention, then document one consistent approach.

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

In `@TECHNICAL_DEBT.md` around lines 23 - 26, Decide and document a single PII
retention model and make the docs and artifacts consistent: either (A) choose
immediate minimization — keep the `anonymizeIp` and `anonymizeUserAgent` helpers
and remove the `runPIICleanup` job, background module, and backfill migration;
or (B) choose time-bounded retention — keep raw IP/user-agent on insert, remove
or rename the pre-insert anonymization helpers, and implement `runPIICleanup`
inside the `background`/`jobs` module (using `@nestjs/schedule`) to anonymize
sessions older than 30 days and add a Drizzle migration to backfill existing old
sessions; update TECHNICAL_DEBT.md so it clearly states which model is chosen
and lists the matching set of tasks (helpers vs job + migration) and references
to `anonymizeIp`, `anonymizeUserAgent`, `runPIICleanup`, and the background/jobs
module.

@pramodnarayana
pramodnarayana merged commit ce7a599 into development Mar 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant