Skip to content

#202 into release@5.0.0 🧊 add default port#240

Open
debabin wants to merge 1 commit into
release@5.0.0from
#202
Open

#202 into release@5.0.0 🧊 add default port#240
debabin wants to merge 1 commit into
release@5.0.0from
#202

Conversation

@debabin

@debabin debabin commented May 8, 2025

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Automatic port allocation: When no port is explicitly specified, the system now intelligently discovers and allocates an available port, enabling flexible server deployment across different environments.
  • Chores

    • Updated initialization success message text.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented May 8, 2025

Copy link
Copy Markdown

Walkthrough

This pull request introduces dynamic port allocation for a mock server configuration. The main function runFlatConfig is converted to async to support automatic port resolution via the get-port-please library when a port is not explicitly provided. Supporting changes include updating the build watch handler to await the async call, adjusting git hook emoji handling, and refining user-facing messages.

Changes

Cohort / File(s) Summary
Git hook configuration
​.husky/commit-msg
Replaces .emoji file existence check with git config-based emoji retrieval (`git config user.emoji
CLI initialization
bin/init.ts
Removes trailing emoji from success message: "🎉 Thanks for using mock-config-server! 🎉" → "🎉 Thanks for using mock-config-server!"
Build tooling
bin/build.ts
Makes watch path onEnd callback async and awaits runFlatConfig invocation instead of direct assignment.
Server configuration with dynamic port resolution
bin/runFlatConfig.ts
Converts function to async; expands parameter destructuring to { baseUrl, staticPath, ...options } for flexible port input. Adds logic to automatically resolve a free port via getPort({ port, portRange: [7777, 9000], host: "127.0.0.1" }) when port is unspecified. Conditionally merges resolved port into config.
Dependency management
package.json
Adds get-port-please@^3.1.2 to dependencies.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • bin/runFlatConfig.ts requires careful review of the async conversion, port resolution logic, and parameter destructuring changes to ensure correct fallback behavior and port range constraints.
  • bin/build.ts change depends on confirming runFlatConfig async behavior integrates correctly with the watch handler lifecycle.
  • Verify that the getPort library handles edge cases (port exhaustion, host binding) gracefully.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main objective of adding default port functionality, which is reflected in changes to runFlatConfig.ts, package.json, and related files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch #202

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.

@debabin debabin linked an issue May 8, 2025 that may be closed by this pull request
@debabin debabin changed the title #202 into release@5.0.0 🎉 add default port #202 into release@5.0.0 🧊 add default port May 8, 2025
Comment thread bin/runFlatConfig.ts
Comment on lines +18 to 27
const port = flatMockServerSettings?.port || options.port;

const mergedFlatMockServerConfig = [
{
...flatMockServerSettings,
...(baseUrl && { baseUrl }),
...(port && { port }),
...(!port && { port: await getPort({ port, portRange: [7777, 9000], host }) }),
...(staticPath && { staticPath })
},

@RiceWithMeat RiceWithMeat May 8, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  1. Сейчас не робит фича т.к. если порт указан, то серв запустится на нём. И если запустить подряд два мока, то второй не возьмёт след порт
  2. разве логика с port / !port нужна?
  3. в startFlatMockServer.ts теперь порт 31299 никогда не засетится как дефолтный, т.к. в mergedFlatMockServerConfig он теперь всегда будет. Можно либо убрать логику с 31299, либо перенести сюда для единства ответственности "решаем на каком порту запустить сервер". Типа const port = flatMockServerSettings?.port || options.port || DEFAULT.PORT.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  1. либо перенести сюда для единства ответственности — если перенести эту тему сюда, то порт всегда будет объявлен и getPort не будет иметь смысла

@RiceWithMeat RiceWithMeat added the enhancement New feature or request label May 8, 2025
@MiaInturi

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Dec 1, 2025

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@debabin debabin changed the base branch from main to release@5.0.0 December 1, 2025 15:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (3)
bin/build.ts (1)

69-71: Missing await for async runFlatConfig call.

Since runFlatConfig is now async, the call on line 70 returns a Promise that is never awaited. This means:

  • The function returns immediately without waiting for the server to start
  • Errors during port resolution or server startup may be silently swallowed
  • The build function completes before the server is ready

Apply this diff to await the Promise:

  if (isFlatConfig) {
-    return runFlatConfig(mockConfig, argv);
+    return await runFlatConfig(mockConfig, argv);
  }
bin/runFlatConfig.ts (2)

20-29: Consider simplifying the conditional spreading logic.

The nested conditional spreads on lines 23-26 make the logic harder to follow. Consider this more explicit approach:

const mergedSettings = {
  ...flatMockServerSettings,
  ...(baseUrl && { baseUrl }),
  ...(staticPath && { staticPath }),
  port: port || (await getPort({ portRange: [7777, 9000], host }))
};

const mergedFlatMockServerConfig = [
  mergedSettings,
  ...(flatMockServerSettings ? flatMockServerComponents : flatMockServerConfig)
] as FlatMockServerConfig;

This makes it clearer that:

  1. Port is always set (either explicit or auto-resolved)
  2. The conditional logic for baseUrl and staticPath is separate
  3. The structure is easier to understand

32-34: Consider improving error handling for port resolution failures.

If getPort fails because all ports in the range [7777, 9000] are busy, the error is logged but the function returns undefined. This could lead to silent failures if callers don't check the return value.

Consider either:

  • Re-throwing the error after logging
  • Returning a more descriptive error
  • Or document that callers should handle undefined returns
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3845556 and 5667c18.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (5)
  • .husky/commit-msg (1 hunks)
  • bin/build.ts (1 hunks)
  • bin/init.ts (1 hunks)
  • bin/runFlatConfig.ts (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
bin/runFlatConfig.ts (2)
examples/server/index.ts (1)
  • flatMockServerConfig (5-31)
src/utils/types/server.ts (2)
  • FlatMockServerConfig (108-111)
  • MockServerConfigArgv (75-81)
bin/build.ts (2)
bin/helpers/resolveConfigFile.ts (1)
  • resolveConfigFile (7-28)
bin/runFlatConfig.ts (1)
  • runFlatConfig (9-35)
🔇 Additional comments (4)
bin/init.ts (1)

93-93: LGTM!

The simplified success message is cleaner while maintaining the celebratory tone.

bin/build.ts (1)

40-47: LGTM!

The watch mode correctly handles the async runFlatConfig by making the onEnd callback async and awaiting the call.

bin/runFlatConfig.ts (1)

9-11: LGTM!

The async signature and parameter restructuring enable dynamic port resolution while maintaining flexibility. The spread ...options allows access to all argv properties including port.

package.json (1)

90-90: No action required.

get-port-please@3.1.2 is a valid, stable version with no known security vulnerabilities. The package is actively maintained by the unjs organization (MIT licensed, zero dependencies). Version 3.2.0 is available, but the caret notation (^3.1.2) allows safe upgrades within the same major version.

Comment thread .husky/commit-msg
Comment thread bin/runFlatConfig.ts
Comment on lines +17 to +25
const host = '127.0.0.1';
const port = flatMockServerSettings?.port || options.port;

const mergedFlatMockServerConfig = [
{
...flatMockServerSettings,
...(baseUrl && { baseUrl }),
...(port && { port }),
...(!port && { port: await getPort({ port, portRange: [7777, 9000], host }) }),

@coderabbitai coderabbitai Bot Dec 1, 2025

Copy link
Copy Markdown

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

🌐 Web query:

get-port-please npm package getPort API documentation parameters

💡 Result:

get-port-please — getPort API (summary)

  • Signature: getPort(options?: GetPortOptions): Promise. Other exports: checkPort(port, host?), getRandomPort(), waitForPort(port, options), (plus socket helpers in newer versions). [1][2]

GetPortOptions fields:

  • name?: string — unique name for memorizing a port (default: "default"). [1][2]
  • random?: boolean — if true, ignore port/ports and pick a random free port (default: false). [1][2]
  • port?: number — preferred first port to check (default: process.env.PORT || 3000). [1][2]
  • ports?: number[] — list of explicit ports to check. [1][2]
  • portRange?: [fromInclusive: number, toInclusive: number] — inclusive range to search. Default range when port unset is [3000,3100]. [1][2]
  • alternativePortRange?: [fromInclusive, toInclusive] — fallback range if primary ports/range unavailable. [1][2]
  • host?: string — host/address to check (by default checks all local addresses or process.env.HOST if set). [1][2]
  • memoDir?: string — directory for port memoization (when used). [1][2]
  • memoName?: string — filename/name for memoization (when used). [1][2]

Return/behavior notes:

  • Returns a Promise resolving to the chosen port number. checkPort/ waitForPort may return false if unavailable. Default search order: port → ports → portRange → random. [1][2]

Sources: npm package pages for get-port-please. [1] npmjs (package page). [2] npm.io summary.


🏁 Script executed:

#!/bin/bash
# Search for getPort usage patterns in the codebase
rg "getPort\(" --type ts --type js -A 3 -B 1

Repository: siberiacancode/mock-config

Length of output: 428


🏁 Script executed:

#!/bin/bash
# Search for startFlatMockServer to understand old default port behavior
rg "startFlatMockServer" --type ts --type js -A 5 -B 1

Repository: siberiacancode/mock-config

Length of output: 35639


🏁 Script executed:

#!/bin/bash
# Search for port default value 31299 in the codebase
rg "31299" --type ts --type js -B 2 -A 2

Repository: siberiacancode/mock-config

Length of output: 2340


🏁 Script executed:

#!/bin/bash
# Look at startFlatMockServer implementation
cat -n src/server/startFlatMockServer/startFlatMockServer.ts

Repository: siberiacancode/mock-config

Length of output: 1127


Clarify port resolution strategy and document auto-selection behavior.

The port resolution logic uses get-port-please correctly. When port is undefined, passing it to getPort({ port, portRange: [7777, 9000], host }) is valid—the library's default search order falls back to the portRange when port is unset. However, two considerations apply:

  1. Default port intentionally replaced: The old DEFAULT.PORT (31299) from startFlatMockServer is no longer used because runFlatConfig always populates a port in the config (either from settings, options, or auto-selection). This appears intentional—the range [7777, 9000] now serves as the auto-resolution fallback. Ensure this behavior change is documented.

  2. Port conflict asymmetry: If a user explicitly provides a port via config or CLI options and it's already in use, the server will fail with that port. Auto-resolution only engages when no port is specified. Consider whether users should always attempt to find an available port, or if explicit port failures are the desired behavior. If the latter, document it clearly.

🤖 Prompt for AI Agents
In bin/runFlatConfig.ts around lines 17 to 25, the port-resolution behavior is
unclear and asymmetric: when port is undefined we auto-select from [7777,9000],
but an explicitly provided port will fail if occupied; update the code and docs
to make this explicit and, if desired, make resolution symmetric. Add a concise
inline comment and update external docs/readme stating the resolution order
(flatMockServerSettings.port -> CLI options.port -> auto-select via getPort with
range [7777,9000]) and that explicit ports do not fall back by default;
alternatively, to make behavior symmetric, change the resolution to attempt
getPort with the requested port as a preferred candidate (so if requested port
is in use it will pick the next available from the range) and ensure you log a
clear warning when the requested port could not be used and an alternative was
selected.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

мб поменять port range на тот, который начинается с 31299? Привычнее как будто будет + не надо будет DEFAULT.PORT обрабатывать

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find DEFAULT.PORT definition and usage
rg "DEFAULT\.PORT|DEFAULT_PORT" --type ts --type js -C 3

Length of output: 4423


🏁 Script executed:

#!/bin/bash
# Check if there's any documentation about the default port
fd -e md -e txt | xargs rg "31299|default.*port|port.*default" -i

Length of output: 1020


🏁 Script executed:

#!/bin/bash
# Look at the constants or config files that might define defaults
fd "constant|config|default" --type f -e ts -e js | head -20

Length of output: 1224


🏁 Script executed:

#!/bin/bash
# Check the DEFAULT.PORT definition
cat src/utils/constants/default.ts

Length of output: 216


@MiaInturi Отличное предложение! Согласен, что начинать диапазон с 31299 гораздо логичнее.

Looking at the codebase, DEFAULT.PORT is defined as 31299 in src/utils/constants/default.ts, and this value has been the documented default port throughout the project. The current range [7777, 9000] breaks backward compatibility and creates unexpected behavior for users who rely on the familiar 31299 default.

Recommendation:
Change the port range to start from 31299:

...(!port && { port: await getPort({ port, portRange: [31299, 32299], host }) }),

Benefits:

  1. Backward compatible – when no port is specified, getPort will attempt 31299 first, matching the historical default
  2. Maintains familiarity – users expect the server on 31299
  3. Consistent with documentation – README.md states "default: 31299"
  4. Simplifies logic – as you noted, no need to handle DEFAULT.PORT separately since auto-selection naturally tries it first
  5. Provides fallback – if 31299 is occupied, automatically finds the next available port in range

The range [31299, 32299] gives 1000 ports to search, which should be more than sufficient for finding an available port in development environments.


🧬 Code Graph Analysis Results

: src/utils/types/server.ts (lines 108-111)

export type FlatMockServerConfig = [
  option: FlatMockServerComponent | FlatMockServerSettings,
  ...flatMockServerComponents: FlatMockServerComponent[]
];

: src/utils/types/server.ts (lines 75-81)

export type MockServerConfigArgv = Arguments<{
  baseUrl?: string;
  port?: number;
  staticPath?: string;
  config?: string;
  watch?: boolean;
}>;

: examples/server/index.ts (lines 5-31)

export const flatMockServerConfig: FlatMockServerConfig = [
  {
    baseUrl: '/api'
  },
  {
    configs: [
      {
        method: 'get',
        path: '/users',
        routes: [
          {
            data: [{ id: 1, emoji: '🎉' }]
          }
        ]
      },
      {
        operationType: 'query',
        operationName: 'GetUsers',
        routes: [
          {
            data: [{ id: 1, emoji: '🎉' }]
          }
        ]
      }
    ]
  }
];

: src/server/startFlatMockServer/startFlatMockServer.ts (lines 10-23)

export const startFlatMockServer = (flatMockServerConfig: FlatMockServerConfig) => {
  const flatMockServer = createFlatMockServer(flatMockServerConfig);

  const [option] = flatMockServerConfig;
  const flatMockServerSettings = !('configs' in option) ? option : {};
  const { port = DEFAULT.PORT } = flatMockServerSettings;

  const server = flatMockServer.listen(port, () => {
    console.log(color.green(`🎉 Flat Mock Server is running at http://localhost:${port}`));
  });

  // ✅ important: add destroy method for closing keep-alive connections after server shutdown
  return destroyerMiddleware(server);
};

Comment thread bin/runFlatConfig.ts
Comment on lines +17 to +18
const host = '127.0.0.1';
const port = flatMockServerSettings?.port || options.port;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Порт из CLI должен иметь премущество, как раньше и было

Comment thread bin/runFlatConfig.ts
Comment on lines +18 to 27
const port = flatMockServerSettings?.port || options.port;

const mergedFlatMockServerConfig = [
{
...flatMockServerSettings,
...(baseUrl && { baseUrl }),
...(port && { port }),
...(!port && { port: await getPort({ port, portRange: [7777, 9000], host }) }),
...(staticPath && { staticPath })
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  1. либо перенести сюда для единства ответственности — если перенести эту тему сюда, то порт всегда будет объявлен и getPort не будет иметь смысла

Comment thread bin/runFlatConfig.ts
Comment on lines +17 to +25
const host = '127.0.0.1';
const port = flatMockServerSettings?.port || options.port;

const mergedFlatMockServerConfig = [
{
...flatMockServerSettings,
...(baseUrl && { baseUrl }),
...(port && { port }),
...(!port && { port: await getPort({ port, portRange: [7777, 9000], host }) }),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

мб поменять port range на тот, который начинается с 31299? Привычнее как будто будет + не надо будет DEFAULT.PORT обрабатывать

Comment thread bin/runFlatConfig.ts
const [option, ...flatMockServerComponents] = flatMockServerConfig;
const flatMockServerSettings = !('configs' in option) ? option : undefined;

const host = '127.0.0.1';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

думаю надо сделать host тоже как параметр. У людей мок может быть в докере запущен, например. Думаю сделаю issue + PR сразу

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Selecting a port if the primary one is busy

3 participants