Skip to content

#197 into release@5.0.0 💎 update zod from v3 to v4#252

Open
MiaInturi wants to merge 9 commits intorelease@5.0.0from
#197
Open

#197 into release@5.0.0 💎 update zod from v3 to v4#252
MiaInturi wants to merge 9 commits intorelease@5.0.0from
#197

Conversation

@MiaInturi
Copy link
Collaborator

@MiaInturi MiaInturi commented Dec 30, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced CLI input validation with clearer error messages for configuration options (baseUrl, port, staticPath, config file).
    • Improved commit message formatting in git hooks for better branch and emoji information.
  • Dependency Updates

    • Upgraded zod from ^3.24.1 to ^4.1.13.
  • Build & Development

    • Added TypeScript type-checking step for templates during the build process.
    • Refined configuration validation handling across mock server endpoints.

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

@MiaInturi MiaInturi added enhancement New feature or request release@5.0.0 issues for release@5.0.0 labels Dec 30, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 30, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR refactors the validation system by consolidating error-handling utilities, replacing custom schema helpers with a new oneKeyDispatchSchema dispatcher, and moving config validation from server creation functions to CLI entry points. Zod dependency is upgraded to ^4.1.13, and build scripts are updated for template type-checking.

Changes

Cohort / File(s) Summary
Build & Configuration
.gitignore, .husky/commit-msg, package.json, tsconfig.dev.json
Updated husky hook to use git config user emoji; added VSCode editor state to .gitignore; added TypeScript type-check step to build:copy-templates script; upgraded zod ^3.24.1 → ^4.1.13; removed vi.config.js from tsconfig.dev.json exclude list.
CLI Entry Points (Validation Added)
bin/cli.ts, bin/run.ts, bin/runFlatConfig.ts
Added input validation using schema coercion and explicit error handling before starting servers; moved validation logic from server creation to CLI initialization path.
Server Creation Functions (Validation Removed)
src/server/createMockServer/createMockServer.ts, src/server/createRestMockServer/createRestMockServer.ts, src/server/createGraphQLMockServer/createGraphQLMockServer.ts, src/server/createFlatMockServer/createFlatMockServer.ts
Removed runtime validation calls; corresponding schema validation now occurs earlier at CLI layer.
Validation Error Handling (Consolidation)
src/utils/validate/getMostSpecificPathFromError.ts (deleted), src/utils/validate/getValidationMessage.ts (new), src/utils/validate/getValidationMessageFromPath.ts (deleted), src/utils/validate/index.ts
Replaced two-step error path extraction with unified getValidationMessage(issues) function; consolidated error message derivation logic.
Schema Utility Refactoring (Replaced Helpers)
src/utils/validate/utils/extendedDiscriminatedUnion/* (deleted), src/utils/validate/utils/plainObjectSchema/plainObjectSchema.ts (deleted), src/utils/validate/utils/nestedObjectOrArraySchema/nestedObjectOrArraySchema.ts (deleted), src/utils/validate/utils/jsonSchema/jsonSchema.ts (deleted), src/utils/validate/utils/requiredPropertiesSchema/requiredPropertiesSchema.ts (deleted), src/utils/validate/utils/oneKeyDispatchSchema/oneKeyDispatchSchema.ts (new), src/utils/validate/utils/index.ts
Introduced new oneKeyDispatchSchema for key-based validation dispatch; removed five legacy utility modules and updated index exports accordingly.
Schema Updates (Template Literals & Direct Zod)
src/utils/validate/databaseConfigSchema/databaseConfigSchema.ts, src/utils/validate/graphqlConfigSchema/graphqlConfigSchema.ts, src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.ts, src/utils/validate/restConfigSchema/restConfigSchema.ts, src/utils/validate/restConfigSchema/routeConfigSchema/routeConfigSchema.ts, src/utils/validate/queueSchema/queueSchema.ts, src/utils/validate/utils/sharedSchema/sharedSchema.ts
Replaced plainObjectSchema wrappers with direct zod schemas; migrated string constraint checks to templateLiteral-based schemas; refactored union validation to use oneKeyDispatchSchema for REST and GraphQL route configs.
Validation Functions (Updated Error Handling)
src/utils/validate/validateApiMockServerConfig.ts, src/utils/validate/validateFlatMockServerConfig.ts, src/utils/validate/validateMockServerConfig.ts
Updated to use getValidationMessage(issues) instead of path-based error extraction; removed plainObjectSchema for interceptors field.
Complex Schema Updates
src/utils/validate/utils/checkModeSchema/checkModeSchema.ts, src/utils/validate/utils/entitiesSchema/entitiesSchema.ts
Updated discriminated union types from string literal 'strict' to z.core.$strict; refactored entity schemas to use looser object validation with refine; replaced plainEntityObjectiveValueSchema with generic JSON-based union.
Supporting Utilities & Types
src/utils/validate/isOnlyRequestedDataResolvingPropertyExists.ts (deleted), src/utils/types/entities.ts, src/utils/types/server.ts
Removed property existence validator; renamed NonCheckModeWithoutCheckMode; added documentation comments to FlatMockServerComponent.
Test Updates
src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.test.ts, src/utils/validate/restConfigSchema/routeConfigSchema/routeConfigSchema.test.ts, src/utils/validate/utils/entitiesSchema/entitiesSchema.test.ts, src/utils/validate/utils/extendedDiscriminatedUnion/extendedDiscriminatedUnion.test.ts (deleted), bin/init.ts
Updated test error assertions to use getValidationMessage; removed tests for deleted extendedDiscriminatedUnion; removed await on createTemplate in init flow.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

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 PR title '#197 into release@5.0.0 💎 update zod from v3 to v4' clearly and specifically summarizes the main change: upgrading the Zod dependency from version 3 to version 4.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

"skipLibCheck": true
},
"exclude": ["examples", "bin/templates", "dist", "node_modules", "vi.config.js"]
"exclude": ["examples", "bin/templates", "dist", "node_modules"]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Файла не существует, поэтому удалил.

Comment on lines -33 to +31
interceptors: plainObjectSchema(interceptorsSchema).optional(),
interceptors: interceptorsSchema.optional(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

В бета-версии zod v4 regexp не воспринимался как объект, сейчас же снова стал.

По факту plainObjectSchema нужна была для случаев, когда можно прокинуть пустой объект (типо interceptors — там же можно просто {} написать и не прокидывать никакой из interceptor-ов).

Мне очень не нравилось, что из-за такого узкого и очень редкого кейса приходится использовать нашу самописную обертку, так что я пошел, чекнул как у других популярных либ (valibot, arktype) и у них все так же.

Так что я просто предлагаю убрать эту обертку.

Comment on lines -43 to +40
const validationMessage = getValidationMessageFromPath(path);
const validationMessage = getValidationMessage(validationResult.error.issues);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

теперь вместо двух функций getMostSpecificPathFromError + getValidationMessageFromPath вызывается одна getValidationMessage, т.к. эти функции всегда шли в паре

Comment on lines -27 to -28
const isConfigsContainAtLeastOneElement =
Array.isArray(mockServerConfig.configs) && !!mockServerConfig.configs.length;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

особо это условие смысла не имело — даже если configs пустой массив, то валидация для него не сломается

Comment on lines 9 to 37
export const oneKeyDispatchSchema = <S extends Record<string, z.ZodTypeAny>>(schemasByKey: S) => {
const keys = Object.keys(schemasByKey);

return z
.custom((value) => isPlainObject(value))
.superRefine((value, ctx) => {
const existingKeys = keys.filter((key) => Object.prototype.hasOwnProperty.call(value, key));

if (existingKeys.length !== 1) {
ctx.addIssue({
code: 'custom',
path: []
});
return;
}

const [key] = existingKeys;
const schema = schemasByKey[key];

const result = schema.safeParse(value);
if (!result.success) {
const issuePath = getMostSpecificPathFromError(result.error.issues);
ctx.addIssue({
code: 'custom',
path: issuePath
});
}
});
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Функция создает Zod-схему валидации, которая требует, чтобы объект содержал ровно один ключ из заданного набора, и валидирует значение по соответствующей схеме:

  1. Принимает объект схем (schemasByKey), где ключи — строки, значения — Zod-схемы.
  2. Проверяет наличие ровно одного ключа из набора.
  3. Если ключей нет или их больше одного — ошибка.
  4. Берет схему по найденному ключу и валидирует весь объект. При ошибке добавляет её с указанием пути.

Это нужно для случаев, когда у нас в зависимости от ключа надо выбрать "ветку" валидации. Типо есть data, queue, file — одновременно эти ключи не должны существовать и в зависимости от того, какой ключ сейчас используется, должна применяться соотв. валидация.

Сам zod не имеет механизма, чтобы остановиться "заранее", просто проверив, что те или иные ключи есть/нет и выдает валидационные ошибки для всех веток сразу. А нам же, как я уже сказал выше, нужны ошибки для ветки, соответствующей ключу.

Comment on lines -77 to 83

const mappedEntityDescriptorSchema = extendedDiscriminatedUnion('checkMode', [
const mappedEntityDescriptorSchema = z.discriminatedUnion('checkMode', [
entityDescriptorSchema(checkActualValueCheckModeSchema),
entityDescriptorSchema(z.literal('function'), z.function()),
entityDescriptorSchema(z.literal('regExp'), z.instanceof(RegExp)),
entityDescriptorSchema(compareWithDescriptorValueCheckModeSchema, mappedEntityValueSchema)
]);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

раньше zod не поддерживал вложенные discriminatedUnion, а сейчас поддерживает.

Тут это важно, т.к. entityDescriptorSchema тоже discriminatedUnion (по параметру oneOf).

Comment on lines +85 to 88
export const mappedEntitySchema = z.record(
z.string(),
z.union([mappedEntityValueSchema, mappedEntityDescriptorSchema])
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

теперь z.record требует явного указания типа ключа

"build:types": "tsc -p tsconfig.production.json && tsc-alias -p tsconfig.production.json",
"build:swc": "swc bin src index.ts -d dist --extensions .ts --copy-files --ignore **/*.test.ts --ignore bin/templates",
"build:copy-templates": "shx mkdir -p dist/bin/templates/ts && shx cp -r bin/templates/ts dist/bin/templates && shx mkdir -p dist/bin/templates/js && shx cp -r bin/templates/js dist/bin/templates",
"build:copy-templates": "tsc --noEmit -p bin/templates/tsconfig.json && shx mkdir -p dist/bin/templates/ts && shx cp -r bin/templates/ts dist/bin/templates && shx mkdir -p dist/bin/templates/js && shx cp -r bin/templates/js dist/bin/templates",
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Раньше можно было выпустить билд c TS ошибкой в example-ах, теперь же нельзя

Comment on lines +11 to 13
validateFlatMockServerConfig(flatMockServerConfig);
const [option, ...flatMockServerComponents] = flatMockServerConfig;
const flatMockServerSettings = !('configs' in option) ? option : undefined;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Я перенес вызовы валидирующих функций в run-функции (run, runFlatConfig) по причине того, что раньше валидация применялась для merged конфигов и соотв при наличии какой-то ошибки путь был неправильным.

Например, если конфиг выглядит так:

const mockServerConfig: FlatMockServerConfig = [
  {
    name: 'rest',
    configs: [
      {
        method: 'get',
        path: '/users',
        routes: [
          {
            // Для этого объекта должна быть ошибка
            non_expected_key: 'value'
          }
        ]
      }
    ]
  }
];

то при валидации смердженного конфига (где настройки поставлены в качестве нулевого элемента) путь будет не configuration[0].configs ...., а configuration[1].configs .....

НО у этого есть минус: если в конфиге неправильные настройки (типо невозможного порта), но через CLI передано верное значение, то валидация ругнется, т.к. мы проверяем чисто конфиг, а не смердженную его версию.

Мб как-то по умному валидировать, типо если первый объект — это настройки, то смерджить и валидировать, а если НЕ-настройки, то валидировать до мерджа

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

UPD: я понял, что теперь нет валидации, если люди напрямую вызывают create server функции. Мб стоит мерджить конфиги и CLI в этой функции тогда, хз)
Ну либо вообще отказаться от идеи того, что она является доступной извне. Типо если люди хотят подключить свой сервер к моку, то могут просто на своем сервере создать прокси

Comment on lines -35 to +38
if (
Array.isArray(mergedApiMockServerConfig.configs) &&
isPlainObject(mergedApiMockServerConfig.configs[0]) &&
'path' in mergedApiMockServerConfig.configs[0]
) {
const { configs } = mergedApiMockServerConfig;
const [firstConfig] = Array.isArray(configs) ? configs : [];

if (isPlainObject(firstConfig) && 'path' in firstConfig) {
validateApiMockServerConfig(mockConfig, 'rest');
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

логика та же самая, просто переписал чуток, чтобы не нужно было два раза писать Array.isArray(mergedApiMockServerConfig.configs) и доставать первый элемент через индекс

@MiaInturi
Copy link
Collaborator Author

@coderabbitai please review this pr. You can consider my comments for this pr as explanation for code snippets

@coderabbitai
Copy link

coderabbitai bot commented Dec 30, 2025

@MiaInturi: I'll review this PR for the zod v3 to v4 update. I'll take your comments into consideration as explanations for the code changes.

✅ 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.

@MiaInturi MiaInturi self-assigned this Dec 30, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

Caution

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

⚠️ Outside diff range comments (3)
src/utils/validate/queueSchema/queueSchema.ts (1)

15-15: Fix z.function() usage for Zod v4 compatibility.

In Zod v4, z.function() is no longer a schema type but a function factory requiring explicit input and output schemas. Using z.function() without arguments is invalid and will fail validation.

Since z.any() already accepts functions, z.function() is redundant in this union. Remove it:

data: z.any()

If stricter function validation is needed, define the function schema with input/output types:

data: z.union([z.function({ input: [...], output: z.unknown() }), z.any()])

Note: This pattern appears in multiple files (interceptorsSchema.ts, corsSchema.ts, routeConfigSchema.ts).

src/utils/validate/utils/entitiesSchema/entitiesSchema.ts (2)

48-57: Nested withoutCheckModeSchema may cause validation issues.

Line 53 applies withoutCheckModeSchema to plainEntityObjectiveValueSchema, which then pipes into a union. Since withoutCheckModeSchema uses z.looseObject({}).refine(...), it will reject arrays (from z.array(z.json()) in the union), as looseObject only accepts objects.

This means the plainEntityObjectiveValueSchema branch for arrays would never match within this nested context.

🔎 Suggested fix

If arrays should also be excluded from having checkMode, consider adjusting the logic:

     z.union([
       propertyLevelPlainEntityDescriptorSchema,
-      withoutCheckModeSchema(plainEntityObjectiveValueSchema),
+      withoutCheckModeSchema(z.record(z.string(), z.json())),
+      z.array(z.json()),
       plainEntityPrimitiveValueSchema
     ])

Or if arrays don't need the checkMode exclusion check, handle them separately in the union.


19-26: Fix z.function() calls to match Zod v4 API.

In Zod v4, z.function() must be called with explicit input and output schemas. The current usage of z.function() without arguments does not validate function signatures properly. Use z.function(z.tuple([]), z.void()) or provide appropriate input/output schemas instead. This pattern appears in lines 21 and 30 of this file and across multiple validation schemas in the codebase.

♻️ Duplicate comments (2)
bin/runFlatConfig.ts (1)

11-13: Consider post-merge validation to avoid false negatives.

Based on your comment, the current approach validates the raw config before merging CLI arguments. This can reject configs that would be valid after CLI overrides are applied (e.g., invalid port in config but valid --port from CLI).

Options to address this:

  1. Preferred: Validate the merged config (after line 23) instead of the raw config (line 11). This ensures validation reflects the actual runtime config.
  2. Alternative: Implement conditional validation—if the first element contains settings, merge CLI args first; otherwise validate before merging.

The current placement trades off early error detection for potential false positives.

🔎 Proposed fix: validate after merge
 export const runFlatConfig = (
   flatMockServerConfig: FlatMockServerConfig,
   { baseUrl, port, staticPath }: MockServerConfigArgv
 ) => {
   try {
-    validateFlatMockServerConfig(flatMockServerConfig);
     const [option, ...flatMockServerComponents] = flatMockServerConfig;
     const flatMockServerSettings = !('configs' in option) ? option : undefined;
 
     const mergedFlatMockServerConfig = [
       {
         ...flatMockServerSettings,
         ...(baseUrl && { baseUrl }),
         ...(port && { port }),
         ...(staticPath && { staticPath })
       },
       ...(flatMockServerSettings ? flatMockServerComponents : flatMockServerConfig)
     ] as FlatMockServerConfig;
 
+    validateFlatMockServerConfig(mergedFlatMockServerConfig);
     return startFlatMockServer(mergedFlatMockServerConfig);
   } catch (error: any) {
     console.error(error.message);
   }
 };
src/utils/validate/utils/entitiesSchema/entitiesSchema.ts (1)

78-88: Correct Zod v4 migration for z.record with explicit key type.

The explicit z.string() key schema is required in Zod v4. The nested z.discriminatedUnion usage is now properly supported. As noted in past comments, this leverages Zod v4's improved support for nested discriminated unions.

📜 Review details

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

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

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (42)
  • .gitignore
  • .husky/commit-msg
  • bin/cli.ts
  • bin/init.ts
  • bin/run.ts
  • bin/runFlatConfig.ts
  • package.json
  • src/server/createFlatMockServer/createFlatMockServer.ts
  • src/server/createGraphQLMockServer/createGraphQLMockServer.ts
  • src/server/createMockServer/createMockServer.ts
  • src/server/createRestMockServer/createRestMockServer.ts
  • src/utils/types/entities.ts
  • src/utils/types/server.ts
  • src/utils/validate/databaseConfigSchema/databaseConfigSchema.ts
  • src/utils/validate/getMostSpecificPathFromError.ts
  • src/utils/validate/getValidationMessage.ts
  • src/utils/validate/getValidationMessageFromPath.ts
  • src/utils/validate/graphqlConfigSchema/graphqlConfigSchema.ts
  • src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.test.ts
  • src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.ts
  • src/utils/validate/index.ts
  • src/utils/validate/isOnlyRequestedDataResolvingPropertyExists.ts
  • src/utils/validate/queueSchema/queueSchema.ts
  • src/utils/validate/restConfigSchema/restConfigSchema.ts
  • src/utils/validate/restConfigSchema/routeConfigSchema/routeConfigSchema.test.ts
  • src/utils/validate/restConfigSchema/routeConfigSchema/routeConfigSchema.ts
  • src/utils/validate/utils/checkModeSchema/checkModeSchema.ts
  • src/utils/validate/utils/entitiesSchema/entitiesSchema.test.ts
  • src/utils/validate/utils/entitiesSchema/entitiesSchema.ts
  • src/utils/validate/utils/extendedDiscriminatedUnion/extendedDiscriminatedUnion.test.ts
  • src/utils/validate/utils/extendedDiscriminatedUnion/extendedDiscriminatedUnion.ts
  • src/utils/validate/utils/index.ts
  • src/utils/validate/utils/jsonSchema/jsonSchema.ts
  • src/utils/validate/utils/nestedObjectOrArraySchema/nestedObjectOrArraySchema.ts
  • src/utils/validate/utils/oneKeyDispatchSchema/oneKeyDispatchSchema.ts
  • src/utils/validate/utils/plainObjectSchema/plainObjectSchema.ts
  • src/utils/validate/utils/requiredPropertiesSchema/requiredPropertiesSchema.ts
  • src/utils/validate/utils/sharedSchema/sharedSchema.ts
  • src/utils/validate/validateApiMockServerConfig.ts
  • src/utils/validate/validateFlatMockServerConfig.ts
  • src/utils/validate/validateMockServerConfig.ts
  • tsconfig.dev.json
💤 Files with no reviewable changes (13)
  • src/utils/validate/utils/nestedObjectOrArraySchema/nestedObjectOrArraySchema.ts
  • src/server/createMockServer/createMockServer.ts
  • src/utils/validate/utils/requiredPropertiesSchema/requiredPropertiesSchema.ts
  • src/utils/validate/isOnlyRequestedDataResolvingPropertyExists.ts
  • src/utils/validate/utils/plainObjectSchema/plainObjectSchema.ts
  • src/utils/validate/utils/extendedDiscriminatedUnion/extendedDiscriminatedUnion.test.ts
  • src/utils/validate/getMostSpecificPathFromError.ts
  • src/utils/validate/utils/extendedDiscriminatedUnion/extendedDiscriminatedUnion.ts
  • src/server/createFlatMockServer/createFlatMockServer.ts
  • src/utils/validate/getValidationMessageFromPath.ts
  • src/server/createRestMockServer/createRestMockServer.ts
  • src/utils/validate/utils/jsonSchema/jsonSchema.ts
  • src/server/createGraphQLMockServer/createGraphQLMockServer.ts
🧰 Additional context used
🧬 Code graph analysis (16)
bin/runFlatConfig.ts (2)
src/utils/validate/validateFlatMockServerConfig.ts (1)
  • validateFlatMockServerConfig (15-55)
examples/server/index.ts (1)
  • flatMockServerConfig (5-31)
src/utils/validate/validateFlatMockServerConfig.ts (3)
src/utils/validate/interceptorsSchema/interceptorsSchema.ts (1)
  • interceptorsSchema (3-6)
src/utils/validate/baseUrlSchema/baseUrlSchema.ts (1)
  • baseUrlSchema (3-3)
src/utils/validate/getValidationMessage.ts (1)
  • getValidationMessage (44-47)
src/utils/validate/utils/oneKeyDispatchSchema/oneKeyDispatchSchema.ts (2)
src/utils/helpers/isPlainObject/isPlainObject.ts (1)
  • isPlainObject (1-5)
src/utils/validate/getValidationMessage.ts (1)
  • getMostSpecificPathFromError (12-42)
src/utils/validate/queueSchema/queueSchema.ts (1)
src/utils/helpers/isPlainObject/isPlainObject.ts (1)
  • isPlainObject (1-5)
bin/init.ts (1)
bin/helpers/createTemplate.ts (1)
  • createTemplate (14-40)
src/utils/validate/restConfigSchema/restConfigSchema.ts (3)
src/utils/types/rest.ts (1)
  • RestMethod (7-7)
src/utils/validate/utils/sharedSchema/sharedSchema.ts (1)
  • stringForwardSlashSchema (3-3)
src/utils/validate/interceptorsSchema/interceptorsSchema.ts (1)
  • interceptorsSchema (3-6)
src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.ts (5)
src/utils/validate/utils/entitiesSchema/entitiesSchema.ts (2)
  • mappedEntitySchema (85-88)
  • variablesPlainEntitySchema (69-72)
src/utils/validate/interceptorsSchema/interceptorsSchema.ts (1)
  • interceptorsSchema (3-6)
src/utils/validate/settingsSchema/settingsSchema.ts (1)
  • settingsSchema (3-7)
src/utils/validate/queueSchema/queueSchema.ts (1)
  • queueSchema (8-23)
src/utils/validate/utils/oneKeyDispatchSchema/oneKeyDispatchSchema.ts (1)
  • oneKeyDispatchSchema (9-37)
src/utils/validate/restConfigSchema/routeConfigSchema/routeConfigSchema.test.ts (1)
src/utils/validate/getValidationMessage.ts (1)
  • getValidationMessage (44-47)
src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.test.ts (1)
src/utils/validate/getValidationMessage.ts (1)
  • getValidationMessage (44-47)
src/utils/validate/utils/entitiesSchema/entitiesSchema.test.ts (1)
src/utils/validate/getValidationMessage.ts (1)
  • getValidationMessage (44-47)
src/utils/validate/validateApiMockServerConfig.ts (6)
src/utils/validate/interceptorsSchema/interceptorsSchema.ts (1)
  • interceptorsSchema (3-6)
src/utils/validate/corsSchema/corsSchema.ts (1)
  • corsSchema (6-13)
src/utils/validate/databaseConfigSchema/databaseConfigSchema.ts (1)
  • databaseConfigSchema (5-10)
src/utils/validate/graphqlConfigSchema/graphqlConfigSchema.ts (1)
  • graphqlConfigSchema (32-36)
src/utils/validate/restConfigSchema/restConfigSchema.ts (1)
  • restConfigSchema (27-31)
src/utils/validate/getValidationMessage.ts (1)
  • getValidationMessage (44-47)
src/utils/validate/utils/entitiesSchema/entitiesSchema.ts (1)
src/utils/validate/utils/checkModeSchema/checkModeSchema.ts (3)
  • entityDescriptorSchema (61-90)
  • checkActualValueCheckModeSchema (10-10)
  • compareWithDescriptorValueCheckModeSchema (20-22)
src/utils/validate/databaseConfigSchema/databaseConfigSchema.ts (1)
src/utils/validate/utils/sharedSchema/sharedSchema.ts (2)
  • stringJsonFilenameSchema (5-5)
  • stringForwardSlashSchema (3-3)
src/utils/validate/validateMockServerConfig.ts (2)
src/utils/validate/interceptorsSchema/interceptorsSchema.ts (1)
  • interceptorsSchema (3-6)
src/utils/validate/getValidationMessage.ts (1)
  • getValidationMessage (44-47)
src/utils/validate/graphqlConfigSchema/graphqlConfigSchema.ts (4)
src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.ts (1)
  • routeConfigSchema (34-37)
src/utils/validate/interceptorsSchema/interceptorsSchema.ts (1)
  • interceptorsSchema (3-6)
src/utils/validate/utils/oneKeyDispatchSchema/oneKeyDispatchSchema.ts (1)
  • oneKeyDispatchSchema (9-37)
src/utils/validate/baseUrlSchema/baseUrlSchema.ts (1)
  • baseUrlSchema (3-3)
bin/cli.ts (4)
src/utils/types/server.ts (1)
  • MockServerConfigArgv (75-81)
src/utils/validate/baseUrlSchema/baseUrlSchema.ts (1)
  • baseUrlSchema (3-3)
src/utils/validate/portSchema/portSchema.ts (1)
  • portSchema (4-4)
src/utils/validate/staticPathSchema/staticPathSchema.ts (1)
  • staticPathSchema (12-15)
🔇 Additional comments (33)
tsconfig.dev.json (1)

34-34: LGTM! Appropriate cleanup of the exclude list.

Removing the non-existent vi.config.js from the TypeScript exclusions is correct and keeps the configuration accurate.

.gitignore (1)

101-101: No issue found with .cursor entry.

The .cursor entry is not a duplicate—it appears only once in the file at line 101. Adding this editor state file to the "IDE - VSCode" section is a reasonable housekeeping change, even if unrelated to the main PR objective.

bin/init.ts (1)

83-83: LGTM - Correctly removed unnecessary await.

The createTemplate function is synchronous (uses fs.cpSync, fs.readFileSync, fs.writeFileSync), so awaiting it was unnecessary. The try-catch block will still catch any synchronous errors thrown by createTemplate, so error handling is preserved.

package.json (2)

66-66: LGTM! Type-checking templates before build improves quality.

Adding TypeScript type-checking to the build process prevents shipping examples with type errors, which aligns well with the validation improvements in this PR.


94-94: Zod v4.1.13 is valid and has no security vulnerabilities.

Version 4.1.13 exists on npm and carries no known CVEs (the only Zod CVE, CVE-2023-4316, affected v3.21.0-3.22.3). Note that 4.2.1 is currently the latest version if you wish to adopt bug fixes, though 4.1.13 is stable.

The breaking changes introduced in Zod v4 (unified error API, z.function() schema overhaul, ZodError shape changes, new metadata and JSON Schema support) are well-documented with migration guides and community codemods available.

src/utils/validate/queueSchema/queueSchema.ts (2)

3-4: LGTM: Defensive plain object check added.

The import of isPlainObject supports the stricter validation logic, ensuring that only plain objects (not arrays, null, RegExp instances, etc.) are processed before checking for the 'data' property.


11-11: LGTM: Stricter validation prevents edge cases.

The addition of isPlainObject(value) before checking 'data' in value is a good defensive measure that prevents edge cases where the 'in' operator might be used on non-objects or where non-plain-objects with a 'data' property might pass through.

src/utils/validate/utils/checkModeSchema/checkModeSchema.ts (1)

28-28: LGTM: Correct Zod v4 type signature updates.

The change from the string literal 'strict' to z.core.$strict correctly reflects Zod v4's internal type system for strict object schemas.

Also applies to: 46-46, 54-54

bin/cli.ts (5)

1-1: LGTM!

The node:fs import is appropriately added to support the config file existence validation.


5-6: LGTM!

The validation schema imports are correctly added to support the new coercion logic.


12-15: LGTM!

The explicit type definition improves type safety and makes the relationship between CLI options and the config type more explicit.


52-52: LGTM!

The change from a type assertion to a plain object closure is cleaner, especially with the explicit type definition on lines 12-15.


71-77: LGTM!

The config file existence validation provides helpful early feedback to users. Using fs.existsSync is appropriate for this CLI use case.

src/utils/types/entities.ts (1)

47-55: LGTM: Improved type naming clarity.

The rename from NonCheckMode to WithoutCheckMode is more explicit and self-documenting. The type behavior remains unchanged—excluding checkMode from the type union.

src/utils/validate/utils/entitiesSchema/entitiesSchema.test.ts (1)

1-31: LGTM: Consistent migration to unified error handling.

The test correctly migrates from the two-step path extraction to the single getValidationMessage utility. The expected values (.value, .property.value) confirm that getValidationMessage returns path strings indicating error locations.

src/utils/validate/restConfigSchema/routeConfigSchema/routeConfigSchema.test.ts (1)

19-22: Verify empty string expectation for validation errors.

Similar to the GraphQL route config test, this test expects an empty string for validation messages when parsing fails. Validation errors should typically provide meaningful feedback about what's wrong.

Please confirm this is the intended behavior for incorrect data-resolving property combinations.

src/utils/validate/index.ts (1)

4-4: LGTM: Consolidated validation error API.

The replacement of getMostSpecificPathFromError and getValidationMessageFromPath with a single getValidationMessage export simplifies the public API and aligns with the broader error-handling consolidation across the codebase.

src/utils/validate/utils/index.ts (1)

1-4: LGTM: Validation utility consolidation.

The introduction of oneKeyDispatchSchema and removal of extendedDiscriminatedUnion, nestedObjectOrArraySchema, and plainObjectSchema streamlines the validation utilities. This aligns with the broader migration to Zod v4 and centralized dispatch-based validation patterns.

Note: This is a breaking change if any external consumers depend on the removed exports.

src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.test.ts (1)

19-22: The test expectation is correct; getValidationMessage returns the property path to the error, not a descriptive message.

The function extracts the most specific path from zod validation issues and formats it (e.g., .property.value or [0]). For root-level validation errors—such as the oneKeyDispatchSchema violations in this test (empty object {} or conflicting data and queue keys)—the path is empty, so getValidationMessage correctly returns an empty string. This is consistent with other tests in the codebase (e.g., restConfigSchema.test.ts and similar patterns). The production error messages concatenate this into messages like "Validation Error: configuration.property does not match the API schema" for nested errors, or "Validation Error: configuration does not match the API schema" for root-level errors.

src/utils/validate/validateMockServerConfig.ts (1)

8-8: LGTM! Validation refactor aligns with Zod v4 migration.

The changes consolidate error handling by using the new getValidationMessage utility and remove the plainObjectSchema wrapper for interceptors. This is consistent with the PR's broader refactoring strategy and Zod v4's improved handling of RegExp as objects.

Also applies to: 31-31, 40-40

src/utils/validate/utils/sharedSchema/sharedSchema.ts (1)

3-3: LGTM! Modern Zod v4 template literal schemas.

The migration from .startsWith() and .endsWith() string methods to z.templateLiteral() aligns with Zod v4's new string validation patterns. This provides better type inference and runtime validation.

Also applies to: 5-5

src/utils/validate/validateApiMockServerConfig.ts (1)

8-8: LGTM! Validation consolidation and schema extraction.

The refactor correctly:

  • Uses the new getValidationMessage utility for consistent error reporting
  • Removes the plainObjectSchema wrapper for interceptors
  • Extracts nested configs schemas using .shape.configs.optional(), which is a valid Zod pattern for conditional schema composition

Also applies to: 29-29, 32-33, 38-38

src/utils/validate/validateFlatMockServerConfig.ts (1)

8-8: LGTM! Flat config validation refactored for Zod v4.

The changes correctly:

  • Use the unified getValidationMessage utility
  • Remove plainObjectSchema wrappers for interceptors
  • Update the tuple schema to use Zod v4's z.tuple([...], restSchema) API for variable-length tuples, where the first element is a union of settings/component schemas and remaining elements are component schemas

Also applies to: 26-26, 34-34, 38-41, 47-49

src/utils/validate/getValidationMessage.ts (2)

3-5: TODO comment acknowledged.

The TODO to improve validation messages with detailed descriptions, types, and documentation links is a good enhancement for future work. Consider tracking this as a separate issue for better user experience.


44-47: LGTM! Unified validation message generation.

The getValidationMessage function provides a clean interface that consolidates path extraction and message formatting, replacing the previous two-function approach.

src/utils/validate/restConfigSchema/restConfigSchema.ts (1)

7-7: LGTM! REST config schema simplified.

The changes correctly remove the plainObjectSchema wrapper for interceptors validation and simplify imports. This aligns with Zod v4's improved object validation and the PR's overall refactoring strategy.

Also applies to: 15-15, 30-30

src/utils/validate/utils/entitiesSchema/entitiesSchema.ts (2)

14-17: Correct usage of Zod v4's z.json() type.

The migration to z.json() is appropriate for representing arbitrary JSON values. This is a new Zod v4 feature that properly validates JSON-compatible data structures.


42-46: Good use of z.looseObject() for Zod v4 migration.

The z.looseObject({}) is the correct Zod v4 replacement for allowing unknown keys. The refine to exclude checkMode property is a clever pattern for the discriminated union dispatch.

src/utils/validate/graphqlConfigSchema/graphqlConfigSchema.ts (2)

14-24: Shape spreading pattern is correct for Zod v4.

Using ...baseRequestConfigSchema.shape to compose strict objects is a valid pattern that maintains type safety while extending the base schema.


11-11: Simplified interceptors schema usage is cleaner.

Removing the plainObjectSchema wrapper and using interceptorsSchema.optional() directly is a good simplification that aligns with the broader refactoring in this PR.

Also applies to: 35-35

src/utils/validate/restConfigSchema/routeConfigSchema/routeConfigSchema.ts (1)

73-78: oneKeyDispatchSchema correctly replaces the union-based dispatch.

The migration to oneKeyDispatchSchema for routing based on data, file, or queue keys is a good improvement that provides clearer error messages when validation fails, addressing the issue described in the comment block above.

src/utils/validate/graphqlConfigSchema/routeConfigSchema/routeConfigSchema.ts (1)

8-18: Clean schema composition using shape spreading.

The consistent use of ...baseRouteConfigSchema.shape for schema composition and the oneKeyDispatchSchema for route type dispatch aligns well with the patterns established in the REST config schema. The structure is maintainable and type-safe.

Also applies to: 27-37

src/utils/validate/databaseConfigSchema/databaseConfigSchema.ts (1)

5-9: Correct Zod v4 migration for record schemas.

The removal of plainObjectSchema wrapper and direct use of z.record(z.string(), z.unknown()) is the proper Zod v4 approach. Using stringForwardSlashSchema (a template literal schema) as both key and value type for routes is valid and provides strong validation that both keys and values start with /.

Comment on lines +3 to +9
message=$(cat "$1")

if echo "$message" | (! grep -qF "${branch} ${emoji}") &&\
echo "$message" | (! grep -qF "Merge branch") &&\
echo "$message" | (! grep -qF "Merge remote-tracking branch");\
then
echo "$branch $emoji $(cat "$1")" > "$1"
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Inconsistent use of $message variable.

Line 3 reads the commit message into $message, but line 9 re-reads the file with $(cat "$1") instead of using the already-populated variable. Use $message consistently to avoid redundant I/O.

🔎 Proposed fix
-   echo "$branch $emoji $(cat "$1")" > "$1"
+   echo "$branch $emoji $message" > "$1"
🤖 Prompt for AI Agents
.husky/commit-msg around lines 3 to 9: the script reads the commit message into
the variable $message on line 3 but then re-reads the file with $(cat "$1") when
writing back on line 9; change that write to use the already-populated $message
variable (i.e., echo "$branch $emoji $message" > "$1") to avoid redundant file
I/O and ensure consistent use of the variable.

Comment on lines +5 to +7
if echo "$message" | (! grep -qF "${branch} ${emoji}") &&\
echo "$message" | (! grep -qF "Merge branch") &&\
echo "$message" | (! grep -qF "Merge remote-tracking branch");\
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Unnecessary subshells around negation.

The parentheses in (! grep -qF ...) create subshells that aren't needed. The negation can be applied directly to grep.

🔎 Proposed fix
-if echo "$message" | (! grep -qF "${branch} ${emoji}") &&\
-   echo "$message" | (! grep -qF "Merge branch") &&\
-   echo "$message" | (! grep -qF "Merge remote-tracking branch");\
+if ! echo "$message" | grep -qF "${branch} ${emoji}" &&\
+   ! echo "$message" | grep -qF "Merge branch" &&\
+   ! echo "$message" | grep -qF "Merge remote-tracking branch";\
 then
📝 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
if echo "$message" | (! grep -qF "${branch} ${emoji}") &&\
echo "$message" | (! grep -qF "Merge branch") &&\
echo "$message" | (! grep -qF "Merge remote-tracking branch");\
if ! echo "$message" | grep -qF "${branch} ${emoji}" &&\
! echo "$message" | grep -qF "Merge branch" &&\
! echo "$message" | grep -qF "Merge remote-tracking branch";\
then
🤖 Prompt for AI Agents
.husky/commit-msg lines 5-7: the code uses subshell negation like '(! grep -qF
"...")' which is unnecessary; remove the parentheses so the negation is applied
directly to grep (replace each '(! grep -qF "…")' with '! grep -qF "…"') and
keep the existing pipe and line-continuation/backslash structure unchanged.

Comment on lines 19 to 26
type: 'string',
coerce(value: any) {
try {
return baseUrlSchema.parse(value);
} catch {
throw new Error(`Invalid value for 'baseUrl': ${JSON.stringify(value)}`);
}
}
Copy link

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:

#!/bin/bash
# Search for validation message utilities
rg -n --type=ts 'getValidationMessage|validationMessage|formatValidationError' --max-count=20

Repository: siberiacancode/mock-config

Length of output: 3924


🏁 Script executed:

#!/bin/bash
# Look for files in src/utils directory
find . -path ./node_modules -prune -o -type f -name "*.ts" -print | grep -E '(utils|validate)' | head -20

Repository: siberiacancode/mock-config

Length of output: 1159


🏁 Script executed:

#!/bin/bash
# Examine the full context of bin/cli.ts around the mentioned lines
cat -n bin/cli.ts | sed -n '1,60p'

Repository: siberiacancode/mock-config

Length of output: 2011


🏁 Script executed:

#!/bin/bash
# Search for Zod error handling utilities or patterns
rg -n --type=ts 'treeifyError|z\.ZodError|formatZodError' --max-count=20

Repository: siberiacancode/mock-config

Length of output: 52


🏁 Script executed:

#!/bin/bash
# Check for any validation-related utilities in src directory
find . -path ./node_modules -prune -o -type f -name "*validat*" -print

Repository: siberiacancode/mock-config

Length of output: 223


🏁 Script executed:

#!/bin/bash
# Examine the getValidationMessage implementation
cat -n src/utils/validate/getValidationMessage.ts

Repository: siberiacancode/mock-config

Length of output: 2020


🏁 Script executed:

#!/bin/bash
# Look at how getValidationMessage is used in the validation functions
cat -n src/utils/validate/validateMockServerConfig.ts | sed -n '35,50p'

Repository: siberiacancode/mock-config

Length of output: 615


🏁 Script executed:

#!/bin/bash
# Check what information is available in Zod errors
cat -n src/utils/validate/getValidationMessage.ts | head -20

Repository: siberiacancode/mock-config

Length of output: 1100


🏁 Script executed:

#!/bin/bash
# Look at the validation schemas to understand error types
rg -n --type=ts 'baseUrlSchema|portSchema|staticPathSchema' -A 3 'src/utils/validate'

Repository: siberiacancode/mock-config

Length of output: 8559


🏁 Script executed:

#!/bin/bash
# Check if there are any other error formatting patterns in the codebase
rg -n --type=ts 'issue\.message|issue\.code' src/utils/validate/ | head -20

Repository: siberiacancode/mock-config

Length of output: 249


🏁 Script executed:

#!/bin/bash
# Check the actual schema definitions to understand what errors they can produce
cat -n src/utils/validate/portSchema/portSchema.ts

Repository: siberiacancode/mock-config

Length of output: 219


🏁 Script executed:

#!/bin/bash
# Check baseUrlSchema
cat -n src/utils/validate/baseUrlSchema/baseUrlSchema.ts

Repository: siberiacancode/mock-config

Length of output: 199


🏁 Script executed:

#!/bin/bash
# Look at the actual Zod error structure - check if issue.message is available
rg -n --type=ts 'issue\.message|z\.ZodIssue' src/utils/validate/getValidationMessage.ts -A 2

Repository: siberiacancode/mock-config

Length of output: 52


🏁 Script executed:

#!/bin/bash
# Check if there's a utility that extracts detailed error messages from Zod
rg -n --type=ts 'issue\[' src/utils/validate/ | head -10

Repository: siberiacancode/mock-config

Length of output: 52


🏁 Script executed:

#!/bin/bash
# Check the stringForwardSlashSchema to understand the full baseUrlSchema
rg -n --type=ts 'stringForwardSlashSchema' src/utils/validate/utils/ -A 5

Repository: siberiacancode/mock-config

Length of output: 398


🏁 Script executed:

#!/bin/bash
# Look for test files that might show what errors these schemas produce
find src/utils/validate -name "*.test.ts" | head -5 | xargs grep -l "baseUrlSchema\|portSchema" 2>/dev/null

Repository: siberiacancode/mock-config

Length of output: 54


🏁 Script executed:

#!/bin/bash
# Check if Zod error object includes message property by looking at test expectations
rg -n --type=ts 'error\.message|issue\.message' src/utils/validate/

Repository: siberiacancode/mock-config

Length of output: 52


🏁 Script executed:

#!/bin/bash
# Check what properties a Zod error issue has by examining how it's used
rg -n --type=ts 'issue\.' src/utils/validate/getValidationMessage.ts

Repository: siberiacancode/mock-config

Length of output: 506


🏁 Script executed:

#!/bin/bash
# Try to understand better by looking at a test that uses getValidationMessage with actual errors
cat -n src/utils/validate/utils/entitiesSchema/entitiesSchema.test.ts

Repository: siberiacancode/mock-config

Length of output: 1410


Use the existing getValidationMessage utility and extend error details from Zod validation failures.

The catch blocks discard Zod's validation error information and replace it with a generic message containing only the stringified value. This prevents users from understanding why a value is invalid.

The codebase already has a consolidated getValidationMessage utility in src/utils/validate/ that extracts validation paths, but it currently returns only the error location (e.g., .value), not the failure reason. A TODO comment in getValidationMessage.ts acknowledges this: "improve validation message with more detailed description as types and link to the documentation."

At minimum, use getValidationMessage to add the error path. Ideally, extend the error handling to include Zod's error code and message (available via issue.code and issue.message), so users see meaningful feedback like: Invalid value for 'port': -1 - Must be a non-negative integer instead of just Invalid value for 'port': -1.

Additional note on port coercion (line 34): The +value conversion is potentially redundant since yargs handles type: 'number', though this may be intentional to handle edge cases before schema validation.

Also applies to: 31-38, 43-50

Comment on lines +34 to 55
const { configs } = mergedApiMockServerConfig;
const [firstConfig] = Array.isArray(configs) ? configs : [];

if (isPlainObject(firstConfig) && 'path' in firstConfig) {
validateApiMockServerConfig(mockConfig, 'rest');
return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
}

if (
Array.isArray(mergedApiMockServerConfig.configs) &&
isPlainObject(mergedApiMockServerConfig.configs[0]) &&
('query' in mergedApiMockServerConfig.configs[0] ||
'operationName' in mergedApiMockServerConfig.configs[0])
isPlainObject(firstConfig) &&
('query' in firstConfig || 'operationName' in firstConfig)
) {
validateApiMockServerConfig(mockConfig, 'graphql');
return startGraphQLMockServer(mergedApiMockServerConfig as GraphQLMockServerConfig);
}

validateApiMockServerConfig(mockConfig, 'rest');
return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
}

validateMockServerConfig(mockConfig);
return startMockServer(mergedMockServerConfig);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Validate the merged config, not the original.

The validation calls on lines 38, 46, 50, and 54 validate mockConfig (the original config from the file), but the servers are started with mergedApiMockServerConfig or mergedMockServerConfig (which include CLI argument overrides for baseUrl, port, and staticPath).

This means CLI-provided values bypass validation, potentially allowing invalid configurations to start the server.

🔎 Proposed fix to validate merged configs
     if (isPlainObject(firstConfig) && 'path' in firstConfig) {
-      validateApiMockServerConfig(mockConfig, 'rest');
+      validateApiMockServerConfig(mergedApiMockServerConfig, 'rest');
       return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
     }

     if (
       isPlainObject(firstConfig) &&
       ('query' in firstConfig || 'operationName' in firstConfig)
     ) {
-      validateApiMockServerConfig(mockConfig, 'graphql');
+      validateApiMockServerConfig(mergedApiMockServerConfig, 'graphql');
       return startGraphQLMockServer(mergedApiMockServerConfig as GraphQLMockServerConfig);
     }

-    validateApiMockServerConfig(mockConfig, 'rest');
+    validateApiMockServerConfig(mergedApiMockServerConfig, 'rest');
     return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
   }

-  validateMockServerConfig(mockConfig);
+  validateMockServerConfig(mergedMockServerConfig);
   return startMockServer(mergedMockServerConfig);
📝 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
const { configs } = mergedApiMockServerConfig;
const [firstConfig] = Array.isArray(configs) ? configs : [];
if (isPlainObject(firstConfig) && 'path' in firstConfig) {
validateApiMockServerConfig(mockConfig, 'rest');
return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
}
if (
Array.isArray(mergedApiMockServerConfig.configs) &&
isPlainObject(mergedApiMockServerConfig.configs[0]) &&
('query' in mergedApiMockServerConfig.configs[0] ||
'operationName' in mergedApiMockServerConfig.configs[0])
isPlainObject(firstConfig) &&
('query' in firstConfig || 'operationName' in firstConfig)
) {
validateApiMockServerConfig(mockConfig, 'graphql');
return startGraphQLMockServer(mergedApiMockServerConfig as GraphQLMockServerConfig);
}
validateApiMockServerConfig(mockConfig, 'rest');
return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
}
validateMockServerConfig(mockConfig);
return startMockServer(mergedMockServerConfig);
const { configs } = mergedApiMockServerConfig;
const [firstConfig] = Array.isArray(configs) ? configs : [];
if (isPlainObject(firstConfig) && 'path' in firstConfig) {
validateApiMockServerConfig(mergedApiMockServerConfig, 'rest');
return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
}
if (
isPlainObject(firstConfig) &&
('query' in firstConfig || 'operationName' in firstConfig)
) {
validateApiMockServerConfig(mergedApiMockServerConfig, 'graphql');
return startGraphQLMockServer(mergedApiMockServerConfig as GraphQLMockServerConfig);
}
validateApiMockServerConfig(mergedApiMockServerConfig, 'rest');
return startRestMockServer(mergedApiMockServerConfig as RestMockServerConfig);
}
validateMockServerConfig(mergedMockServerConfig);
return startMockServer(mergedMockServerConfig);
🤖 Prompt for AI Agents
In bin/run.ts around lines 34 to 55, the validation calls currently pass the
original mockConfig while the server is started with
mergedApiMockServerConfig/mergedMockServerConfig (which include CLI overrides);
update the four validate calls to validate the merged objects instead:
validateApiMockServerConfig(mergedApiMockServerConfig, 'rest'),
validateApiMockServerConfig(mergedApiMockServerConfig, 'graphql'), the fallback
validateApiMockServerConfig(mergedApiMockServerConfig, 'rest'), and finally
validateMockServerConfig(mergedMockServerConfig) so CLI-provided values are
validated before starting the servers.

Comment on lines +94 to 96
// TODO:
// this type doesn't corresponds to validation schema
configs: Array<GraphQLRequestConfig | RestRequestConfig>;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Document the type/schema mismatch specifics.

The TODO comment flags a mismatch between this TypeScript type and the validation schema. For better maintainability, consider expanding the comment to clarify:

  • What specific aspect doesn't correspond?
  • What is the actual schema shape?
  • Is there a tracking issue for resolving this mismatch?
🤖 Prompt for AI Agents
In src/utils/types/server.ts around lines 94 to 96, the TODO comment about the
type/schema mismatch is too vague; update it to document exactly which
properties on GraphQLRequestConfig | RestRequestConfig don’t match the
validation schema (list differing field names/types), paste or summarize the
actual validation schema shape (required fields, optional fields, field types),
and add a tracking reference (issue or PR link/ID) and owner to resolve it; then
indicate next steps (either update the TS type to match schema or update schema
to match types) so future maintainers know how to fix it.

COMPARE_WITH_DESCRIPTOR_VALUE_CHECK_MODES
);

// TODO why this fn in that file?
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

TODO comment flags architectural concern.

The TODO questions the placement of the entityDescriptorSchema function in this file. This is worth addressing to improve code organization.

Would you like me to analyze the function's dependencies and suggest a better location, or open an issue to track this refactoring?

🤖 Prompt for AI Agents
In src/utils/validate/utils/checkModeSchema/checkModeSchema.ts around line 24
there is a TODO questioning why entityDescriptorSchema is defined in this file;
analyze the function's dependencies and either relocate it to a more appropriate
module (e.g., a central schemas or validators folder such as src/schemas or
src/utils/validate/schemas) or open a tracked issue for the refactor. To fix:
inspect the function's imports/exports and usages across the codebase, create a
new file for the schema in the chosen location, move the function there and
export it, update all import sites to reference the new path, remove the TODO,
and add/update a small unit test or one-line comment pointing to the new
location so the architecture intent is clear.

Comment on lines 9 to 37
export const oneKeyDispatchSchema = <S extends Record<string, z.ZodTypeAny>>(schemasByKey: S) => {
const keys = Object.keys(schemasByKey);

return z
.custom((value) => isPlainObject(value))
.superRefine((value, ctx) => {
const existingKeys = keys.filter((key) => Object.prototype.hasOwnProperty.call(value, key));

if (existingKeys.length !== 1) {
ctx.addIssue({
code: 'custom',
path: []
});
return;
}

const [key] = existingKeys;
const schema = schemasByKey[key];

const result = schema.safeParse(value);
if (!result.success) {
const issuePath = getMostSpecificPathFromError(result.error.issues);
ctx.addIssue({
code: 'custom',
path: issuePath
});
}
});
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add descriptive error messages to custom validation issues.

The oneKeyDispatchSchema implementation correctly enforces single-key dispatch validation, but the custom issues lack descriptive messages:

  1. Lines 18-22: When existingKeys.length !== 1, the issue provides no message explaining whether zero keys or multiple keys were found.
  2. Lines 31-34: When schema validation fails, the original error details are discarded and replaced with a generic custom issue.

Without messages, debugging validation failures will be challenging for users.

🔎 Proposed fix to add descriptive error messages
 export const oneKeyDispatchSchema = <S extends Record<string, z.ZodTypeAny>>(schemasByKey: S) => {
   const keys = Object.keys(schemasByKey);
 
   return z
     .custom((value) => isPlainObject(value))
     .superRefine((value, ctx) => {
       const existingKeys = keys.filter((key) => Object.prototype.hasOwnProperty.call(value, key));
 
       if (existingKeys.length !== 1) {
         ctx.addIssue({
           code: 'custom',
-          path: []
+          path: [],
+          message:
+            existingKeys.length === 0
+              ? `Expected exactly one of [${keys.join(', ')}], but none were provided`
+              : `Expected exactly one of [${keys.join(', ')}], but found multiple: [${existingKeys.join(', ')}]`
         });
         return;
       }
 
       const [key] = existingKeys;
       const schema = schemasByKey[key];
 
       const result = schema.safeParse(value);
       if (!result.success) {
         const issuePath = getMostSpecificPathFromError(result.error.issues);
         ctx.addIssue({
           code: 'custom',
-          path: issuePath
+          path: issuePath,
+          message: result.error.issues[0]?.message || 'Validation failed'
         });
       }
     });
 };
🤖 Prompt for AI Agents
In src/utils/validate/utils/oneKeyDispatchSchema/oneKeyDispatchSchema.ts around
lines 9 to 37, the custom validation issues are missing descriptive messages;
update the two ctx.addIssue calls so they include helpful, specific messages:
when existingKeys.length !== 1, set message to indicate whether zero keys or
multiple keys were found and list the keys present (e.g., "expected exactly one
key but found 0" or "expected exactly one key but found 2: keyA, keyB"); when
the delegated schema safeParse fails, preserve the original error information by
including the most specific error path and the original Zod error message(s) in
the ctx.addIssue (or convert result.error.issues into one or more ctx.addIssue
calls) so the user sees the underlying validation message(s) along with the
path.

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

Labels

enhancement New feature or request release@5.0.0 issues for release@5.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant