Skip to content

Commit 74908d8

Browse files
committed
feat: add block visibility override
1 parent 9dcf96b commit 74908d8

File tree

8 files changed

+44
-31
lines changed

8 files changed

+44
-31
lines changed

blocks/action.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ const actionBlock: Block<ActionModule> = {
2121
TProps = any,
2222
>(
2323
mod: ActionModule<TProps>,
24+
key: string,
2425
) => [
25-
applyProps(gateKeeper(mod)),
26+
gateKeeper(mod.defaultVisibility, key),
27+
applyProps(mod),
2628
],
2729
defaultPreview: (result) => {
2830
return {

blocks/loader.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,13 +334,12 @@ const wrapLoader = (
334334
const loaderBlock: Block<LoaderModule> = {
335335
type: "loaders",
336336
introspect: { includeReturn: true },
337-
adapt: <TProps = any>(mod: LoaderModule<TProps>) => [
337+
adapt: <TProps = any>(mod: LoaderModule<TProps>, key: string) => [
338+
gateKeeper(mod.defaultVisibility, key),
338339
wrapCaughtErrors,
339340
(props: TProps, ctx: HttpContext<{ global: any } & RequestState>) =>
340341
applyProps(
341-
gateKeeper(
342-
wrapLoader(mod, ctx.resolveChain, ctx.context.state.release),
343-
),
342+
wrapLoader(mod, ctx.resolveChain, ctx.context.state.release),
344343
)(
345344
props,
346345
ctx,

blocks/utils.tsx

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import type { StatusCode as Status } from "@std/http/status";
66
import type { JSX } from "preact";
77
import type { AppManifest, ImportMap } from "../blocks/app.ts";
8-
import { isInvokeCtx, LoaderModule } from "../blocks/loader.ts";
8+
import { isInvokeCtx } from "../blocks/loader.ts";
99
import type { InvocationFunc } from "../clients/withManifest.ts";
1010
import { withSection } from "../components/section.tsx";
1111
import type {
@@ -27,6 +27,7 @@ import type { InvocationProxy } from "../utils/invoke.types.ts";
2727
import { type Device, deviceOf, isBot as isUABot } from "../utils/userAgent.ts";
2828
import type { HttpContext } from "./handler.ts";
2929
import type { Vary } from "../utils/vary.ts";
30+
import { Context } from "../mod.ts";
3031

3132
export interface GateKeeperAccess {
3233
defaultVisibility?: "private" | "public";
@@ -254,26 +255,22 @@ export const buildImportMap = (manifest: AppManifest): ImportMap => {
254255
return buildImportMapWith(manifest, builder);
255256
};
256257

257-
export const gateKeeper = (
258-
{
259-
default: handler,
260-
defaultVisibility = "public",
261-
...rest
262-
}: BlockModule & GateKeeperAccess,
263-
) => {
264-
return {
265-
...rest,
266-
default: async (
267-
props: Parameters<typeof handler>[0],
268-
req: Request,
269-
ctx: FnContext<unknown, any>,
270-
): Promise<ReturnType<typeof handler>> => {
271-
if (defaultVisibility === "private" && !ctx.isInvoke) {
272-
return new Response(null, {
273-
status: 403,
274-
});
275-
}
276-
return await handler(props, req, ctx);
277-
},
258+
export const gateKeeper =
259+
(defaultVisibility: GateKeeperAccess["defaultVisibility"], key: string) =>
260+
<
261+
TContext extends ResolverMiddlewareContext<any> = ResolverMiddlewareContext<
262+
any
263+
>,
264+
>(_props: unknown, ctx: TContext) => {
265+
const currentContext = Context.active();
266+
267+
const visibility = currentContext.visibilityOverrides?.[key] ??
268+
defaultVisibility ?? "public";
269+
270+
if (visibility === "private" && !isInvokeCtx(ctx)) {
271+
return new Response(null, {
272+
status: 403,
273+
});
274+
}
275+
return ctx.next!();
278276
};
279-
};

deco.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import type { ReleaseResolver } from "./engine/core/mod.ts";
66
import type { DecofileProvider } from "./engine/decofile/provider.ts";
77
import type { AppManifest } from "./types.ts";
88
import { randId } from "./utils/rand.ts";
9+
import { BlockKeys } from "./mod.ts";
10+
import { GateKeeperAccess } from "./blocks/utils.tsx";
911

1012
export interface DecoRuntimeState<
1113
TAppManifest extends AppManifest = AppManifest,
@@ -55,6 +57,12 @@ export interface DecoContext<TAppManifest extends AppManifest = AppManifest> {
5557
runtime?: Promise<DecoRuntimeState<TAppManifest>>;
5658
instance: InstanceInfo;
5759
request?: RequestContext;
60+
61+
visibilityOverrides?: Record<
62+
BlockKeys<TAppManifest> extends undefined ? string
63+
: BlockKeys<TAppManifest>,
64+
GateKeeperAccess["defaultVisibility"]
65+
>;
5866
}
5967

6068
export interface RequestContextBinder {
@@ -107,7 +115,7 @@ export const Context = {
107115
// Function to retrieve the active context
108116
active: <T extends AppManifest = AppManifest>(): DecoContext<T> => {
109117
// Retrieve the context associated with the async ID
110-
return asyncLocalStorage.getStore() ?? defaultContext;
118+
return asyncLocalStorage.getStore() as DecoContext<T> ?? defaultContext;
111119
},
112120
bind: <R, TArgs extends unknown[]>(
113121
ctx: DecoContext,

engine/block.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export type InstanceOf<
117117
export type BlockTypes<TManifest extends AppManifest = AppManifest> =
118118
keyof Omit<
119119
TManifest,
120-
"config" | "baseUrl"
120+
"config" | "baseUrl" | "name"
121121
>;
122122

123123
export type BlockKeys<TManifest extends AppManifest = AppManifest> = {

engine/manifest/manifest.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ export const newContext = <
409409
instanceId: string | undefined = undefined,
410410
site: string | undefined = undefined,
411411
namespace: string = "site",
412+
visibilityOverrides?: DecoContext<T>["visibilityOverrides"],
412413
): Promise<DecoContext<T>> => {
413414
const currentContext = Context.active<T>();
414415
const ctx: DecoContext<T> = {
@@ -419,6 +420,7 @@ export const newContext = <
419420
id: instanceId ?? randId(),
420421
startedAt: new Date(),
421422
},
423+
visibilityOverrides,
422424
};
423425

424426
return fulfillContext(ctx, m, currentImportMap, release);

runtime/fresh/plugin.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// TODO make fresh plugin use @deco/deco from JSR. so that we can use the same code for both
22

3-
import type { AppManifest, SiteInfo } from "@deco/deco";
3+
import type { AppManifest, DecoContext, SiteInfo } from "@deco/deco";
44
import { Deco, type PageData, type PageParams } from "@deco/deco";
55
import { framework as htmxFramework } from "@deco/deco/htmx";
66
import type { ComponentType } from "preact";
@@ -51,6 +51,7 @@ export interface InitOptions<TManifest extends AppManifest = AppManifest> {
5151
site?: SiteInfo;
5252
deco?: Deco<TManifest>;
5353
middlewares?: PluginMiddleware[];
54+
visibilityOverrides?: DecoContext<TManifest>["visibilityOverrides"];
5455
}
5556

5657
export type Options<TManifest extends AppManifest = AppManifest> =
@@ -89,6 +90,7 @@ export default function decoPlugin<TManifest extends AppManifest = AppManifest>(
8990
site: opt?.site?.name,
9091
namespace: opt?.site?.namespace,
9192
bindings: { framework: opt?.htmx ? htmxFramework : framework },
93+
visibilityOverrides: opt.visibilityOverrides,
9294
});
9395

9496
const catchAll: PluginRoute = {

runtime/mod.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ export interface DecoOptions<TAppManifest extends AppManifest = AppManifest> {
5757
manifest?: TAppManifest;
5858
decofile?: DecofileProvider;
5959
bindings?: Bindings<TAppManifest>;
60+
61+
visibilityOverrides?: DecoContext<TAppManifest>["visibilityOverrides"];
6062
}
6163

6264
const NOOP_CALL = () => {};
@@ -86,6 +88,7 @@ export class Deco<TAppManifest extends AppManifest = AppManifest> {
8688
crypto.randomUUID(),
8789
site,
8890
opts?.namespace,
91+
opts?.visibilityOverrides,
8992
)
9093
);
9194
Context.setDefault(decoContext);

0 commit comments

Comments
 (0)