Skip to content

Commit 9aee912

Browse files
committed
chore(deps): @casl/ability v7 parity in api + drop @casl/react
Follow-up to #104, which bumped @casl/ability to 7.0.0 in ui only. - api: @casl/ability 6.8.1 -> 7.0.0 (keeps the shared ACL model in parity; api was left on v6 by #104). - ui: drop @casl/react. v7 removed createContextualCan, the only API the UI used from it, and #104 left @casl/react@6 paired with @casl/ability@7 (peer mismatch). Reimplement the small <Can> directly over the existing typed AbilityContext instead of pulling v7's AbilityProvider/useAbility (which would replace the template's deliberate AbilityContext + emptyAbility design and its tests). That makes @casl/react unused, so it's removed. Validated: bun run check (api, ui), ACL suites (api 50, ui 13), ui build; bun install --frozen-lockfile clean in both apps.
1 parent 34fff4a commit 9aee912

5 files changed

Lines changed: 44 additions & 16 deletions

File tree

apps/api/bun.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
},
5252
"dependencies": {
5353
"@anthropic-ai/sdk": "0.98.0",
54-
"@casl/ability": "6.8.1",
54+
"@casl/ability": "7.0.0",
5555
"@elysiajs/cors": "1.4.2",
5656
"@elysiajs/jwt": "1.4.2",
5757
"@elysiajs/swagger": "1.3.1",

apps/ui/bun.lock

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/ui/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
},
6060
"dependencies": {
6161
"@casl/ability": "7.0.0",
62-
"@casl/react": "6.0.0",
6362
"@hookform/resolvers": "5.2.2",
6463
"@sentry/react": "10.53.1",
6564
"@tanstack/react-query": "5.100.14",

apps/ui/src/lib/acl/Can.tsx

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,44 @@
1-
import { createContextualCan } from "@casl/react";
1+
import type { ReactNode } from "react";
22

3-
import { AbilityContext } from "./acl.context";
3+
import type { Action, Subject } from "./acl.types";
4+
import { useCan } from "./useCan";
5+
6+
interface ICanProps {
7+
/** Action to check, e.g. `"manage"`. */
8+
readonly I: Action;
9+
/** Subject to check the action against, e.g. `"Site"`. */
10+
readonly a: Subject;
11+
/** Invert the check — render when the ability *denies* the action. */
12+
readonly not?: boolean;
13+
/** Render children regardless; only meaningful with a render-prop child. */
14+
readonly passThrough?: boolean;
15+
readonly children: ReactNode | ((allowed: boolean) => ReactNode);
16+
}
417

518
/**
619
* Typed `<Can I="manage" a="Site">{children}</Can>` over the active
7-
* membership's ability. Wraps @casl/react's contextual consumer so call
8-
* sites don't have to thread the ability prop themselves.
20+
* membership's ability (read from `<AbilityProvider>` via `useCan`).
21+
*
22+
* Replaces `@casl/react`'s `createContextualCan`, removed in v7. The rest of
23+
* the ACL layer keeps its own typed `AbilityContext` + `emptyAbility` default
24+
* (so a pre-`/me` tree denies everything), so binding `Can` to that context
25+
* here is all that's needed.
926
*
1027
* Render-gating only — the server enforces every action independently.
1128
*/
12-
export const Can = createContextualCan(AbilityContext.Consumer);
29+
export function Can({
30+
I,
31+
a,
32+
not = false,
33+
passThrough = false,
34+
children
35+
}: ICanProps): ReactNode {
36+
const ability = useCan();
37+
const allowed = not ? ability.cannot(I, a) : ability.can(I, a);
38+
39+
if (typeof children === "function") {
40+
return children(allowed);
41+
}
42+
43+
return allowed || passThrough ? children : null;
44+
}

0 commit comments

Comments
 (0)