Skip to content

Commit 6c8df00

Browse files
dahliaclaude
andcommitted
Fix JSR publishing hang for @fedify/testing
Fixed JSR publishing hanging indefinitely at the processing stage by hiding complex type exports from the public API. The JSR type analyzer struggled with complex type dependencies when analyzing MockFederation, TestFederation, TestContext, and SentActivity types. Changes: - MockFederation class is no longer exported from public API - TestFederation, TestContext, SentActivity interfaces are not exported - Updated all tests to use createFederation() factory function - Updated documentation to remove type imports and use type inference - Types are still available through TypeScript type inference This approach minimizes the public API surface that JSR needs to analyze while maintaining full type safety for users. #468 Co-Authored-By: Claude <[email protected]>
1 parent add825a commit 6c8df00

File tree

5 files changed

+28
-38
lines changed

5 files changed

+28
-38
lines changed

CHANGES.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,17 @@ To be released.
1111
### @fedify/testing
1212

1313
- Fixed JSR publishing hanging indefinitely at the *processing* stage by
14-
refactoring the public API to use TypeScript utility types (`Omit`, `Pick`)
15-
instead of direct class exports. The JSR type analyzer struggled with
16-
complex type dependencies when exporting the `MockFederation` class
17-
directly, causing indefinite hangs during the processing stage. [[#468]]
18-
19-
- Added `TestContext<TContextData>` interface that extends `Context` with
20-
testing utilities using `Omit<Context, "clone">` and
21-
`Pick<RequestContext, ...>`. This ensures automatic inheritance of new
22-
methods added to `Context` or `RequestContext` while maintaining JSR
23-
compatibility.
24-
- Added `TestFederation<TContextData>` interface that extends `Federation`
25-
with testing utilities using `Omit<Federation, "createContext">`.
26-
- Added `createFederation()` factory function that returns
27-
`TestFederation<TContextData>` for creating mock federation instances.
28-
- Exported `SentActivity` interface for tracking sent activities.
14+
hiding complex type exports from the public API. The JSR type analyzer
15+
struggled with complex type dependencies when analyzing the `MockFederation`,
16+
`TestFederation`, `TestContext`, and `SentActivity` types, causing indefinite
17+
hangs during the processing stage. [[#468]]
18+
2919
- **Breaking change**: `MockFederation` class is no longer exported from
30-
the public API. Use `createFederation()` instead, which returns a
31-
`TestFederation` instance with the same functionality.
20+
the public API. Use `createFederation()` factory function instead.
21+
- `TestFederation<TContextData>`, `TestContext<TContextData>`, and
22+
`SentActivity` interfaces are no longer exported from the public API,
23+
but their types are still inferred from `createFederation()` return type
24+
and can be used via TypeScript's type inference.
3225

3326
### @fedify/cli
3427

docs/manual/test.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,11 @@ interface that allows you to:
200200
Here's a basic example of using `createFederation()`:
201201

202202
~~~~ typescript twoslash
203-
import { createFederation, type TestFederation } from "@fedify/testing";
203+
import { createFederation } from "@fedify/testing";
204204
import { Create, Note } from "@fedify/fedify/vocab";
205205

206206
// Create a mock federation with context data
207-
const federation: TestFederation<{ userId: string }> = createFederation<{ userId: string }>({
207+
const federation = createFederation<{ userId: string }>({
208208
contextData: { userId: "test-user" }
209209
});
210210

@@ -239,12 +239,12 @@ which provides a mock implementation of the `Context` interface that tracks
239239
sent activities and provides mock implementations of URI generation methods:
240240

241241
~~~~ typescript twoslash
242-
import { createFederation, type TestContext } from "@fedify/testing";
242+
import { createFederation } from "@fedify/testing";
243243
import { Create, Note, Person } from "@fedify/fedify/vocab";
244244

245245
// Create a mock federation and context
246246
const federation = createFederation<{ userId: string }>();
247-
const context: TestContext<{ userId: string }> = federation.createContext(
247+
const context = federation.createContext(
248248
new URL("https://example.com"),
249249
{ userId: "test-user" }
250250
);

packages/testing/src/mock.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import type { InboxContext } from "@fedify/fedify/federation";
22
import { Create, Note, Person } from "@fedify/fedify/vocab";
33
import { assertEquals, assertRejects } from "@std/assert";
44
import { test } from "../../fedify/src/testing/mod.ts";
5-
import { MockFederation } from "./mock.ts";
5+
import { createFederation } from "./mock.ts";
66

77
test("getSentActivities returns sent activities", async () => {
8-
const mockFederation = new MockFederation<void>();
8+
const mockFederation = createFederation<void>();
99
const context = mockFederation.createContext(
1010
new URL("https://example.com"),
1111
undefined,
@@ -36,7 +36,7 @@ test("getSentActivities returns sent activities", async () => {
3636
});
3737

3838
test("reset clears sent activities", async () => {
39-
const mockFederation = new MockFederation<void>();
39+
const mockFederation = createFederation<void>();
4040
const context = mockFederation.createContext(
4141
new URL("https://example.com"),
4242
undefined,
@@ -67,7 +67,7 @@ test("reset clears sent activities", async () => {
6767

6868
test("receiveActivity triggers inbox listeners", async () => {
6969
// Provide contextData through constructor
70-
const mockFederation = new MockFederation<{ test: string }>({
70+
const mockFederation = createFederation<{ test: string }>({
7171
contextData: { test: "data" },
7272
});
7373
let receivedActivity: Create | null = null;
@@ -100,7 +100,7 @@ test("receiveActivity triggers inbox listeners", async () => {
100100
});
101101

102102
test("MockContext tracks sent activities", async () => {
103-
const mockFederation = new MockFederation<void>();
103+
const mockFederation = createFederation<void>();
104104
const mockContext = mockFederation.createContext(
105105
new URL("https://example.com"),
106106
undefined,
@@ -129,7 +129,7 @@ test("MockContext tracks sent activities", async () => {
129129
});
130130

131131
test("MockContext URI methods should work correctly", () => {
132-
const mockFederation = new MockFederation<void>();
132+
const mockFederation = createFederation<void>();
133133
const mockContext = mockFederation.createContext(
134134
new URL("https://example.com"),
135135
undefined,
@@ -167,7 +167,7 @@ test("MockContext URI methods should work correctly", () => {
167167
});
168168

169169
test("MockContext URI methods respect registered paths", () => {
170-
const mockFederation = new MockFederation<void>();
170+
const mockFederation = createFederation<void>();
171171

172172
// Register custom paths with dummy dispatchers
173173
mockFederation.setNodeInfoDispatcher("/.well-known/nodeinfo", () => ({
@@ -257,7 +257,7 @@ test("MockContext URI methods respect registered paths", () => {
257257
});
258258

259259
test("receiveActivity throws error when contextData not initialized", async () => {
260-
const mockFederation = new MockFederation<void>();
260+
const mockFederation = createFederation<void>();
261261

262262
// Set up an inbox listener without initializing contextData
263263
mockFederation
@@ -281,7 +281,7 @@ test("receiveActivity throws error when contextData not initialized", async () =
281281
});
282282

283283
test("MockFederation distinguishes between immediate and queued activities", async () => {
284-
const mockFederation = new MockFederation<void>();
284+
const mockFederation = createFederation<void>();
285285

286286
// Start the queue to enable queued sending
287287
await mockFederation.startQueue(undefined);
@@ -329,7 +329,7 @@ test("MockFederation distinguishes between immediate and queued activities", asy
329329
});
330330

331331
test("MockFederation without queue sends all activities immediately", async () => {
332-
const mockFederation = new MockFederation<void>();
332+
const mockFederation = createFederation<void>();
333333

334334
const context = mockFederation.createContext(
335335
new URL("https://example.com"),

packages/testing/src/mock.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function expandUriTemplate(
6969
* Represents a sent activity with metadata about how it was sent.
7070
* @since 1.8.0
7171
*/
72-
export interface SentActivity {
72+
interface SentActivity {
7373
/** Whether the activity was queued or sent immediately. */
7474
queued: boolean;
7575
/** Which queue was used (if queued). */
@@ -85,7 +85,7 @@ export interface SentActivity {
8585
* Extends the standard Context interface with additional testing utilities.
8686
* @since 1.9.1
8787
*/
88-
export interface TestContext<TContextData>
88+
interface TestContext<TContextData>
8989
extends
9090
Omit<Context<TContextData>, "clone">,
9191
Pick<
@@ -116,7 +116,7 @@ export interface TestContext<TContextData>
116116
* Extends the standard Federation interface with additional testing utilities.
117117
* @since 1.9.1
118118
*/
119-
export interface TestFederation<TContextData>
119+
interface TestFederation<TContextData>
120120
extends Omit<Federation<TContextData>, "createContext"> {
121121
// Test-specific properties
122122
sentActivities: SentActivity[];
@@ -167,7 +167,7 @@ export interface TestFederation<TContextData>
167167
* @template TContextData The context data to pass to the {@link Context}.
168168
* @since 1.8.0
169169
*/
170-
export class MockFederation<TContextData> implements Federation<TContextData> {
170+
class MockFederation<TContextData> implements Federation<TContextData> {
171171
public sentActivities: SentActivity[] = [];
172172
public queueStarted = false;
173173
private activeQueues: Set<"inbox" | "outbox" | "fanout"> = new Set();

packages/testing/src/mod.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,4 @@ export {
2828
createFederation,
2929
createInboxContext,
3030
createRequestContext,
31-
type SentActivity,
32-
type TestContext,
33-
type TestFederation,
3431
} from "./mock.ts";

0 commit comments

Comments
 (0)