Skip to content

Commit f935cd5

Browse files
committed
Hide the task handle's phantom context-data marker
The __contextData phantom field binds a TaskDefinition handle to its federation's context data type, but as a string-keyed property it leaked into user-facing docs and IDE completions despite its @internal tag. Replace it with a module-private unique symbol key: no value exists at runtime, the marker disappears from completions, and cross-federation handle rejection still type-checks, now guarded by a regression test. Also replace the tasks barrel's wildcard re-export of task.ts with explicit named exports of the six types its consumers actually use, so nothing new falls through the barrel unnoticed. #803 (comment) Assisted-by: Claude Code:claude-fable-5
1 parent 29a5dcb commit f935cd5

3 files changed

Lines changed: 24 additions & 2 deletions

File tree

packages/fedify/src/federation/tasks/mod.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@
77
* @module
88
*/
99
export { default as TaskCodec } from "./codec.ts";
10-
export * from "./task.ts";
10+
export type {
11+
TaskDefinition,
12+
TaskDefinitionInternal,
13+
TaskDefinitionOptions,
14+
TaskEnqueueOptions,
15+
TaskHandler,
16+
TaskRegistry,
17+
} from "./task.ts";

packages/fedify/src/federation/tasks/task.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ export interface TaskDefinitionOptions<
7777
readonly queue?: MessageQueue;
7878
}
7979

80+
/**
81+
* Phantom key binding a {@link TaskDefinition} to its federation's context
82+
* data type. Declared only—no value exists at runtime, and the symbol is
83+
* not exported, so the marker stays out of user-facing completions.
84+
*/
85+
declare const contextDataBrand: unique symbol;
86+
8087
/**
8188
* The handle returned by {@link TaskRegistry.defineTask}. It carries the
8289
* task name and schema so that {@link Context.enqueueTask} can validate the
@@ -101,7 +108,7 @@ export interface TaskDefinition<TContextData, TData> {
101108
/**
102109
* @internal Phantom marker binding the handle to its federation.
103110
*/
104-
readonly __contextData?: TContextData;
111+
readonly [contextDataBrand]?: TContextData;
105112
}
106113

107114
/**

packages/fedify/src/federation/tasks/tasks.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,14 @@ test("task type-level guards", () => {
235235
// @ts-expect-error: a wrong-shaped payload must not type-check.
236236
return ctx.enqueueTask(task, { n: "not a number" });
237237
};
238+
const _crossContextHandleIsACompileError = (
239+
ctx: Context<void>,
240+
task: TaskDefinition<{ tenant: string }, { n: number }>,
241+
) => {
242+
// @ts-expect-error: a handle bound to different context data must not
243+
// type-check.
244+
return ctx.enqueueTask(task, { n: 1 });
245+
};
238246
});
239247

240248
test("Context.enqueueTask() end-to-end", async (t) => {

0 commit comments

Comments
 (0)