Skip to content

F/cli optimization#1107

Open
fernando-aviles wants to merge 7 commits intomainfrom
f/cli-optimization
Open

F/cli optimization#1107
fernando-aviles wants to merge 7 commits intomainfrom
f/cli-optimization

Conversation

@fernando-aviles
Copy link
Contributor

@fernando-aviles fernando-aviles commented Mar 13, 2026

Greptile Summary

This PR delivers three performance optimisations and one bug fix for the CLI's composite JSON merge pipeline:

  • Fast-path flatten (flattenJson.ts): A new tryFastFlatten helper handles simple $.* and $.*.prop JSONPath patterns with a direct Object.keys iteration instead of invoking jsonpath-plus, producing identical RFC 6901 JSON Pointers (with correct ~0/~1 escaping) and correctly falling back to the full JSONPath engine for anything more complex.
  • Pre-parse translated content (mergeJson.ts): JSON.parse(target.translatedContent) was previously called inside nested loops over every sourceObjectPointer. It is now called once per target up-front, eliminating redundant parsing.
  • O(n) sort (mergeJson.ts): The sortByLocaleOrder 'locales' mode replaced an O(n²) splice loop with a Map-based grouping strategy. This is correct for the common case, but introduces a subtle ordering difference for edge cases (see inline comment).
  • Primitive source item fix (mergeJson.ts): A new isPrimitiveSourceItem guard correctly short-circuits the JSONPointer mutation path for locale objects whose value is a primitive (string/number/boolean/null), assigning the translated value directly. Previously, spreading a primitive into the mergedItems object would silently corrupt the result.

Confidence Score: 4/5

  • Safe to merge with low risk; one minor behavioural edge case in experimental sort ordering should be verified.
  • The optimisations are straightforward and the fast-path logic is provably equivalent to JSONPath for the patterns it covers. The primitive source item fix addresses a real bug. The only concern is the subtle reordering of locale-less items vs. unrecognised-locale items in the experimental sortByLocaleOrder refactor, which may differ from the old behaviour in edge cases but is unlikely to affect production workloads given its experimental status.
  • packages/cli/src/formats/json/mergeJson.ts — specifically the sortByLocaleOrder refactor around lines 503-509.

Important Files Changed

Filename Overview
packages/cli/src/formats/json/flattenJson.ts Adds a O(n) fast path (tryFastFlatten) for simple $.* and $.*.prop patterns, correctly generating RFC 6901 JSON Pointers (with ~0/~1 escaping) and falling back to jsonpath-plus for any pattern it cannot handle. Logic is functionally equivalent to the JSONPath slow path for the patterns it covers.
packages/cli/src/formats/json/mergeJson.ts Two optimizations (pre-parse target JSON once; O(n) Map-based sort) plus a new isPrimitiveSourceItem branch that fixes handling of primitive locale values. The sort refactor has a minor behavioural difference: items without a localeValue are now always ordered after items with unrecognised locales, whereas previously they were interleaved in original order.
packages/cli/src/generated/version.ts Auto-generated version bump from 2.10.0 to 2.10.1 — no issues.
.changeset/late-mugs-marry.md New changeset entry for the CLI optimisation patch — correct and complete.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[flattenJson called with jsonPath] --> B{tryFastFlatten matches simple wildcard?}
    B -- Yes --> C[Object.keys iteration and RFC 6901 pointer generation]
    C --> D{Any matches found?}
    D -- Yes --> E[Return result map]
    D -- No --> F[Return empty map]
    B -- No --> G[jsonpath-plus full engine]
    G --> H[Return pointer to value map]
    E --> I[Object.assign into extractedJson]
    F --> I
    H --> I

    subgraph mergeJson composite path
    J[Parse originalContent] --> K[structuredClone into mergedJson]
    K --> L[Pre-parse ALL targets ONCE into parsedTargets]
    L --> M[generateSourceObjectPointers via flattenJson]
    M --> N{sourceObjectOptions type?}
    N -- array --> O[Loop parsedTargets and build itemsToAdd and indiciesToRemove]
    N -- object --> P{isPrimitiveSourceItem?}
    P -- Yes --> Q[Assign translatedValue directly from targetItems root or first value]
    P -- No --> R[structuredClone and JSONPointer mutations]
    Q --> S[JSONPointer.set into mergedJson]
    R --> S
    O --> T[sortByLocaleOrder using Map grouping]
    T --> S
    end
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: packages/cli/src/formats/json/mergeJson.ts
Line: 503-509

Comment:
**Ordering of ungrouped items changed vs. original behaviour**

Before this refactor, `remainingItems` held all items that did NOT match any `localeOrderValues` entry — including items with an unrecognised `localeValue` **and** items whose `localeValue` was `undefined`/`null` — and they were appended in their **original relative order**.

The new Map-based implementation separates these two categories:
1. Items with an unrecognised locale are grouped in `localeGroups` and flushed first (lines 503-507).
2. Items with a falsy `localeValue` are in `ungrouped` and always appended last (line 509).

This means if the original array had, for example, `[{localeValue: undefined}, {localeValue: "zh"}]` where `"zh"` is not in `localeOrderValues`, the old code would produce `[…, {undefined}, {zh}]` while the new code produces `[…, {zh}, {undefined}]`. The relative position of locale-less items and unrecognised-locale items is now reversed compared to the original ordering.

Although this path is gated behind `experimentalSort: 'locales'` and is an edge case, the reordering is silently different from the old behaviour and could surprise users who have both locale-less items and extra-locale items in their composite JSON arrays.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: ad020d5

Greptile also left 1 inline comment on this PR.

@fernando-aviles fernando-aviles requested a review from a team as a code owner March 13, 2026 22:19
Comment on lines +503 to 509
for (const [localeValue, group] of localeGroups) {
if (!localeOrderValues.includes(localeValue)) {
orderedItems.push(...group);
}
}
orderedItems.push(...ungrouped);

Copy link
Contributor

Choose a reason for hiding this comment

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

Ordering of ungrouped items changed vs. original behaviour

Before this refactor, remainingItems held all items that did NOT match any localeOrderValues entry — including items with an unrecognised localeValue and items whose localeValue was undefined/null — and they were appended in their original relative order.

The new Map-based implementation separates these two categories:

  1. Items with an unrecognised locale are grouped in localeGroups and flushed first (lines 503-507).
  2. Items with a falsy localeValue are in ungrouped and always appended last (line 509).

This means if the original array had, for example, [{localeValue: undefined}, {localeValue: "zh"}] where "zh" is not in localeOrderValues, the old code would produce […, {undefined}, {zh}] while the new code produces […, {zh}, {undefined}]. The relative position of locale-less items and unrecognised-locale items is now reversed compared to the original ordering.

Although this path is gated behind experimentalSort: 'locales' and is an edge case, the reordering is silently different from the old behaviour and could surprise users who have both locale-less items and extra-locale items in their composite JSON arrays.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/cli/src/formats/json/mergeJson.ts
Line: 503-509

Comment:
**Ordering of ungrouped items changed vs. original behaviour**

Before this refactor, `remainingItems` held all items that did NOT match any `localeOrderValues` entry — including items with an unrecognised `localeValue` **and** items whose `localeValue` was `undefined`/`null` — and they were appended in their **original relative order**.

The new Map-based implementation separates these two categories:
1. Items with an unrecognised locale are grouped in `localeGroups` and flushed first (lines 503-507).
2. Items with a falsy `localeValue` are in `ungrouped` and always appended last (line 509).

This means if the original array had, for example, `[{localeValue: undefined}, {localeValue: "zh"}]` where `"zh"` is not in `localeOrderValues`, the old code would produce `[…, {undefined}, {zh}]` while the new code produces `[…, {zh}, {undefined}]`. The relative position of locale-less items and unrecognised-locale items is now reversed compared to the original ordering.

Although this path is gated behind `experimentalSort: 'locales'` and is an edge case, the reordering is silently different from the old behaviour and could surprise users who have both locale-less items and extra-locale items in their composite JSON arrays.

How can I resolve this? If you propose a fix, please make it concise.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants