Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 3 additions & 15 deletions packages/spec/src/shared/error-map.zod.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,21 +5,9 @@ import { suggestFieldType, formatSuggestion, findClosestMatches } from './sugges
import { FieldType } from '../data/field.zod';

/**
* Zod v4 raw issue structure (subset used by the error map).
* Zod v4 raw issue type used by the error map.
*/
export interface ObjectStackRawIssue {
code: string;
path?: (string | number)[];
input?: unknown;
values?: unknown[];
origin?: string;
minimum?: number;
maximum?: number;
expected?: string;
format?: string;
keys?: string[];
[key: string]: unknown;
}
export type ObjectStackRawIssue = z.core.$ZodRawIssue;

/**
* ObjectStack Custom Zod Error Map
Expand DownExpand Up@@ -142,7 +130,7 @@ export const objectStackErrorMap = (issue: ObjectStackRawIssue): { message: stri
* Zod Issue interface (subset needed for formatting).
*/
interface ZodIssueMinimal {
path: (string | number)[];
path: PropertyKey[];
message: string;
code?: string;
}
Comment on lines 132 to 136

CopilotAIFeb 12, 2026

Copy link

Choose a reason for hiding this comment

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

ZodIssueMinimal.path is now PropertyKey[] (can include symbol). Downstream formatting currently relies on implicit string conversion (join('.') / template literals), which can throw for symbol values. Consider normalizing path segments with String(...) before joining/printing to keep formatting robust.

Copilot uses AI. Check for mistakes.
Expand Down
13 changes: 9 additions & 4 deletions packages/spec/src/stack.zod.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -266,10 +266,15 @@ function validateCrossReferences(config: ObjectStackDefinition): string[] {
// Validate hook → object references
if (config.hooks) {
for (const hook of config.hooks) {
if (hook.object && !objectNames.has(hook.object)) {
errors.push(
`Hook '${hook.name}' references object '${hook.object}' which is not defined in objects.`,
);
if (hook.object) {
const hookObjects = Array.isArray(hook.object) ? hook.object : [hook.object];
for (const obj of hookObjects) {
if (!objectNames.has(obj)) {
Comment on lines +269 to +272

CopilotAIFeb 12, 2026

Copy link

Choose a reason for hiding this comment

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

This change adds support for hook.object being a string[], but stack.test.ts only covers the string case. Please add strict-mode tests for (1) hook.object as an array where all objects exist, and (2) an array containing an undefined object to confirm the new normalization logic and error message behavior.

Copilot uses AI. Check for mistakes.
errors.push(
`Hook '${hook.name}' references object '${obj}' which is not defined in objects.`,
);
Comment on lines +269 to +275

CopilotAIFeb 12, 2026

Copy link

Choose a reason for hiding this comment

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

HookSchema explicitly allows wildcard object: '*' (and tests cover it), but strict cross-reference validation currently treats '*' like a normal object name and will always error when objects are defined. Consider treating '*' as a special case (skip validation for it, and/or allow it in arrays) so strict mode doesn’t reject valid hook configs.

Copilot uses AI. Check for mistakes.
}
}
}
}
}
Expand Down
Loading