Skip to content

Comments

Jason/package reorgaziation#349

Open
jasonmorais wants to merge 22 commits intomainfrom
jason/package-reorgaziation
Open

Jason/package reorgaziation#349
jasonmorais wants to merge 22 commits intomainfrom
jason/package-reorgaziation

Conversation

@jasonmorais
Copy link
Contributor

@jasonmorais jasonmorais commented Feb 23, 2026

Summary by Sourcery

Extract mock OAuth2 and payment server logic into reusable seedwork packages and re-home local mock servers as apps while aligning package naming and references with the new @app and @Cellix conventions.

New Features:

  • Introduce reusable @cellix/mock-oauth2-server-seedwork and @cellix/mock-payment-server-seedwork packages exposing configurable startup APIs for OAuth2 and payment mocks.
  • Add dedicated @app/mock-oauth2-server and @app/mock-payment-server apps that configure environment, TLS, and URLs and delegate to the shared seedwork servers.

Enhancements:

  • Make the mock OAuth2 server fully configurable via an OAuth2Config object and environment-driven user profile resolution.
  • Refactor mock payment server implementation into a single, strongly typed Express server that models Cybersource-style endpoints for customers, payment instruments, payments, refunds, plans, and subscriptions.
  • Standardize package names from @sthrift/api/docs/ui and infra services to @app/* and @cellix/* where appropriate, updating imports, tsconfig references, build scripts, and docs.
  • Move mock messaging and MongoDB memory server packages into apps/, updating references, Sonar configuration, and documentation accordingly.

Documentation:

  • Update architecture and developer documentation to reflect new @app/api entrypoint and renamed @Cellix infrastructure services and mock servers.

@jasonmorais jasonmorais requested a review from a team February 23, 2026 16:17
@jasonmorais jasonmorais requested a review from nnoce14 as a code owner February 23, 2026 16:17
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Feb 23, 2026

Reviewer's Guide

Refactors mock OAuth2 and payment servers into reusable seedwork packages and relocates mock servers into dedicated apps, while renaming core backend/api/docs/ui packages from @sthrift/* to @app/* and standardizing payment/infra packages under @cellix/* with corresponding tooling and documentation updates.

Sequence diagram for starting the mock OAuth2 server via app entrypoint

sequenceDiagram
  participant Dev as Developer
  participant MockOAuth2App as mock_oauth2_app_index_ts
  participant Env as setupEnvironment
  participant Config as OAuth2Config_builder
  participant Seed as startMockOAuth2Server
  participant Express as ExpressServer

  Dev->>MockOAuth2App: node dist/src/index.js
  MockOAuth2App->>Env: setupEnvironment()
  Env-->>MockOAuth2App: environment loaded from .env and .env.local

  MockOAuth2App->>Config: resolvePathsAndCerts(projectRoot, port, env)
  Config-->>MockOAuth2App: OAuth2Config instance

  MockOAuth2App->>Seed: startMockOAuth2Server(config)
  Seed->>Express: configureRoutesAndSecurity(config)
  Express-->>Seed: serverInstance
  Seed-->>MockOAuth2App: Promise resolved
  MockOAuth2App-->>Dev: mock OAuth2 server listening at config.baseUrl
Loading

Sequence diagram for starting the mock payment server via app entrypoint

sequenceDiagram
  participant Dev as Developer
  participant MockPaymentApp as mock_payment_app_index_ts
  participant Env as dotenv_setup
  participant Config as PaymentConfig_builder
  participant Seed as startMockPaymentServer
  participant Express as ExpressServer

  Dev->>MockPaymentApp: node dist/src/index.js
  MockPaymentApp->>Env: dotenv.config()
  Env-->>MockPaymentApp: environment loaded

  MockPaymentApp->>Config: resolveProjectRootAndCerts(port, env)
  Config-->>MockPaymentApp: PaymentConfig instance

  MockPaymentApp->>Seed: startMockPaymentServer(config)
  Seed->>Express: configurePaymentEndpoints(config)
  Express-->>Seed: serverInstance
  Seed-->>MockPaymentApp: Promise resolved
  MockPaymentApp-->>Dev: mock payment server listening at paymentBaseUrl
Loading

Class diagram for OAuth2 mock server seedwork types

classDiagram
  class OAuth2Config {
    +number port
    +string baseUrl
    +string host
    +Set~string~ allowedRedirectUris
    +string allowedRedirectUri
    +Map~string,string~ redirectUriToAudience
    +string certKeyPath
    +boolean hasCerts
    +string certPath
    +NodeJS_ProcessEnv env
    +getUserProfile(isAdminPortal boolean) UserProfile
  }

  class UserProfile {
    +string email
    +string given_name
    +string family_name
  }

  class MockOAuth2SeedworkModule {
    +startMockOAuth2Server(config OAuth2Config) Promise~void~
  }

  class MockOAuth2AppEntry {
    +setupEnvironment() void
    +main() void
  }

  OAuth2Config --> UserProfile : returns
  MockOAuth2SeedworkModule --> OAuth2Config : uses
  MockOAuth2AppEntry --> OAuth2Config : builds
  MockOAuth2AppEntry --> MockOAuth2SeedworkModule : calls
Loading

Class diagram for payment mock server seedwork types

classDiagram
  class PaymentConfig {
    +number port
    +string protocol
    +string host
    +string paymentHost
    +string frontendBaseUrl
    +string paymentBaseUrl
    +string certKeyPath
    +string certPath
    +string iframeJsPath
  }

  class MockPaymentSeedworkModule {
    +startMockPaymentServer(config PaymentConfig) Promise~void~
  }

  class MockPaymentAppEntry {
    +setupEnvironment() void
    +main() void
  }

  class PaymentServiceTypes {
    <<from @cellix/payment-service>>
    CustomerProfile
    PaymentTokenInfo
    PaymentTransactionResponse
    CustomerPaymentResponse
    CustomerPaymentInstrumentResponse
    CustomerPaymentInstrumentsResponse
    TransactionReceipt
    PlanCreation
    PlanCreationResponse
    PlansListResponse
    PlanResponse
    Subscription
    SubscriptionResponse
    SuspendSubscriptionResponse
    SubscriptionsListResponse
    PaymentInstrumentInfo
  }

  MockPaymentSeedworkModule --> PaymentConfig : uses
  MockPaymentSeedworkModule --> PaymentServiceTypes : returns
  MockPaymentAppEntry --> PaymentConfig : builds
  MockPaymentAppEntry --> MockPaymentSeedworkModule : calls
Loading

File-Level Changes

Change Details Files
Extract mock OAuth2 server logic into a reusable seedwork package and wire it from a new app-level mock-oauth2-server.
  • Introduce OAuth2Config type and refactor server startup to accept injected configuration, including redirect URI sets, host/baseUrl, cert paths, and user profile provider.
  • Replace direct env/process usage in token issuance and OIDC metadata with values from the provided OAuth2Config.
  • Export startMockOAuth2Server wrapper that runs main(config) and handles startup errors.
  • Create apps/mock-oauth2-server app that loads env, detects certs, constructs OAuth2Config (including redirect mappings and host/BASE_URL), and calls startMockOAuth2Server.
  • Move setup-environment helper into seedwork and export it separately; update package.json/tsconfig for the new @cellix/mock-oauth2-server-seedwork package.
packages/cellix/mock-oauth2-server/src/index.ts
apps/mock-oauth2-server/src/index.ts
packages/cellix/mock-oauth2-server-seedwork/src/index.ts
packages/cellix/mock-oauth2-server-seedwork/src/setup-environment.ts
packages/cellix/mock-oauth2-server-seedwork/package.json
packages/cellix/mock-oauth2-server-seedwork/tsconfig.json
apps/mock-oauth2-server/package.json
apps/mock-oauth2-server/README.md
apps/mock-oauth2-server/.env
apps/mock-oauth2-server/turbo.json
packages/cellix/mock-oauth2-server/.gitignore
packages/cellix/mock-oauth2-server/.env
packages/cellix/mock-oauth2-server/package.json
packages/cellix/mock-oauth2-server/src/setup-environment.ts
Extract mock payment server into a reusable seedwork package and host it in a new app-level mock-payment-server.
  • Create @cellix/mock-payment-server-seedwork with a configurable startMockPaymentServer(PaymentConfig) that sets up Express, CORS, mock Cybersource-like endpoints (tokens, payments, refunds, plans, subscriptions, customer/payment instruments), and HTTPS/HTTP startup with port retry logic.
  • Add apps/mock-payment-server app that loads env, discovers certs, derives protocol and base URLs, builds PaymentConfig, and starts the mock payment server.
  • Wire seedwork build, lint, and TypeScript references; add copy-assets build step and ignore files for new package and app.
packages/cellix/mock-payment-server-seedwork/src/index.ts
packages/cellix/mock-payment-server-seedwork/README.md
packages/cellix/mock-payment-server-seedwork/package.json
packages/cellix/mock-payment-server-seedwork/tsconfig.json
packages/cellix/mock-payment-server-seedwork/.gitignore
apps/mock-payment-server/src/index.ts
apps/mock-payment-server/package.json
apps/mock-payment-server/tsconfig.json
apps/mock-payment-server/.env
apps/mock-payment-server/.gitignore
apps/mock-payment-server/turbo.json
packages/cellix/mock-payment-server/package.json
packages/cellix/mock-payment-server/src/index.ts
packages/cellix/mock-payment-server/tsconfig.json
Relocate mock messaging and MongoDB servers from packages into apps, updating paths, configs, and documentation accordingly.
  • Move @sthrift/mock-messaging-server into apps/mock-messaging-server, adjusting package name to @app/mock-messaging-server and fixing cert path root resolution.
  • Move @sthrift/mock-mongodb-memory-server into apps/mock-mongodb-memory-server, updating tsconfig references to shared mongoose models and mock seedwork.
  • Update references in root package.json scripts, Sonar properties, docs, and messaging-service-mock devDependencies/README to point to the new app locations and @app/* package names.
apps/mock-messaging-server/src/index.ts
apps/mock-messaging-server/package.json
apps/mock-messaging-server/README.md
apps/mock-mongodb-memory-server/package.json
apps/mock-mongodb-memory-server/tsconfig.json
packages/sthrift/mock-messaging-server/src/index.ts
packages/sthrift/mock-messaging-server/package.json
packages/sthrift/mock-messaging-server/README.md
packages/sthrift/mock-mongodb-memory-server/package.json
packages/sthrift/mock-mongodb-memory-server/tsconfig.json
package.json
sonar-project.properties
packages/sthrift/messaging-service-mock/package.json
packages/sthrift/messaging-service-mock/README.md
packages/sthrift/messaging-service-twilio/README.md
TURBOREPO.md
Rename core API, docs, and UI apps from @sthrift/* to @app/* and standardize infra packages under @cellix/*.
  • Rename apps/api package to @app/api and update all references in workspace scripts, build pipeline YAML, instructions, README, and architecture diagrams.
  • Rename apps/docs and apps/ui-sharethrift to @app/docs and @app/ui-sharethrift and update deployment configs and root scripts accordingly.
  • Rename infra/service packages (payment-service-cybersource, payment-service-mock, service-blob-storage, service-mongoose, service-otel, service-sendgrid, service-token-validation) from @sthrift/* to @cellix/, adjusting package.json names, tsconfig references, docs, and imports in apps/api and context-spec to match.
  • Update architecture-diagram.md to reflect new @cellix/ service names and the @app/api entrypoint name.
apps/api/package.json
apps/api/src/index.ts
apps/api/src/service-config/mongoose/index.ts
apps/api/src/service-config/otel-starter.ts
apps/api/.github/instructions/api.instructions.md
apps/api/readme.md
apps/docs/package.json
apps/docs/deploy-docs.yml
apps/ui-sharethrift/package.json
packages/cellix/payment-service-cybersource/package.json
packages/cellix/payment-service-mock/package.json
packages/cellix/service-blob-storage/package.json
packages/cellix/service-blob-storage/tsconfig.json
packages/cellix/service-mongoose/package.json
packages/cellix/service-mongoose/readme.md
packages/cellix/service-mongoose/tsconfig.json
packages/cellix/service-otel/package.json
packages/cellix/service-otel/readme.md
packages/cellix/service-sendgrid/package.json
packages/cellix/service-token-validation/package.json
packages/sthrift/context-spec/package.json
packages/sthrift/context-spec/tsconfig.json
documents/architecture-diagram.md
TURBOREPO.md
build-pipeline/core/monorepo-build-stage.yml
.github/copilot-instructions.md
package.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 3 issues, and left some high level feedback:

  • In @cellix/mock-payment-server-seedwork/src/index.ts, app.use(express.json()) is registered twice; drop the duplicate call to avoid unnecessary middleware re-execution and keep the setup clearer.
  • startMockOAuth2Server in @cellix/mock-oauth2-server-seedwork calls process.exit(1) on error while the app-level entrypoint also does its own catch/process.exit, which makes the seedwork less reusable; consider letting the caller decide how to handle startup failures and remove the process.exit from the seedwork.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `@cellix/mock-payment-server-seedwork/src/index.ts`, `app.use(express.json())` is registered twice; drop the duplicate call to avoid unnecessary middleware re-execution and keep the setup clearer.
- `startMockOAuth2Server` in `@cellix/mock-oauth2-server-seedwork` calls `process.exit(1)` on error while the app-level entrypoint also does its own `catch`/`process.exit`, which makes the seedwork less reusable; consider letting the caller decide how to handle startup failures and remove the `process.exit` from the seedwork.

## Individual Comments

### Comment 1
<location path="apps/mock-oauth2-server/src/index.ts" line_range="84" />
<code_context>
+		const family_name = isAdminPortal
+			? process.env['ADMIN_FAMILY_NAME'] || process.env['FAMILY_NAME'] || ''
+			: process.env['FAMILY_NAME'] || '';
+		return { email, given_name, family_name };
+	},
+};startMockOAuth2Server(config).catch((err: unknown) => {
</code_context>
<issue_to_address>
**nitpick:** Separate the config object literal and `startMockOAuth2Server` call to avoid relying on ASI.

Right now the closing brace and `startMockOAuth2Server(config)...` call are on the same line as `};startMockOAuth2Server(...)`. This unusual style can hurt readability and trigger linting issues. Moving the call to a new line or adding an explicit semicolon before it will make the intent clearer and avoid ASI-related surprises.
</issue_to_address>

### Comment 2
<location path="packages/cellix/mock-oauth2-server-seedwork/README.md" line_range="40" />
<code_context>
+## Exports
+
+- `startMockOAuth2Server` - Main function to start the OAuth2 server
+- `setupEnvironment` - Utility to setup environment variables from `.env` and `.env.local`
+- Type exports: `OAuth2Config`, `UserProfile`, etc.
+
</code_context>
<issue_to_address>
**nitpick (typo):** Use "set up" (verb) instead of "setup" (noun) in this sentence.

Here it’s used as a verb phrase (“to set up”), so the description should read: `Utility to set up environment variables from .env and .env.local.` The `setupEnvironment` function name can stay as-is; this only applies to the description text.

Suggested implementation:

```
 // Set up environment variables

```

There is likely also an export description bullet earlier in the README that reads:

- `setupEnvironment` - Utility to setup environment variables from `.env` and `.env.local`

That line should be updated to:

- `setupEnvironment` - Utility to set up environment variables from `.env` and `.env.local`

to use the verb phrase “set up” in the sentence while keeping the function name unchanged.
</issue_to_address>

### Comment 3
<location path="packages/cellix/mock-payment-server-seedwork/src/index.ts" line_range="39" />
<code_context>
+	iframeJsPath?: string;
+}
+
+export function startMockPaymentServer(config: PaymentConfig): Promise<void> {
+	const app: Express = express();
+	app.disable('x-powered-by');
</code_context>
<issue_to_address>
**issue (complexity):** Consider splitting route registration, mock response construction, and server startup into dedicated helpers to keep this large mock server file easier to understand and maintain without changing behavior.

You can keep the same behavior but reduce complexity by extracting some of the repeated patterns into small helpers. A few targeted refactors would make this much easier to navigate without changing any responses.

### 1. Factor out route groups from `startMockPaymentServer`

Right now `startMockPaymentServer` both configures the app and registers all routes. You can keep the function as the only public API but move route registration into focused helpers:

```ts
// payment-routes.ts
export function registerPaymentRoutes(app: Express, config: PaymentConfig) {
  const CYBERSOURCE_MERCHANT_ID = 'simnova_sharethrift';

  app.post('/payments/v1/authorizations', (req, res) => {
    res.json({
      status: 'AUTHORIZED',
      id: 'mock-transaction-id',
      amount: req.body.amount || '100.00',
      currency: req.body.currency || 'USD',
      merchantId: CYBERSOURCE_MERCHANT_ID,
      decision: 'ACCEPT',
      message: 'Mock authorization successful',
    });
  });

  // /pts/v2/payments, /pts/v2/refunds, etc.
}
```

```ts
// customer-routes.ts
export function registerCustomerRoutes(app: Express) {
  app.post('/pts/v2/customers', (req, res) => {
    const { customerProfile, paymentTokenInfo } = req.body;
    const mockResponse = buildCreateCustomerResponse(customerProfile, paymentTokenInfo);
    return res.status(201).json(mockResponse);
  });

  app.get('/pts/v2/customers/:customerId', (req, res) => {
    const mockResponse = buildCustomerPaymentResponse(req.params.customerId);
    return res.status(200).json(mockResponse);
  });

  // payment-instrument routes...
}
```

And in `startMockPaymentServer`:

```ts
export function startMockPaymentServer(config: PaymentConfig): Promise<void> {
  const app = express();
  // common middleware, CORS, static, etc.

  registerFlexRoutes(app, config);
  registerPaymentRoutes(app, config);
  registerCustomerRoutes(app);
  registerPlanRoutes(app);
  registerSubscriptionRoutes(app);

  return startServerWithRetry(app, config);
}
```

This keeps the public API unchanged but makes each group of endpoints self-contained.

### 2. Extract mock object factories to remove duplication

Several endpoints build nearly identical nested structures. For example, the single payment instrument response in `/tms/v2/customers/:customerId/payment-instruments/:paymentInstrumentId` and the one in the list endpoint share the same shape. You can centralize that to reduce drift:

```ts
// mock-factories.ts
export function buildPaymentInstrument(
  customerId: string,
  overrides: Partial<CustomerPaymentInstrumentResponse> = {},
): CustomerPaymentInstrumentResponse {
  const base: CustomerPaymentInstrumentResponse = {
    _links: {
      self: {
        href: `https://api.mockcybersource.com/customers/${customerId}/payment-instruments/PI_1111`,
      },
      customer: {
        href: `https://api.mockcybersource.com/customers/${customerId}`,
      },
    },
    id: 'PI_1111',
    object: 'paymentInstrument',
    default: true,
    state: 'ACTIVE',
    card: { expirationMonth: '12', expirationYear: '2026', type: '001' },
    buyerInformation: { currency: 'USD' },
    billTo: {
      firstName: 'John',
      lastName: 'Doe',
      address1: '123 Mock Street',
      address2: '',
      locality: 'Faketown',
      administrativeArea: 'CA',
      postalCode: '99999',
      country: 'US',
      email: 'john.doe@example.com',
      phoneNumber: '+1-555-1234',
    },
    processingInformation: { billPaymentProgramEnabled: false },
    instrumentIdentifier: { id: 'MOCK_IDENTIFIER_1111' },
    metadata: { creator: 'mock_system' },
    _embedded: {
      instrumentIdentifier: {
        _links: {
          self: {
            href: `https://api.mockcybersource.com/instrument-identifiers/MOCK_IDENTIFIER_1111`,
          },
          paymentInstruments: {
            href: `https://api.mockcybersource.com/customers/${customerId}/payment-instruments`,
          },
        },
        id: 'MOCK_IDENTIFIER_1111',
        object: 'instrumentIdentifier',
        state: 'ACTIVE',
        card: { number: '411111XXXXXX1111' },
        processingInformation: {
          authorizationOptions: {
            initiator: {
              merchantInitiatedTransaction: { previousTransactionId: 'TXN12345' },
            },
          },
        },
        metadata: { creator: 'mock_system' },
      },
    },
  };

  return { ...base, ...overrides };
}
```

Then your handlers become much simpler:

```ts
app.get(
  '/tms/v2/customers/:customerId/payment-instruments/:paymentInstrumentId',
  (req, res) => {
    const { customerId, paymentInstrumentId } = req.params;
    const mockResponse = buildPaymentInstrument(customerId, { id: paymentInstrumentId });
    return res.status(200).json(mockResponse);
  },
);

app.get(
  '/tms/v2/customers/:customerId/payment-instruments',
  (req, res) => {
    const { customerId } = req.params;
    const offset = Number((req.query['offset'] as string) ?? 0);
    const limit = Number((req.query['limit'] as string) ?? 10);

    const all = [buildPaymentInstrument(customerId)];
    const response: CustomerPaymentInstrumentsResponse = {
      _links: {
        self: { href: `https://api.mockcybersource.com/customers/${customerId}/payment-instruments` },
        first: { href: `https://api.mockcybersource.com/customers/${customerId}/payment-instruments?offset=0&limit=${limit}` },
        last: { href: `https://api.mockcybersource.com/customers/${customerId}/payment-instruments?offset=0&limit=${limit}` },
      },
      offset,
      limit,
      count: all.length,
      total: all.length,
      _embedded: { paymentInstruments: all.slice(offset, offset + limit) },
    };

    return res.status(200).json(response);
  },
);
```

You can apply the same pattern for:

- `buildCustomerPaymentResponse(customerId)`
- `buildPlanResponse(planId?)`
- `buildSubscriptionResponse(subscriptionId?)`
- `buildPaymentTransactionResponse(...)` (for create customer / add instrument)

This keeps the types as-is but moves the nested literals out of the route callbacks.

### 3. Deduplicate HTTP/HTTPS server startup with a small helper

The `startServer` inner function has two nearly identical branches. You can keep the retry behavior but centralize the common logic:

```ts
// server-start.ts
function listenWithRetry(
  create: () => import('http').Server,
  port: number,
  host: string,
  log: (port: number) => void,
  maxAttempts = 5,
  attempt = 0,
  onError?: (err: NodeJS.ErrnoException) => void,
): void {
  const server = create().listen(port, host, () => {
    log(port);
  });

  server.on('error', (error: NodeJS.ErrnoException) => {
    if (error.code === 'EADDRINUSE' && attempt < maxAttempts) {
      const nextPort = port + 1;
      console.warn(`Port ${port} in use. Retrying mock-payment-server on ${nextPort}...`);
      server.close(() => {
        listenWithRetry(create, nextPort, host, log, maxAttempts, attempt + 1, onError);
      });
      return;
    }
    onError?.(error);
  });
}
```

Then inside `startMockPaymentServer`:

```ts
return new Promise((resolve, reject) => {
  const log = (port: number) => {
    console.log(` Mock Payment Server listening on ${config.protocol}://${config.paymentHost.replace(/:\d+$/, ':' + port)}`);
    console.log(`   CORS origin: ${config.frontendBaseUrl}`);
    console.log(`   Microform origin: ${config.paymentBaseUrl}`);
    resolve();
  };

  if (hasCerts) {
    const httpsOptions = {
      key: fs.readFileSync(config.certKeyPath as string),
      cert: fs.readFileSync(config.certPath as string),
    };

    listenWithRetry(
      () => https.createServer(httpsOptions, app),
      config.port,
      config.host,
      log,
      5,
      0,
      reject,
    );
  } else {
    listenWithRetry(
      () => app,
      config.port,
      config.host,
      (port) => {
        console.log(` Mock Payment Server listening on ${config.protocol}://localhost:${port} (no certs found)`);
        console.log(`   CORS origin: ${config.frontendBaseUrl}`);
        console.log(`   Microform origin: ${config.paymentBaseUrl}`);
        resolve();
      },
      5,
      0,
      reject,
    );
  }
});
```

This keeps the retry semantics and logging but removes duplication and makes the startup flow easier to follow.

---

All of these changes preserve the existing behavior and responses, but they reduce the visual and structural complexity by isolating concerns: route registration per domain, mock structure construction, and server startup.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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