Skip to content

fix: include * where predicate#2858

Merged
davydkov merged 6 commits into
mainfrom
fix-wildcard-predicate
Apr 8, 2026
Merged

fix: include * where predicate#2858
davydkov merged 6 commits into
mainfrom
fix-wildcard-predicate

Conversation

@davydkov

@davydkov davydkov commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fix predicate evaluation for wildcard expressions with where.
Previously, include * where was applying filter to the root elements (or children inside scoped view).
Now it applies the filter to all elements, to match the wildcard semantics.

Fixes #2837

@changeset-bot

changeset-bot Bot commented Apr 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 75e306a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@likec4/core Patch
@likec4/playground Patch
@likec4/config Patch
@likec4/diagram Patch
@likec4/generators Patch
@likec4/language-server Patch
@likec4/language-services Patch
@likec4/layouts Patch
@likec4/leanix-bridge Patch
likec4 Patch
@likec4/mcp Patch
@likec4/react Patch
@likec4/vite-plugin Patch
@likec4/vscode-preview Patch
likec4-vscode Patch
@likec4/docs-astro Patch
@likec4/lsp Patch
@likec4/style-preset Patch
@likec4/styles Patch
@likec4/log Patch
@likec4/tsconfig Patch

Not sure what this means? Click here to learn what changesets are.

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

@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 82e2f4ce-b5ae-4d2e-b199-51966f89d98c

📥 Commits

Reviewing files that changed from the base of the PR and between 6d88f88 and 75e306a.

📒 Files selected for processing (3)
  • devops/vitest.ts
  • packages/core/src/compute-view/deployment-view/predicates/utils.ts
  • vitest.config.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • vitest.config.ts
  • packages/core/src/compute-view/deployment-view/predicates/utils.ts
  • devops/vitest.ts

📝 Walkthrough

Walkthrough

Fixes wildcard predicate evaluation so include * where applies the where filter across all model elements rather than only roots/scoped children; also updates predicate utilities/types, tests, and lint/test configs, and records a changeset for the fix (references issue #2837).

Changes

Cohort / File(s) Summary
Changeset & Workspace Catalog
\.changeset/fix-wildcard-predicate.md, pnpm-workspace.yaml
Added a patch changeset documenting the wildcard predicate fix. Bumped several catalog package versions (oxlint, oxlint-tsgolint, turbo) and reordered an esbuild catalog entry.
Linting & OXLint Config / package scripts
\.oxlintrc\.json, package\.json
Enabled type-aware option in .oxlintrc.json. Removed --type-aware from npm lint scripts, added lint:errors-only script, and adjusted CI lint flags.
Vitest / Test Config
devops/vitest.ts, vitest.config.ts
Removed custom pathe-based alias/resolve logic and cacheDir override; replaced with ssr.resolve.conditions: ['sources'] in shared and root configs and removed snapshot escaping/isolate/maxConcurrency overrides.
TypeScript Project Config
packages/config/scripts/tsconfig.json
Added a TypeScript project references entry pointing to ../tsconfig.json.
Builder Types
packages/core/src/builder/_types.ts
Removed conditional IfNever from tags props; tags now consistently typed as [Tag, ...Tag[]] across element/node/view/relation prop types.
Predicate Utilities
packages/core/src/compute-view/deployment-view/predicates/utils.ts, packages/core/src/compute-view/deployment-view/predicates/deploymentRefs-where.ts
Added explicit overloads for predicateToPatch (include/exclude) and changed applyElementPredicate to return mutable arrays. Wrapped predicateToPatch results with nonNullable() in deployment ref predicate executor to avoid forced type assertions.
Wildcard Predicate Logic (deployment & element views)
packages/core/src/compute-view/deployment-view/predicates/wildcard.ts, packages/core/src/compute-view/element-view/predicates/wildcard.ts
Changed wildcard include behavior: when where present, derive roots from model.elements() filtered by where (not only model.roots()); adjusted child/orphan handling and connection construction to ensure filters apply to descendants and connections are created/connected appropriately.
Tests & Test Helpers
packages/core/src/compute-view/deployment-view/predicates/__test__/wildcard.filter.spec.ts, packages/core/src/compute-view/element-view/predicates/__test__/wildcard.spec.ts, packages/core/src/compute-view/element-view/__test__/wildcard-expr.spec.ts, packages/core/src/compute-view/element-view/__test__/TestHelper.ts
Updated fixtures and expectations to reflect corrected wildcard where semantics (new tags, node/edge expectations, and scoped tests). Added toHaveNoConnections() matcher to test helper assertions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • chore: shared vitest conf #2751: Modifies shared Vitest configuration and test setup patterns—closely related to the Vitest/shared test config changes in this PR.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: fixing the include * where predicate behavior for wildcard expressions.
Description check ✅ Passed The PR description explains the fix and references the linked issue #2837, though it does not follow the provided template checklist.
Linked Issues check ✅ Passed The changes comprehensively address issue #2837 by modifying wildcard predicate logic to apply filters to all elements rather than just root elements, matching documented wildcard semantics.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the wildcard predicate evaluation. The supporting changes to oxlint config, vitest config, and dependency versions are reasonable infrastructure updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-wildcard-predicate

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/core/src/compute-view/deployment-view/predicates/utils.ts (1)

205-217: ⚠️ Potential issue | 🔴 Critical

Remove cast and align implementation return type with overload promise.

The overload at line 205 advertises (data: readonly E[]) => E[], but the implementation at line 214 returns ((data: readonly E[]) => readonly E[]) with a cast. Line 217 uses as readonly E[], which violates the "avoid as casts" guideline. Implement the promised mutable return directly:

Suggested fix
 ):
   | boolean
   | readonly E[]
-  | ((data: readonly E[]) => readonly E[])
+  | ((data: readonly E[]) => E[])
 {
   if (args.length === 1) {
-    return x => applyElementPredicate(x, args[0]) as readonly E[]
+    const where = args[0]
+    return (x: readonly E[]) => x.filter(el => applyElementPredicate(el, where))
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/compute-view/deployment-view/predicates/utils.ts` around
lines 205 - 217, The overload promises a mutable "(data: readonly E[]) => E[]"
but the implementation returns a readonly array with an "as" cast; in
applyElementPredicate change the args.length === 1 branch to return a function
that converts the result into a mutable array instead of casting (e.g. return x
=> Array.from(applyElementPredicate(x, args[0])) ), so the returned type is E[]
without using "as" casts and aligns with the declared overload for
applyElementPredicate.
🧹 Nitpick comments (4)
packages/core/src/builder/_types.ts (1)

69-69: Extract and reuse a shared tags type alias across exported props.

The same tags?: [Tag, ...Tag[]] shape is duplicated in four exported prop types. Please centralize it into a single alias to avoid drift and keep the API surface easier to maintain.

Proposed refactor
+type TagsProp<Tag> = [Tag, ...Tag[]]

 export type NewElementProps<Tag, Metadata> = {
   title?: string
   summary?: MarkdownOrString | string
   description?: MarkdownOrString | string
   technology?: string
-  tags?: [Tag, ...Tag[]]
+  tags?: TagsProp<Tag>
   metadata?: Metadata
   icon?: string
   ...
 }

 export type NewDeploymentNodeProps<Tag, Metadata> = {
   title?: string
   summary?: MarkdownOrString | string
   description?: MarkdownOrString | string
   technology?: string
-  tags?: [Tag, ...Tag[]]
+  tags?: TagsProp<Tag>
   metadata?: Metadata
   ...
 }

 export type NewViewProps<Tag> = {
   title?: string
   description?: MarkdownOrString | string
-  tags?: [Tag, ...Tag[]]
+  tags?: TagsProp<Tag>
   links?: Array<string | { title?: string; url: string }>
 }

 export type NewRelationProps<Kind, Tag, Metadata> = {
   kind?: Kind
   title?: string
   description?: MarkdownOrString | string
   technology?: string
   notes?: MarkdownOrString | string
-  tags?: [Tag, ...Tag[]]
+  tags?: TagsProp<Tag>
   metadata?: Metadata
   ...
 }

As per coding guidelines, "Agent types and interfaces should be defined separately and reused across the codebase".

Also applies to: 94-94, 117-117, 127-127

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/builder/_types.ts` at line 69, Create a shared exported
type alias like `Tags = [Tag, ...Tag[]]` and replace the duplicated inline
`tags?: [Tag, ...Tag[]]` occurrences in the four exported prop types with
`tags?: Tags`; update the four prop type declarations that currently use the
inline tuple to reference `Tags` instead, and export the new `Tags` alias so
other modules can reuse it (ensure the alias is declared near the other type
definitions in _types.ts and run type checks to confirm no breaking changes).
packages/core/src/compute-view/element-view/predicates/__test__/wildcard.spec.ts (2)

74-114: Add an imported-element where regression.

The changed unscoped include * where path now walks model.elements() and splits imported vs. project elements, but this spec still covers imports only for bare *. A tagged imported descendant would exercise different logic, so it’s worth pinning with a dedicated case.

Based on learnings, "Applies to **/*.spec.ts : Aim to cover new features with relevant tests; keep test names descriptive".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/core/src/compute-view/element-view/predicates/__test__/wildcard.spec.ts`
around lines 74 - 114, The test suite lacks a case for an imported-element
matched by an unscoped include '*' with a where clause; add a new spec similar
to the existing "include * where" that uses TestHelper.from(builder.clone()) and
t.processPredicates($rules($include('*', { where: 'tag is `#ui`' }))) but targets
an imported descendant (e.g., an imported element with a tag) to exercise the
split logic in the unscoped include implementation; ensure the new test asserts
the expected elements and connections via t.expect(...).toHaveElements(...) and
t.expect(...).toHaveNoConnections() and give it a descriptive name like "include
* where imported element".

159-175: Rename the no matches case.

There is still a #mobile descendant under cloud, so the current title reads like a data contradiction. Calling out “no matching direct children” or the fallback behavior would make failures easier to interpret.

Based on learnings, "Applies to **/*.spec.ts : Aim to cover new features with relevant tests; keep test names descriptive".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/core/src/compute-view/element-view/predicates/__test__/wildcard.spec.ts`
around lines 159 - 175, Rename the test case description to accurately reflect
that there are no matching direct children under 'cloud' rather than no matches
at all; update the it(...) string currently reading "include * in cloud where
tag is `#mobile` (no matches)" to something like "include * in cloud where tag is
`#mobile` (no matching direct children; matches descendants/fallback)" so the
behavior exercised by TestHelper.from(builder.clone()),
processPredicatesWithScope('cloud', $include('*', { where: 'tag is `#mobile`' }))
and the subsequent expectations (t.expect(...).toHaveElements /
toHaveConnections) is clearly documented.
packages/core/src/compute-view/deployment-view/predicates/__test__/wildcard.filter.spec.ts (1)

85-93: Also assert edges for kind is nd.

This case exercises the new root-only where connection path, but it currently locks in nodes only. Adding the expected edges would protect the behavioral change in WildcardPredicate.include, not just the selection set.

Based on learnings, "Applies to **/*.spec.ts : Aim to cover new features with relevant tests; keep test names descriptive".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/core/src/compute-view/deployment-view/predicates/__test__/wildcard.filter.spec.ts`
around lines 85 - 93, The test currently asserts only nodes for the
$include('*', { where: 'kind is nd' }) case via
t.expectComputedView(...).toHaveNodes(...); add a complementary assertion that
checks the edges produced by this root-only where connection path by calling
t.expectComputedView($include('*', { where: 'kind is nd' })).toHaveEdges(...)
and list the expected connections (e.g. edges showing prod->prod.infra,
prod->prod.z1 and root-level connections to customer and global) so the spec for
WildcardPredicate.include verifies both the selection set and the resulting
edges.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@devops/vitest.ts`:
- Around line 10-14: The ssr.resolve.conditions setting is placed under ssr and
thus only affects SSR mode; move the array from ssr.resolve.conditions into the
top-level resolve.conditions in the shared defineVitest() config so module
resolution applies to all test runs (e.g., change the config to use resolve: {
conditions: ['sources'], ... } and remove the nested ssr.resolve.conditions
entry).

---

Outside diff comments:
In `@packages/core/src/compute-view/deployment-view/predicates/utils.ts`:
- Around line 205-217: The overload promises a mutable "(data: readonly E[]) =>
E[]" but the implementation returns a readonly array with an "as" cast; in
applyElementPredicate change the args.length === 1 branch to return a function
that converts the result into a mutable array instead of casting (e.g. return x
=> Array.from(applyElementPredicate(x, args[0])) ), so the returned type is E[]
without using "as" casts and aligns with the declared overload for
applyElementPredicate.

---

Nitpick comments:
In `@packages/core/src/builder/_types.ts`:
- Line 69: Create a shared exported type alias like `Tags = [Tag, ...Tag[]]` and
replace the duplicated inline `tags?: [Tag, ...Tag[]]` occurrences in the four
exported prop types with `tags?: Tags`; update the four prop type declarations
that currently use the inline tuple to reference `Tags` instead, and export the
new `Tags` alias so other modules can reuse it (ensure the alias is declared
near the other type definitions in _types.ts and run type checks to confirm no
breaking changes).

In
`@packages/core/src/compute-view/deployment-view/predicates/__test__/wildcard.filter.spec.ts`:
- Around line 85-93: The test currently asserts only nodes for the $include('*',
{ where: 'kind is nd' }) case via t.expectComputedView(...).toHaveNodes(...);
add a complementary assertion that checks the edges produced by this root-only
where connection path by calling t.expectComputedView($include('*', { where:
'kind is nd' })).toHaveEdges(...) and list the expected connections (e.g. edges
showing prod->prod.infra, prod->prod.z1 and root-level connections to customer
and global) so the spec for WildcardPredicate.include verifies both the
selection set and the resulting edges.

In
`@packages/core/src/compute-view/element-view/predicates/__test__/wildcard.spec.ts`:
- Around line 74-114: The test suite lacks a case for an imported-element
matched by an unscoped include '*' with a where clause; add a new spec similar
to the existing "include * where" that uses TestHelper.from(builder.clone()) and
t.processPredicates($rules($include('*', { where: 'tag is `#ui`' }))) but targets
an imported descendant (e.g., an imported element with a tag) to exercise the
split logic in the unscoped include implementation; ensure the new test asserts
the expected elements and connections via t.expect(...).toHaveElements(...) and
t.expect(...).toHaveNoConnections() and give it a descriptive name like "include
* where imported element".
- Around line 159-175: Rename the test case description to accurately reflect
that there are no matching direct children under 'cloud' rather than no matches
at all; update the it(...) string currently reading "include * in cloud where
tag is `#mobile` (no matches)" to something like "include * in cloud where tag is
`#mobile` (no matching direct children; matches descendants/fallback)" so the
behavior exercised by TestHelper.from(builder.clone()),
processPredicatesWithScope('cloud', $include('*', { where: 'tag is `#mobile`' }))
and the subsequent expectations (t.expect(...).toHaveElements /
toHaveConnections) is clearly documented.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6cac8767-6e92-4b60-bf7d-f0eac321f8f4

📥 Commits

Reviewing files that changed from the base of the PR and between 9309d3a and 6d88f88.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • .changeset/fix-wildcard-predicate.md
  • .oxlintrc.json
  • devops/vitest.ts
  • package.json
  • packages/config/scripts/tsconfig.json
  • packages/core/src/builder/_types.ts
  • packages/core/src/compute-view/deployment-view/predicates/__test__/wildcard.filter.spec.ts
  • packages/core/src/compute-view/deployment-view/predicates/deploymentRefs-where.ts
  • packages/core/src/compute-view/deployment-view/predicates/utils.ts
  • packages/core/src/compute-view/deployment-view/predicates/wildcard.ts
  • packages/core/src/compute-view/element-view/__test__/TestHelper.ts
  • packages/core/src/compute-view/element-view/__test__/wildcard-expr.spec.ts
  • packages/core/src/compute-view/element-view/predicates/__test__/wildcard.spec.ts
  • packages/core/src/compute-view/element-view/predicates/wildcard.ts
  • pnpm-workspace.yaml
  • vitest.config.ts
💤 Files with no reviewable changes (1)
  • vitest.config.ts

Comment thread devops/vitest.ts
@davydkov davydkov merged commit c0048b6 into main Apr 8, 2026
11 of 12 checks passed
@davydkov davydkov deleted the fix-wildcard-predicate branch April 8, 2026 12:41
@likec4-ci likec4-ci Bot mentioned this pull request Apr 8, 2026
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.

[deployment views] Include by tag does not seems to work

1 participant