Skip to content

Conversation

@luxass
Copy link
Member

@luxass luxass commented Jan 5, 2026

🔗 Linked issue

📚 Description

This PR renames the schemas, and fixes that broke when changing the schemas.

Some schemas like the lockfile, and the superRefine will be added in a separate PR.

Summary by CodeRabbit

  • New Features

    • File listings now consistently include modification timestamps across all API responses.
  • Bug Fixes

    • Statistics data is now always returned as complete objects with default values instead of potentially missing data.
    • File tree responses are standardized to ensure consistent structure and data availability across different Unicode versions.

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

luxass added 3 commits January 5, 2026 17:46
- Renamed `BaseItemSchema` to `FileEntryBaseSchema` for clarity.
- Updated `FileEntrySchema` tests to use `toMatchSchema` for better readability.
- Added tests for `FileEntryListSchema` and `UCDStoreManifestSchema` to enhance coverage.
- Improved validation logic for expected files in the manifest schema.
@changeset-bot
Copy link

changeset-bot bot commented Jan 5, 2026

⚠️ No Changeset found

Latest commit: f1e82e6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

📝 Walkthrough

Walkthrough

This PR refactors the file-tree type system throughout the codebase, renaming UnicodeTree to UnicodeFileTree, adding lastModified field handling, introducing new utility functions (findFileByPath, flattenFilePaths), making statistics non-nullable with defaults, and updating related schemas, tests, and client code.

Changes

Cohort / File(s) Summary
API Route & Schema Registration
apps/api/src/routes/v1_versions/$version.ts
Updated GET /{version}/file-tree response schema from UnicodeTreeSchema to UnicodeFileTreeSchema; added runtime schema registration for UnicodeFileTreeNode; cast response to UnicodeFileTree before returning; initialized statistics to concrete object with default counters
Core Type Definitions
packages/schemas/src/types.ts
Added new exported DeepOmit<T, K> generic utility type for recursively omitting keys from object types, handling arrays and nested structures
File-tree Schema Refactoring
packages/schemas/src/fs.ts
Introduced FileEntryBaseSchema, FileEntryDirectorySchema, FileEntryFileSchema; updated FileEntrySchema union; added FileEntryListSchema; restructured UCDStoreManifestSchema nesting
Unicode Schema Overhaul
packages/schemas/src/unicode.ts
Replaced UnicodeTreeNode/UnicodeTreeSchema with recursive UnicodeFileTreeNode/UnicodeFileTreeSchema structures; added UnicodeFileTreeNodeWithoutLastModified via DeepOmit; updated UnicodeVersionDetailsSchema to provide default statistics (0 values) instead of optional
Schema Exports
packages/schemas/src/index.ts
Renamed exported schemas/types from UnicodeTree* to UnicodeFileTree*; added UnicodeFileTreeNodeWithoutLastModified export
Comprehensive Schema Tests
packages/schemas/test/{api.test.ts, fs.test.ts, manifest.test.ts, unicode.test.ts}
Added extensive unit tests for ApiErrorSchema, FileEntry*Schema, UCDStoreManifestSchema, UnicodeVersionDetailsSchema, UnicodeFileTreeNodeSchema, and related schemas
File Tree Utilities
packages/shared/src/files.ts
Introduced new exported utilities: findFileByPath<T> for recursive node lookup and flattenFilePaths<T> for flattening hierarchical trees to path arrays
Generic Filter Refactoring
packages/shared/src/filter.ts
Replaced TreeEntry type with generic T extends UnicodeFileTreeNodeWithoutLastModified; updated filterTreeStructure and internal functions to be generic while maintaining filtering logic
Filter & Flatten Exports
packages/shared/src/{index.ts, flatten.ts}
Removed TreeEntry export; removed deprecated packages/shared/src/flatten.ts module; added findFileByPath and flattenFilePaths to public exports
Filter Tests
packages/shared/test/{files.test.ts, filter.test.ts, flatten.test.ts}
Added comprehensive tests for findFileByPath and flattenFilePaths; updated filter tests to use const type assertions; removed old flatten test file
API Client Update
packages/client/src/resources/versions.ts
Updated import from UnicodeTreeSchema to UnicodeFileTreeSchema; no functional changes
Client Tests
packages/client/test/resources/versions.test.ts
Replaced local baseUrl with UCDJS_API_BASE_URL constant; added lastModified metadata to mock file-tree data; updated URL construction patterns
API Tests
apps/api/test/routes/v1_versions/$version.test.ts
Replaced static file list with UnicodeFileTree shape via flattenFilePaths; added lastModified timestamps to mock responses; updated assertions to match flattened structure; introduced cache-header and version-specific tests
Store Type Updates
packages/ucd-store-v2/src/{types.ts, operations/files/tree.ts}, packages/ucd-store/src/store.ts
Updated getFileTree return type from UnicodeTreeNode[] to UnicodeFileTreeNodeWithoutLastModified[]; updated imports accordingly
Store Tests
packages/ucd-store/test/{internal/files.test.ts, maintenance/analyze.test.ts}
Updated type imports and assertions from UnicodeTree to UnicodeFileTree
Test Utils Updates
packages/test-utils/src/mock-store/types.ts, packages/test-utils/test/mock-store/mock-store.test.ts
Updated MockStoreFiles to use UnicodeFileTree; added lastModified fields to mock entries; added const type assertions
Utils Export
packages/utils/src/index.ts
Removed TreeEntry from public type exports
VSCode Integration
vscode/src/lib/files.ts
Updated type import from UnicodeTreeNode to UnicodeFileTreeNodeWithoutLastModified
Dependencies
pnpm-workspace.yaml
Updated zod 4.2.1 → 4.3.5; updated apache-autoindex-parse 4.1.0 → 5.0.2

Sequence Diagram(s)

File-tree retrieval and validation flow with the new schema structure:

sequenceDiagram
    participant Client as Client/API
    participant Route as GET /{version}/file-tree
    participant Schema as UnicodeFileTreeSchema
    participant Registry as Schema Registry
    
    Client->>Route: Request file-tree
    Route->>Route: Fetch and calculate file-tree
    Route->>Route: Cast to UnicodeFileTree type
    Route->>Schema: Validate against UnicodeFileTreeSchema
    Schema->>Schema: Validate each UnicodeFileTreeNode<br/>(recursive directory/file structure)
    Schema->>Registry: Register UnicodeFileTreeNode schema
    Registry-->>Route: Schema registration confirmed
    Schema-->>Route: Validation result (success)
    Route-->>Client: JSON response with<br/>normalized lastModified (number)
Loading

Version details retrieval with mandatory statistics:

sequenceDiagram
    participant Client as Client
    participant Route as GET /{version}
    participant Stats as Statistics<br/>Calculation
    participant Schema as UnicodeVersionDetailsSchema
    
    Client->>Route: Request version details
    Route->>Stats: calculateStatistics() or use tmp
    Stats-->>Route: stats object
    Route->>Route: Initialize statistics with defaults<br/>(newBlocks, totalBlocks, etc.)
    Route->>Schema: Validate UnicodeVersionDetails<br/>including statistics
    Schema-->>Route: Validation (statistics always object)
    Route-->>Client: JSON with mandatory<br/>statistics object
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Behold the tree transformed anew,
From Unicode to FileTree true!
With lastModified in every node,
Our flat paths light the rabbit's road.
Statistics locked, no null in sight—
The schema sings in type-safe light! 🌳✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'refactor: update schemas and fix some issues' is vague and generic. It describes schema updates broadly without specifying the key change (renaming Unicode tree schemas or introducing FileEntry types). Consider a more specific title like 'refactor: rename Unicode tree schemas to UnicodeFileTree and update FileEntry types' to better convey the main changes.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

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.

@github-actions github-actions bot added the pkg: schemas Changes related to the FS Bridge package. label Jan 5, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

🌏 Preview Deployments

Application Status Preview URL
API ⏭️ Skipped N/A
Website ⏭️ Skipped N/A

Built from commit: f1e82e6cbe71932122a8dfe705d52e360cac4b7d


🤖 This comment will be updated automatically when you push new commits to this PR.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

📋 OpenAPI Schema Analysis

Summary

Schema Components

Change Type Count Details
🟢 Added 3 New schema components
🔴 Removed 2 ⚠️ Breaking
🟡 Modified 2 Changed schema definitions

Overall Status

Status Result
⚠️ Breaking Changes Yes - This PR contains breaking changes

Detailed Changes

📋 Schema Components Changes

Added Schemas (3):

  • UnicodeFileTreeNode
  • UnicodeFileTree
  • FileEntry

Removed Schemas (2): ⚠️

  • UnicodeTreeNode
  • UnicodeTree

Modified Schemas (2):

  • UnicodeVersionDetails
  • FileEntryList

Important

⚠️ Breaking Changes Detected

This PR contains breaking changes that require maintainer approval.
Maintainers: Add the approve-breaking-openapi label to approve these changes.


🤖 This comment is automatically updated when you push new commits.

luxass added 5 commits January 5, 2026 19:42
Introduce `findFileByPath` and `flattenFilePaths` functions to enhance file tree manipulation capabilities. The new functions allow for recursive searching of files by path and flattening of hierarchical file structures into an array of paths. Additionally, remove the old `flatten` implementation to streamline the codebase.
Removed the hardcoded `baseUrl` and replaced it with `UCDJS_API_BASE_URL` for consistency across the version tests. Added `lastModified` timestamps to file entries in the mock file tree for better accuracy in testing.
@luxass luxass changed the title refactor(schemas): rename schemas and improve validation tests refactor: update schemas and fix some issues Jan 5, 2026
@github-actions github-actions bot added pkg: ucd-store Changes related to the UCD Store package. pkg: utils Changes related to the Utils package. apps: api Changes related to the API. pkg: shared Changes related to the Shared package. pkg: test-utils Changes related to the test-utils package. labels Jan 5, 2026
@luxass luxass marked this pull request as ready for review January 5, 2026 19:30
Copilot AI review requested due to automatic review settings January 5, 2026 19:30
@codecov
Copy link

codecov bot commented Jan 5, 2026

Codecov Report

❌ Patch coverage is 81.25000% with 9 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
apps/api/src/routes/v1_versions/$version.ts 33.33% 3 Missing and 1 partial ⚠️
packages/schemas/src/unicode.ts 80.00% 2 Missing ⚠️
packages/shared/src/files.ts 91.30% 2 Missing ⚠️
vscode/src/lib/files.ts 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors schema naming conventions and fixes related type issues. The main changes involve renaming UnicodeTree* schemas to UnicodeFileTree* for better clarity and consistency, updating dependencies (zod 4.2.1 → 4.3.5, apache-autoindex-parse 4.1.0 → 5.0.2), and reorganizing shared utilities for file tree operations.

Key Changes:

  • Renamed schema types from UnicodeTree* to UnicodeFileTree* throughout the codebase
  • Consolidated file tree utilities (flattenFilePaths, findFileByPath) into a single files.ts module in the shared package
  • Updated lastModified field to use number | null instead of optional number | undefined for consistency
  • Added comprehensive test coverage for the new schema structures

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pnpm-workspace.yaml Updated zod to 4.3.5 and apache-autoindex-parse to 5.0.2
pnpm-lock.yaml Lockfile updates for dependency version changes
vscode/src/lib/files.ts Updated import from UnicodeTreeNode to UnicodeFileTreeNodeWithoutLastModified
packages/utils/src/index.ts Removed TreeEntry export as it's no longer used
packages/ucd-store/test/ Updated type imports to use new UnicodeFileTree* naming
packages/ucd-store/src/store.ts Updated return type to UnicodeFileTreeNodeWithoutLastModified[]
packages/ucd-store-v2/src/ Updated types and interfaces to use new schema names
packages/test-utils/ Updated mock types and test fixtures to use UnicodeFileTree
packages/shared/src/ Consolidated file utilities into files.ts, removed flatten.ts, updated filter.ts
packages/shared/test/ Migrated flatten tests to files.test.ts and updated filter tests
packages/schemas/src/ Major refactoring: renamed schemas, added DeepOmit utility type, updated lastModified handling
packages/schemas/test/ Added comprehensive test coverage for new schemas
packages/client/ Updated schema imports and usage
apps/api/ Updated route handlers to use new schemas and handle type transformations
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +176 to +189
}).superRefine((data, ctx) => {
if (data.type === "directory" && !("children" in data)) {
ctx.addIssue({
code: "custom",
message: "Directory nodes must include children.",
});
}

if (data.type === "file" && "children" in data) {
ctx.addIssue({
code: "custom",
message: "File nodes cannot have children.",
});
}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

The superRefine validation logic checks if directory nodes have children and if file nodes don't have children. However, this validation is redundant because the schema already defines these constraints through the union of UnicodeFileTreeDirectorySchema (which has children) and UnicodeFileTreeFileSchema (which doesn't). The Zod union will ensure that only the correct shape is accepted. Consider removing this superRefine to avoid duplicate validation.

Suggested change
}).superRefine((data, ctx) => {
if (data.type === "directory" && !("children" in data)) {
ctx.addIssue({
code: "custom",
message: "Directory nodes must include children.",
});
}
if (data.type === "file" && "children" in data) {
ctx.addIssue({
code: "custom",
message: "File nodes cannot have children.",
});
}

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +7
export type DeepOmit<T, K extends PropertyKey> = T extends object
? T extends any[]
? DeepOmit<T[number], K>[]
: {
[P in Exclude<keyof T, K>]: DeepOmit<T[P], K>;
}
: T;
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

The DeepOmit utility type doesn't properly handle the case where T is an array. The current implementation T extends any[] ? DeepOmit<T[number], K>[] : ... will recursively omit from array elements but won't preserve array-specific properties correctly for union types like UnicodeFileTreeNode[]. This could lead to incorrect type inference when used with complex recursive structures. Consider testing this type thoroughly or using a well-tested utility library implementation.

Suggested change
export type DeepOmit<T, K extends PropertyKey> = T extends object
? T extends any[]
? DeepOmit<T[number], K>[]
: {
[P in Exclude<keyof T, K>]: DeepOmit<T[P], K>;
}
: T;
export type DeepOmit<T, K extends PropertyKey> = T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepOmit<U, K>>
: T extends object
? {
[P in Exclude<keyof T, K>]: DeepOmit<T[P], K>;
}
: T;

Copilot uses AI. Check for mistakes.
@greptile-apps
Copy link

greptile-apps bot commented Jan 5, 2026

Greptile Summary

Renamed schemas from UnicodeTree* to UnicodeFileTree* for better clarity, consolidated tree-related code into files.ts, and changed lastModified from number to number | null for better null handling.

  • Renamed UnicodeTreeSchemaUnicodeFileTreeSchema and related types
  • Changed lastModified type from number to number | null in FileEntryBaseSchema
  • Removed custom TreeEntry type, now using UnicodeFileTreeNodeWithoutLastModified consistently
  • Deleted flatten.ts and moved flattenFilePaths to new files.ts along with findFileByPath
  • Added DeepOmit utility type for recursively omitting properties
  • Changed statistics field to use .default() with zero values instead of optional
  • Added superRefine validation to ensure directories have children and files don't
  • Updated all imports across packages, stores, client, and vscode extension

Confidence Score: 4/5

  • Safe to merge with one type safety concern that should be addressed
  • The refactoring is well-executed with consistent renames across the codebase. One issue: the type cast in $version.ts:264 bypasses validation where traverse() returns lastModified: number | undefined but schema expects number | null. This could allow undefined values through. All tests pass, but runtime validation is being circumvented.
  • Pay attention to apps/api/src/routes/v1_versions/$version.ts - the type cast at line 264 needs proper data transformation

Important Files Changed

Filename Overview
packages/schemas/src/unicode.ts Renamed tree schemas to UnicodeFileTree*, added superRefine validation for directory/file children constraints, changed statistics to use .default() instead of optional
packages/schemas/src/fs.ts Changed lastModified from number to `number
packages/schemas/src/types.ts Added new DeepOmit utility type for recursively omitting properties from nested objects and arrays
packages/shared/src/files.ts New file merging findFileByPath and flattenFilePaths functions, now using UnicodeFileTreeNodeWithoutLastModified instead of custom TreeNode interface
apps/api/src/routes/v1_versions/$version.ts Updated to use renamed UnicodeFileTree* schemas, changed statistics handling to always return default object, added type cast for traverse() result due to lastModified type mismatch

Sequence Diagram

sequenceDiagram
    participant Client
    participant API as API Route<br/>(v1_versions/$version.ts)
    participant Traverse as apache-autoindex-parse<br/>(traverse)
    participant Unicode as unicode.org
    participant Schemas as @ucdjs/schemas<br/>(UnicodeFileTree*)

    Client->>API: GET /api/v1/versions/{version}/file-tree
    API->>API: Resolve version (latest → stable version)
    API->>API: Map UCD version
    API->>Traverse: traverse(unicode.org/Public/{version}/ucd)
    Traverse->>Unicode: Fetch directory listing
    Unicode-->>Traverse: HTML with file entries
    Traverse->>Traverse: Parse entries (lastModified: number | undefined)
    Traverse-->>API: Return tree structure
    Note over API: Type cast: as UnicodeFileTree<br/>(undefined → null mismatch)
    API->>Schemas: Expected: UnicodeFileTreeSchema<br/>(lastModified: number | null)
    API-->>Client: JSON response with file tree
    
    Note over Schemas: UnicodeFileTreeNodeSchema validates:<br/>- Directories must have children<br/>- Files cannot have children
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

29 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link
Contributor

@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: 1

Fix all issues with AI Agents 🤖
In @pnpm-workspace.yaml:
- Line 61: The package entry "apache-autoindex-parse: 5.0.2" in
pnpm-workspace.yaml references a non-existent public release; update that entry
to a published version (for example change to "apache-autoindex-parse: 3.0.3")
or remove the explicit version and let the package.json specify it, or if you
intend to use a private registry, add/verify the registry configuration (and any
auth) so pnpm can resolve "apache-autoindex-parse" to the private 5.0.2 package.

Caution

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

⚠️ Outside diff range comments (1)
apps/api/src/routes/v1_versions/$version.ts (1)

256-264: Type cast may mask undefined values for lastModified at runtime.

The comment acknowledges that traverse returns lastModified as number | undefined, but the cast to UnicodeFileTree assumes it's always number. If traverse returns entries with undefined for lastModified, the API will return undefined values despite the schema declaring number.

Consider either:

  1. Transforming the result to ensure lastModified is always a number (e.g., default to 0 or Date.now())
  2. Updating the schema to allow null for lastModified
🔎 Proposed fix to ensure lastModified is always a number
-      // We cast the result to UnicodeFileTree because the traverse function
-      // returns entries that uses lastModified as `number | undefined`.
-      // But we can't use the `number | undefined` type in the API schema.
-      // So we need to return lastModified as `number | null` always.
-      return c.json(result as UnicodeFileTree, 200);
+      // Transform the result to ensure lastModified is always a number
+      // since traverse returns `number | undefined` but API schema requires `number`
+      const normalizeLastModified = (entries: typeof result): UnicodeFileTree => {
+        return entries.map(entry => ({
+          ...entry,
+          lastModified: entry.lastModified ?? 0,
+          ...(entry.type === "directory" && entry.children
+            ? { children: normalizeLastModified(entry.children) }
+            : {}),
+        })) as UnicodeFileTree;
+      };
+      return c.json(normalizeLastModified(result), 200);

As per coding guidelines, remember to regenerate the OpenAPI spec by running pnpm build:openapi after changing API routes or Zod schemas.

🧹 Nitpick comments (5)
packages/client/test/resources/versions.test.ts (1)

141-143: Consider using consistent mockFetch signature.

This test uses the direct call signature mockFetch("GET", url, handler) while other tests in this file use the array-wrapped form mockFetch([["GET", url, handler]]). Consider using a consistent pattern throughout the file for maintainability.

packages/schemas/src/fs.ts (1)

38-42: Consider using z.number().nullable() for conciseness.

The current z.number().or(z.null()) works correctly, but z.number().nullable() is more idiomatic in Zod and produces the same result.

🔎 Suggested change
 const FileEntryBaseSchema = z.object({
   name: z.string(),
   path: z.string(),
-  lastModified: z.number().or(z.null()),
+  lastModified: z.number().nullable(),
 });
packages/schemas/src/unicode.ts (1)

170-190: The directory validation check may be redundant.

The superRefine check at line 177 (!("children" in data)) verifies directories have children, but UnicodeFileTreeDirectorySchema already enforces children as a required field via .extend(). The Zod union parsing would fail before reaching superRefine if children is missing from a directory node.

The file check at line 184 is useful as a defensive measure since FileEntryFileSchema doesn't explicitly forbid extra properties.

packages/shared/test/files.test.ts (1)

110-114: Redundant assertion.

The not.toEqual check on line 112 is redundant since line 113 already asserts toBeUndefined(). If the result is undefined, it inherently won't equal the object.

Proposed simplification
     const result = findFileByPath(files, "folder/nested.txt");
-    expect(result).not.toEqual({ type: "file", name: "nested.txt", path: "/folder/nested.txt", lastModified: null });
     expect(result).toBeUndefined();
apps/api/test/routes/v1_versions/$version.test.ts (1)

29-44: expectedFiles variable appears unused — consider removing or using it.

The expectedFiles array is defined but not used in the current tests. Each test defines its own mock data inline. Consider either:

  1. Removing this unused variable
  2. Using it in the tests to reduce duplication
🔎 Proposed fix to remove unused variable
-    const expectedFiles = [
-      { type: "file", name: "file1.txt", path: "file1.txt", lastModified: 1755287100000 },
-      { type: "file", name: "file2.txt", path: "file2.txt", lastModified: 1755287100000 },
-      {
-        type: "directory",
-        name: "subdir",
-        path: "subdir/",
-        lastModified: 1755287100000,
-      },
-      {
-        type: "directory",
-        name: "emoji",
-        path: "emoji/",
-        lastModified: 1755287100000,
-      },
-    ] satisfies Entry[];
-
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0261e07 and f1e82e6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • apps/api/src/routes/v1_versions/$version.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/client/src/resources/versions.ts
  • packages/client/test/resources/versions.test.ts
  • packages/schemas/src/fs.ts
  • packages/schemas/src/index.ts
  • packages/schemas/src/types.ts
  • packages/schemas/src/unicode.ts
  • packages/schemas/test/api.test.ts
  • packages/schemas/test/fs.test.ts
  • packages/schemas/test/manifest.test.ts
  • packages/schemas/test/unicode.test.ts
  • packages/shared/src/files.ts
  • packages/shared/src/filter.ts
  • packages/shared/src/flatten.ts
  • packages/shared/src/index.ts
  • packages/shared/test/files.test.ts
  • packages/shared/test/filter.test.ts
  • packages/shared/test/flatten.test.ts
  • packages/test-utils/src/mock-store/types.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
  • packages/ucd-store-v2/src/operations/files/tree.ts
  • packages/ucd-store-v2/src/types.ts
  • packages/ucd-store/src/store.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/utils/src/index.ts
  • pnpm-workspace.yaml
  • vscode/src/lib/files.ts
💤 Files with no reviewable changes (2)
  • packages/shared/src/flatten.ts
  • packages/shared/test/flatten.test.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{test,spec}.?(c|m)[jt]s?(x)

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.?(c|m)[jt]s?(x): Import test utilities from #test-utils/* path aliases instead of @ucdjs/test-utils in test files to avoid build step requirements and prevent cyclic dependencies
Use testdir() from vitest-testdirs to create temporary test directories in filesystem tests
Use mockStoreApi() utility from #test-utils/mock-store for MSW-based mocking of the UCD API in test files

Files:

  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/schemas/test/unicode.test.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/schemas/test/fs.test.ts
  • packages/schemas/test/manifest.test.ts
  • packages/shared/test/filter.test.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
  • packages/shared/test/files.test.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/schemas/test/api.test.ts
  • packages/client/test/resources/versions.test.ts
apps/api/test/**/*.{test,spec}.?(c|m)[jt]s?(x)

📄 CodeRabbit inference engine (AGENTS.md)

Place API app tests in apps/api/test/routes/** for endpoint tests and apps/api/test/unit/** for unit tests with mocks

Files:

  • apps/api/test/routes/v1_versions/$version.test.ts
apps/api/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Regenerate OpenAPI spec by running 'pnpm build:openapi' after changing API routes or Zod schemas

Files:

  • apps/api/src/routes/v1_versions/$version.ts
apps/api/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

apps/api/src/**/*.ts: Build API (apps/api) using Hono web framework with OpenAPI plugin (@hono/zod-openapi) and organize routes by version and type
Use Zod schemas for defining API route schemas and request/response types in the API application

Files:

  • apps/api/src/routes/v1_versions/$version.ts
apps/api/src/routes/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Document API endpoints with OpenAPI annotations using @hono/zod-openapi decorators

Files:

  • apps/api/src/routes/v1_versions/$version.ts
🧠 Learnings (24)
📓 Common learnings
Learnt from: luxass
Repo: ucdjs/ucd PR: 6
File: packages/cli/src/cmd/codegen/fields.ts:68-82
Timestamp: 2025-05-04T11:52:22.858Z
Learning: User prefers to address the issue with Node.js API compatibility (`Dirent.parentPath` not being part of Node's API and the `recursive: true` option for `readdir` being only available in Node 21+) in a separate PR rather than the current one.
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to **/*.{test,spec}.?(c|m)[jt]s?(x) : Use mockStoreApi() utility from #test-utils/mock-store for MSW-based mocking of the UCD API in test files

Applied to files:

  • packages/test-utils/src/mock-store/types.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/schemas/test/fs.test.ts
  • packages/schemas/test/manifest.test.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/schemas/test/api.test.ts
  • packages/client/test/resources/versions.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to **/*.{test,spec}.?(c|m)[jt]s?(x) : Import test utilities from #test-utils/* path aliases instead of ucdjs/test-utils in test files to avoid build step requirements and prevent cyclic dependencies

Applied to files:

  • packages/test-utils/src/mock-store/types.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/utils/src/index.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/schemas/test/fs.test.ts
  • packages/schemas/test/manifest.test.ts
  • packages/shared/test/filter.test.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
  • packages/shared/test/files.test.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/client/test/resources/versions.test.ts
📚 Learning: 2025-06-09T05:10:32.105Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 45
File: packages/ucd-store/src/download.ts:24-24
Timestamp: 2025-06-09T05:10:32.105Z
Learning: In the ucd-store package refactor, picomatch was moved from direct usage in download.ts to internal usage within the createPathFilter function in filter.ts. The pattern format is still picomatch-compatible, so JSDoc comments referencing picomatch pattern format remain correct.

Applied to files:

  • packages/test-utils/src/mock-store/types.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/shared/src/index.ts
  • packages/utils/src/index.ts
  • packages/ucd-store/src/store.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/ucd-store-v2/src/types.ts
  • packages/schemas/test/fs.test.ts
  • packages/schemas/test/manifest.test.ts
  • packages/shared/test/filter.test.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
  • packages/ucd-store-v2/src/operations/files/tree.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/shared/src/filter.ts
  • packages/schemas/src/fs.ts
  • packages/client/test/resources/versions.test.ts
  • packages/shared/src/files.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to packages/*/tsconfig.json : Use ucdjs-tooling/tsconfig for TypeScript configuration in new packages

Applied to files:

  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/ucd-store-v2/src/types.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Use File System Bridge Pattern (ucdjs/fs-bridge) abstraction for file system operations to support multiple backends (Node.js, HTTP, in-memory)

Applied to files:

  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/ucd-store/src/store.ts
  • packages/ucd-store-v2/src/types.ts
📚 Learning: 2025-07-13T09:23:43.820Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 107
File: apps/api/src/routes/v1_files.ts:18-32
Timestamp: 2025-07-13T09:23:43.820Z
Learning: UNICODE_STABLE_VERSION from luxass/unicode-utils-new refers to a specific Unicode version string (not a dynamic value), and the validation logic in the files API correctly checks the normalized version (after "latest" substitution) against UNICODE_VERSION_METADATA rather than the mappedVersion from resolveUCDVersion().

Applied to files:

  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/schemas/test/unicode.test.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/client/src/resources/versions.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/schemas/src/index.ts
  • packages/client/test/resources/versions.test.ts
  • apps/api/src/routes/v1_versions/$version.ts
  • packages/schemas/src/unicode.ts
📚 Learning: 2025-05-04T11:52:22.858Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 6
File: packages/cli/src/cmd/codegen/fields.ts:68-82
Timestamp: 2025-05-04T11:52:22.858Z
Learning: User prefers to address the issue with Node.js API compatibility (`Dirent.parentPath` not being part of Node's API and the `recursive: true` option for `readdir` being only available in Node 21+) in a separate PR rather than the current one.

Applied to files:

  • packages/shared/src/index.ts
  • packages/utils/src/index.ts
  • packages/shared/test/filter.test.ts
  • packages/ucd-store-v2/src/operations/files/tree.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/shared/src/files.ts
📚 Learning: 2025-07-20T05:37:40.565Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 131
File: tooling/eslint-plugin/package.json:0-0
Timestamp: 2025-07-20T05:37:40.565Z
Learning: In the ucdjs/ucd project, internal tooling packages (private packages in the tooling/ directory) export TypeScript files directly without requiring a build step, unlike published packages which use tsdown to build and export from ./dist/. Examples include ucdjs/tsdown-config and ucdjs/eslint-plugin.

Applied to files:

  • packages/utils/src/index.ts
  • packages/ucd-store/src/store.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/ucd-store-v2/src/types.ts
📚 Learning: 2025-08-17T10:06:18.009Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 206
File: packages/ucd-store/src/internal/repair.ts:88-96
Timestamp: 2025-08-17T10:06:18.009Z
Learning: The internal__clean function in ucdjs/ucd-store can be safely called with versions: [] and a directories parameter to clean up only specific directories without processing any version files or modifying the manifest. When versions is empty, the analysis returns no results, skipping all file deletion logic, but the directory cleanup section still processes directories from the directories parameter.

Applied to files:

  • packages/ucd-store/src/store.ts
📚 Learning: 2025-06-29T11:20:13.668Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 87
File: packages/worker-shared/tsconfig.build.json:1-4
Timestamp: 2025-06-29T11:20:13.668Z
Learning: In the ucdjs/ucd project, the packages use tsdown instead of tsc for building libraries. The tsconfig.build.json files are primarily for IDE experience and type checking, not for direct compilation, so including "test" directories in these configs doesn't affect build output.

Applied to files:

  • packages/ucd-store/test/internal/files.test.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
📚 Learning: 2025-08-23T05:20:36.940Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 209
File: packages/ucd-store/test/clean.test.ts:9-9
Timestamp: 2025-08-23T05:20:36.940Z
Learning: In the ucdjs/ucd codebase using modern Vitest, the assert export from "vitest" works as a callable function assert(condition, message) and provides TypeScript type narrowing, making it the preferred choice over expect() for runtime assertions that need compile-time type safety. The existing usage pattern assert(condition, message) throughout the test suite is working correctly.

Applied to files:

  • packages/schemas/test/fs.test.ts
  • packages/schemas/test/manifest.test.ts
  • packages/shared/test/filter.test.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
  • packages/schemas/test/api.test.ts
📚 Learning: 2025-08-23T05:20:36.940Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 209
File: packages/ucd-store/test/clean.test.ts:9-9
Timestamp: 2025-08-23T05:20:36.940Z
Learning: In the ucdjs/ucd codebase, Vitest's assert import works as a callable function assert(condition, message) and provides TypeScript type narrowing, making it the preferred choice over expect() for runtime assertions that also need compile-time type safety.

Applied to files:

  • packages/schemas/test/manifest.test.ts
  • packages/test-utils/test/mock-store/mock-store.test.ts
📚 Learning: 2025-08-23T05:16:26.866Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 209
File: packages/ucd-store/test/clean.test.ts:9-9
Timestamp: 2025-08-23T05:16:26.866Z
Learning: In the ucdjs/ucd codebase, the team prefers using `assert(condition, message)` over `expect(condition).toBeTruthy()` because assert provides TypeScript type narrowing while expect doesn't. This is important for maintaining type safety after runtime validation checks.

Applied to files:

  • packages/schemas/test/manifest.test.ts
📚 Learning: 2025-10-14T07:15:35.199Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 326
File: packages/shared/src/ucd-config.ts:34-58
Timestamp: 2025-10-14T07:15:35.199Z
Learning: In packages/shared/src/ucd-config.ts, the `getDefaultUCDEndpointConfig` function uses a build-time define `__UCD_ENDPOINT_DEFAULT_CONFIG__` that is replaced at build time by the bundler. The `??` operator is evaluated at build time, so the final code contains no runtime branching. Therefore, runtime unit tests for this function are not valuable—the build process itself handles the injection and fallback logic.

Applied to files:

  • packages/test-utils/test/mock-store/mock-store.test.ts
  • apps/api/test/routes/v1_versions/$version.test.ts
  • packages/client/test/resources/versions.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to apps/api/test/**/*.{test,spec}.?(c|m)[jt]s?(x) : Place API app tests in apps/api/test/routes/** for endpoint tests and apps/api/test/unit/** for unit tests with mocks

Applied to files:

  • packages/shared/test/files.test.ts
  • packages/schemas/test/api.test.ts
📚 Learning: 2025-06-14T05:20:20.149Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 56
File: packages/utils/src/ucd-files/validate.ts:115-130
Timestamp: 2025-06-14T05:20:20.149Z
Learning: Node.js 22 supports the `recursive` option in `fs.readdir()` (introduced in Node.js 18.17.0), which returns a flattened string array of all descendant files and directories when `recursive: true` is passed.

Applied to files:

  • packages/shared/test/files.test.ts
  • packages/shared/src/files.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to apps/api/src/**/*.ts : Build API (apps/api) using Hono web framework with OpenAPI plugin (hono/zod-openapi) and organize routes by version and type

Applied to files:

  • apps/api/test/routes/v1_versions/$version.test.ts
  • apps/api/src/routes/v1_versions/$version.ts
📚 Learning: 2025-07-01T04:10:40.989Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 89
File: apps/api/src/routes/v1_files.ts:42-43
Timestamp: 2025-07-01T04:10:40.989Z
Learning: The `traverse` method from the `apache-autoindex-parse` library always returns an array, even when HTTP requests fail or encounter network errors. Network failures are handled internally by the library rather than throwing exceptions, so catch blocks are primarily for parsing errors or unexpected JavaScript runtime errors.

Applied to files:

  • apps/api/test/routes/v1_versions/$version.test.ts
📚 Learning: 2025-07-01T04:10:40.989Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 89
File: apps/api/src/routes/v1_files.ts:42-43
Timestamp: 2025-07-01T04:10:40.989Z
Learning: The `traverse` method from the `apache-autoindex-parse` library always returns an array, even when HTTP requests fail or encounter network errors. The method handles request failures internally rather than throwing exceptions.

Applied to files:

  • apps/api/test/routes/v1_versions/$version.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to apps/api/src/**/*.ts : Use Zod schemas for defining API route schemas and request/response types in the API application

Applied to files:

  • packages/schemas/test/api.test.ts
  • packages/schemas/src/fs.ts
  • apps/api/src/routes/v1_versions/$version.ts
  • packages/schemas/src/unicode.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Require Node.js >= 22.18 and pnpm 10.26.1 for development in this project

Applied to files:

  • pnpm-workspace.yaml
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to apps/api/src/routes/**/*.ts : Document API endpoints with OpenAPI annotations using hono/zod-openapi decorators

Applied to files:

  • apps/api/src/routes/v1_versions/$version.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to apps/api/src/**/*.{ts,tsx} : Regenerate OpenAPI spec by running 'pnpm build:openapi' after changing API routes or Zod schemas

Applied to files:

  • apps/api/src/routes/v1_versions/$version.ts
🧬 Code graph analysis (10)
packages/ucd-store-v2/src/types.ts (2)
packages/ucd-store-v2/src/operations/files/tree.ts (1)
  • GetFileTreeOptions (15-21)
packages/shared/src/async/try-catch.ts (1)
  • OperationResult (7-7)
packages/schemas/test/fs.test.ts (2)
packages/schemas/src/index.ts (3)
  • FileEntrySchema (5-5)
  • FileEntryListSchema (4-4)
  • UCDStoreManifestSchema (6-6)
packages/schemas/src/fs.ts (3)
  • FileEntrySchema (52-62)
  • FileEntryListSchema (85-88)
  • UCDStoreManifestSchema (4-34)
packages/test-utils/test/mock-store/mock-store.test.ts (2)
packages/ucd-store-v2/src/store.ts (1)
  • tree (165-167)
packages/test-utils/src/msw.ts (1)
  • HttpResponse (11-11)
packages/ucd-store-v2/src/operations/files/tree.ts (1)
packages/shared/src/async/try-catch.ts (1)
  • OperationResult (7-7)
packages/shared/test/files.test.ts (1)
packages/shared/src/files.ts (2)
  • findFileByPath (12-31)
  • flattenFilePaths (53-73)
apps/api/test/routes/v1_versions/$version.test.ts (3)
packages/test-utils/src/msw.ts (1)
  • mockFetch (16-19)
apps/api/test/helpers/request.ts (2)
  • json (33-35)
  • executeRequest (15-40)
apps/api/wrangler-types.d.ts (1)
  • env (10237-10237)
packages/schemas/src/fs.ts (1)
packages/schemas/src/index.ts (1)
  • FileEntrySchema (5-5)
apps/api/src/routes/v1_versions/$version.ts (2)
apps/api/src/routes/v1_versions/utils.ts (1)
  • calculateStatistics (141-199)
apps/api/src/types.ts (1)
  • HonoEnv (1-3)
packages/shared/src/files.ts (2)
packages/shared/src/index.ts (2)
  • findFileByPath (8-8)
  • flattenFilePaths (8-8)
tooling/moonbeam/src/esm-loader.mjs (1)
  • entries (44-44)
packages/schemas/src/unicode.ts (2)
packages/schemas/src/fs.ts (2)
  • FileEntryFileSchema (48-50)
  • FileEntryDirectorySchema (44-46)
packages/schemas/src/types.ts (1)
  • DeepOmit (1-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Agent
  • GitHub Check: Greptile Review
  • GitHub Check: test (macos-latest)
  • GitHub Check: test (windows-latest)
🔇 Additional comments (65)
packages/utils/src/index.ts (1)

2-2: TreeEntry removal from public API is safe and verified.

The removal of TreeEntry from packages/utils/src/index.ts exports is confirmed safe. Comprehensive search shows no imports or usages of this type exist in the codebase, and TreeEntry no longer exists in the shared package. The change aligns with the broader schema refactoring objectives.

packages/ucd-store/test/maintenance/analyze.test.ts (2)

1-1: LGTM: Schema rename correctly applied.

The import change from UnicodeTree to UnicodeFileTree aligns with the PR's schema refactoring objectives.


14-41: LGTM: Type assertion correctly updated.

The MOCK_FILES type assertion has been properly updated to use UnicodeFileTree, maintaining consistency with the import change. The mock data structure correctly represents a file tree with all required fields.

pnpm-workspace.yaml (1)

56-56: No issues found; zod 4.3.5 is a safe patch-version update.

Zod 4.3.5 exists and has no known security vulnerabilities. This is a patch version update within 4.x, which carries minimal risk.

packages/schemas/src/types.ts (1)

1-7: LGTM!

The DeepOmit utility type is well-implemented. It correctly handles the three cases: arrays (recursively applies to elements), objects (excludes specified keys and recurses on values), and primitives (returns as-is). This is a clean approach for creating UnicodeFileTreeNodeWithoutLastModified.

packages/client/test/resources/versions.test.ts (2)

1-6: LGTM!

Good use of #test-utils/msw path alias for test utilities as per coding guidelines. The import of UCDJS_API_BASE_URL from @ucdjs/env centralizes the base URL configuration appropriately.


33-44: LGTM!

Mock data correctly includes the lastModified field on all file tree entries, aligning with the updated UnicodeFileTreeSchema structure.

packages/schemas/src/fs.ts (4)

4-14: LGTM!

The UCDStoreManifestSchema structure with nested defaults is well-designed. The outer .default({}) ensures missing version keys get the default object with expectedFiles: [].


44-62: LGTM!

Clean schema composition using extend() for the directory and file variants, and proper union with descriptive metadata.


63-81: Noted: Deferred validation for path conventions.

The commented superRefine validation for path conventions (leading slash, trailing slash for directories) is appropriately marked as a TODO pending #420. The comments clearly explain the intended behavior.


85-90: LGTM!

FileEntryListSchema with proper meta and type export provides a clean public API for array validation.

packages/schemas/src/unicode.ts (5)

1-3: LGTM!

Clean imports establishing the dependency on the new DeepOmit type and shared file entry schemas from ./fs.


64-94: LGTM!

The manual interface definitions correctly mirror the Zod schema structure. The comment explaining the Hono ZOD OpenAPI limitation for recursive types provides good context for this design decision.


116-125: LGTM!

Providing default zero values for statistics makes the API more ergonomic by eliminating null checks while preserving semantic clarity (zeros indicate missing/unknown data).


153-168: LGTM!

The recursive schema definition using z.lazy() is the correct pattern for self-referential types. The explicit type annotation on UnicodeFileTreeDirectorySchema and the OpenAPI $ref hint in meta ensure proper type inference and documentation generation.


192-201: LGTM!

Clean type exports. The UnicodeFileTreeNodeWithoutLastModified type correctly uses DeepOmit to recursively strip lastModified from the tree structure, which is useful for the VSCode extension and other consumers that don't need modification timestamps.

vscode/src/lib/files.ts (1)

1-10: LGTM!

The type change from UnicodeTreeNode to UnicodeFileTreeNodeWithoutLastModified correctly reflects that the VSCode extension doesn't need lastModified metadata for tree rendering. This is a clean type-only migration with no runtime behavior changes.

packages/client/src/resources/versions.ts (2)

5-5: LGTM!

Import correctly updated to use the renamed UnicodeFileTreeSchema.


44-51: LGTM!

The getFileTree method correctly uses the renamed UnicodeFileTreeSchema for response validation, maintaining consistency with the schema refactor.

packages/shared/test/filter.test.ts (5)

1-3: LGTM!

Imports are minimal and focused. The removal of the TreeEntry type import (previously used for test data typing) aligns with the schema refactor.


674-719: LGTM!

Test fixtures correctly use as const assertions for type literals, enabling proper type inference without requiring explicit type imports. The test data appropriately omits lastModified since the filter logic operates on path patterns, not timestamps.


881-885: LGTM!

Consistent use of as const assertions in this test fixture.


896-919: LGTM!

Nested structure test fixture correctly updated with as const assertions.


1038-1073: LGTM!

Edge case test fixture for files without extensions properly uses as const assertions.

packages/shared/src/index.ts (1)

8-9: LGTM! Public API updated for file-tree refactor.

The new exports findFileByPath and flattenFilePaths replace the previous flatten and TreeEntry surface, aligning with the broader UnicodeTree → UnicodeFileTree migration across the codebase.

packages/ucd-store/test/internal/files.test.ts (1)

1-1: LGTM! Type imports updated correctly.

The test now uses UnicodeFileTree type to match the refactored schemas. The mock response data appropriately includes lastModified fields for the new schema structure.

Also applies to: 42-42

packages/test-utils/src/mock-store/types.ts (1)

2-2: LGTM! Mock store types aligned with schema refactor.

The MockStoreFiles type now correctly uses UnicodeFileTree instead of UnicodeTree, maintaining consistency with the updated schemas throughout the codebase.

Also applies to: 84-84

packages/ucd-store-v2/src/types.ts (1)

4-4: LGTM! File-tree operation types updated correctly.

The tree method now returns UnicodeFileTreeNodeWithoutLastModified[], accurately reflecting the schema refactor. The type name clearly indicates that lastModified is excluded from the nodes returned by this operation.

Also applies to: 173-173

packages/ucd-store/src/store.ts (1)

4-4: LGTM! Store method signature updated for schema refactor.

The getFileTree method now correctly returns UnicodeFileTreeNodeWithoutLastModified[], maintaining consistency with the updated schemas and the v2 store implementation.

Also applies to: 142-142

packages/shared/test/files.test.ts (2)

1-4: LGTM! Imports are appropriate.

The imports are correctly using @ucdjs/schemas for the type and vitest for testing. No test utilities from the repository are needed here, so the imports comply with the coding guidelines.


206-437: LGTM! Comprehensive test coverage for flattenFilePaths.

The test suite covers a wide range of scenarios including edge cases (empty arrays, empty directories), nested structures, and the prefix parameter behavior. The test data correctly reflects the UnicodeFileTreeNodeWithoutLastModified constraint used by the implementation.

packages/schemas/test/manifest.test.ts (1)

1-87: LGTM! Well-structured schema validation tests.

The test suite thoroughly covers validation scenarios for UCDStoreVersionManifestSchema including valid cases (with files, empty array, nested paths) and rejection cases (missing field, wrong type, non-string elements). The use of toMatchSchema custom matcher is consistent with other test files in the PR.

packages/schemas/test/fs.test.ts (4)

1-4: LGTM! Imports and setup are correct.

The imports correctly bring in the schemas from ../src/fs and the type reference directive ensures the custom matcher types are available.


7-85: LGTM! FileEntrySchema tests are comprehensive.

Good coverage of valid entries (directory, file) and invalid cases (missing fields, invalid type, missing name/path). The mix of toMatchSchema for detailed assertions and safeParse for simple rejection checks is appropriate.


87-135: LGTM! FileEntryListSchema tests cover essential cases.

The tests verify valid lists, empty lists, and rejection of lists containing invalid entries.


137-211: LGTM! UCDStoreManifestSchema tests are thorough.

The tests correctly validate the record-based manifest structure where each version key maps to an object with expectedFiles. The default value behavior (empty array when expectedFiles is missing) is properly tested, aligning with the schema definition using .default([]).

packages/schemas/test/unicode.test.ts (4)

1-10: LGTM! Imports correctly reference the renamed schemas.

The imports properly use the new UnicodeFileTreeNodeSchema and UnicodeFileTreeSchema names, consistent with the PR's schema renaming from UnicodeTree* to UnicodeFileTree*.


11-131: LGTM! UnicodeVersionSchema tests are comprehensive.

Excellent coverage of all version types (stable, draft, unsupported), mapped UCD versions, and rejection cases for invalid data formats.


168-300: LGTM! UnicodeFileTreeNodeSchema tests validate structural constraints.

The tests correctly verify that:

  • lastModified is required (even if nullable)
  • Files cannot have children
  • Directories must have children
  • Nested structures are properly validated

302-407: LGTM! UnicodeFileTreeSchema and UnicodeVersionDetailsSchema tests.

The tests cover essential validation scenarios including tree structure validation, default statistics handling, and rejection of invalid (negative) statistics values.

packages/shared/src/files.ts (2)

1-31: LGTM! findFileByPath implementation is correct.

The function correctly:

  • Falls back to name if path is undefined
  • Recursively searches directory children
  • Returns the matching node or undefined

The type-safe generic approach works well with the UnicodeFileTreeNodeWithoutLastModified constraint.


53-73: LGTM! flattenFilePaths implementation is correct.

The function correctly:

  • Validates input is an array
  • Uses prependLeadingSlash for consistent path formatting with prefix
  • Recursively processes directory children
  • Only collects file paths (not directory paths)

The prefix parameter is designed for prepending a base path (like a URL prefix) rather than building paths from directory names, which makes sense given that each node already has a complete path property.

packages/schemas/test/api.test.ts (3)

1-4: LGTM! Test file setup is correct.

The imports and type reference directive are properly configured for testing the API schemas.


7-71: LGTM! ApiErrorSchema tests are well-structured.

Good use of it.each for parameterized testing of HTTP status codes, and comprehensive coverage of validation scenarios including missing fields and type mismatches.


73-195: LGTM! UCDWellKnownConfigSchema tests are thorough.

The tests correctly validate:

  • Complete configuration with all fields
  • Default values when optional fields are omitted
  • Rejection of missing/incomplete endpoints
  • Type validation for version and versions fields
packages/schemas/src/index.ts (1)

17-31: Schema exports correctly renamed to UnicodeFileTree.*

The exports properly reflect the PR's schema renaming:

  • UnicodeTreeNodeSchemaUnicodeFileTreeNodeSchema
  • UnicodeTreeSchemaUnicodeFileTreeSchema
  • Added new type UnicodeFileTreeNodeWithoutLastModified

All internal usages throughout the codebase have been updated accordingly. The new type is actively used across packages (vscode, ucd-store-v2, shared, ucd-store) in filters, type constraints, and operation return types.

Note: This is a breaking change for external consumers using the old export names.

packages/test-utils/test/mock-store/mock-store.test.ts (4)

1-6: LGTM!

The import update from UnicodeTree to UnicodeFileTree correctly reflects the schema rename, and test utilities are properly imported from #test-utils/* path aliases as per coding guidelines.


199-223: LGTM!

The test correctly uses UnicodeFileTree type, includes the required lastModified field, and properly types the HttpResponse.json generic parameter.


409-439: LGTM!

The customTree variable is properly typed as UnicodeFileTree with the required lastModified field.


976-1026: LGTM!

Good use of Date.now() for the lastModified field to provide realistic test data, and the test properly validates the hook behavior with the updated UnicodeFileTree type.

packages/ucd-store-v2/src/operations/files/tree.ts (2)

1-4: LGTM!

The import update to UnicodeFileTreeNodeWithoutLastModified correctly reflects the schema changes. This type appropriately represents file tree nodes in the store context where lastModified may not always be available from local filesystem operations.


31-37: LGTM!

The JSDoc and function signature correctly reflect the updated return type. The type is consistent with the store.ts implementation at lines 141-163 which uses the same UnicodeFileTreeNodeWithoutLastModified[] type.

apps/api/src/routes/v1_versions/$version.ts (4)

1-6: LGTM!

Import updates correctly reflect the schema renames. Using Zod schemas for API route definitions follows the coding guidelines for the API application.


112-112: LGTM!

Schema correctly updated to UnicodeFileTreeSchema for the OpenAPI response definition.


212-231: Statistics are now always returned with defaults — verify this is intentional.

The statistics object is now always included in the response with default zero values, even when calculateStatistics returns null (e.g., when bucket is unavailable or files are missing). This is a behavior change from potentially returning undefined statistics.

This approach ensures consistent API response shape, which is good for clients. However, consumers should be aware that zero values may indicate "not available" rather than "actually zero."


236-237: LGTM!

Registering UnicodeFileTreeNode in the OpenAPI registry ensures proper schema documentation for the recursive tree structure.

apps/api/test/routes/v1_versions/$version.test.ts (6)

1-10: LGTM!

Imports correctly use #test-utils/* path aliases per coding guidelines, and the flattenFilePaths utility from @ucdjs-internal/shared enables cleaner assertions on nested file tree structures.


46-93: LGTM!

Good test coverage with proper mocking of the recursive directory traversal. Using flattenFilePaths for assertions makes the test more readable and maintainable.


95-142: LGTM!

Good test coverage for the latest version alias, correctly mocking the resolved version endpoints.


182-193: LGTM!

Good use of reduce with proper type assertions to separate file and directory entries for structural validation.


266-304: LGTM!

Error handling tests correctly validate the structured error response format with the error.message property.


310-370: LGTM!

Cache tests are appropriately marked as todo with a clear explanation of the Vitest Pool Workers caching issues. The test structure is solid and will be ready when the underlying issue is resolved.

packages/shared/src/filter.ts (3)

1-4: LGTM!

Import correctly updated to use UnicodeFileTreeNodeWithoutLastModified as the base type constraint for the generic filter function.


200-206: LGTM!

Good use of generics to make filterTreeStructure reusable with different node types while preserving the input type in the output. This allows the function to work with both UnicodeFileTree and UnicodeFileTreeNodeWithoutLastModified[] types.


208-245: No changes needed—the generic type implementation is correct.

The code properly handles type preservation for nested children. The DeepOmit<UnicodeFileTreeNode, "lastModified"> type recursively removes lastModified at all nesting levels, including within the children arrays. When T extends UnicodeFileTreeNodeWithoutLastModified, the entry.children property is correctly typed as UnicodeFileTreeNodeWithoutLastModified[], which satisfies the recursive call's generic constraint. The spread operator at line 236 correctly preserves the type while overriding the children property with the filtered results.

@luxass luxass merged commit 7828f33 into main Jan 5, 2026
37 checks passed
@luxass luxass deleted the feat/rename-schemas-and-improve branch January 5, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approve-breaking-openapi apps: api Changes related to the API. pkg: schemas Changes related to the FS Bridge package. pkg: shared Changes related to the Shared package. pkg: test-utils Changes related to the test-utils package. pkg: ucd-store Changes related to the UCD Store package. pkg: utils Changes related to the Utils package.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants