Skip to content

Commit 1c10362

Browse files
committed
WIP
1 parent 6a91984 commit 1c10362

File tree

15 files changed

+300
-2
lines changed

15 files changed

+300
-2
lines changed

deno.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"./worker",
3939
"./stream-helpers",
4040
"./signals",
41-
"./process"
41+
"./process",
42+
"./inspector"
4243
]
4344
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { type Scope, type Stream, useScope } from "effection";
2+
import { createImplementation } from "../lib/implementation.ts";
3+
import { type ContextNode, type ContextData, protocol } from "./protocol.ts";
4+
5+
export const context = createImplementation(protocol, function* () {
6+
let scope = yield* useScope();
7+
return {
8+
*readContextTree(): Stream<never, ContextNode> {
9+
return {
10+
*next() {
11+
return {
12+
done: true,
13+
value: readTree(scope),
14+
};
15+
},
16+
};
17+
}
18+
};
19+
});
20+
21+
interface V3Frame {
22+
context: Record<string, unknown>;
23+
children: Set<V3Frame>;
24+
}
25+
26+
interface V3Scope {
27+
frame: V3Frame;
28+
}
29+
30+
interface V4Scope {
31+
contexts: Record<string, unknown>;
32+
children: V4Scope[];
33+
}
34+
35+
function readTree(scope: Scope): ContextNode {
36+
if (isV3Scope(scope)) {
37+
return readV3Tree(scope);
38+
} else if (isV4Scope(scope)) {
39+
return readV4Tree(scope);
40+
} else {
41+
throw new TypeError(`unrecognizable scope type`);
42+
}
43+
}
44+
45+
function isV3Scope(value: Scope): value is Scope & V3Scope {
46+
let hypothetical = value as Scope & V3Scope;
47+
return hypothetical.frame && typeof hypothetical.frame.context === "object";
48+
}
49+
50+
function isV4Scope(value: Scope): value is Scope & V4Scope {
51+
let hypothetical = value as Scope & V4Scope;
52+
return typeof hypothetical.contexts === "object";
53+
}
54+
55+
function readV3Tree(scope: V3Scope): ContextNode {
56+
let children = [...scope.frame.children].map((frame) => ({ frame }));
57+
return {
58+
data: readContextData(scope.frame.context),
59+
children: children.map(readV3Tree),
60+
};
61+
}
62+
63+
function readV4Tree(scope: V4Scope): ContextNode {
64+
let children = scope.contexts["@effection/scope.children"] as Set<V4Scope>;
65+
return {
66+
data: readContextData(scope.contexts),
67+
children: [...children].map(readV4Tree),
68+
};
69+
}
70+
71+
// make anything serializable.
72+
function readContextData(contexts: Record<string, unknown>): ContextData {
73+
let entries = Object.entries(contexts).map(([key, value]) => {
74+
try {
75+
return [key, JSON.parse(JSON.stringify(value))];
76+
} catch (_error) {
77+
return [key, "unserializable"];
78+
}
79+
});
80+
return Object.fromEntries(entries);
81+
}

inspector/context/protocol.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { scope } from "arktype";
2+
import { createProtocol } from "../lib/mod.ts";
3+
4+
const schema = scope({
5+
ContextData: {
6+
values: "object.json",
7+
},
8+
ContextNode: {
9+
data: "ContextData",
10+
children: "ContextNode[]",
11+
},
12+
None: "never[]",
13+
}).export();
14+
15+
export type ContextData = typeof schema.ContextData.infer;
16+
17+
export type ContextNode = typeof schema.ContextNode.infer;
18+
19+
export const protocol = createProtocol({
20+
readContextTree: {
21+
args: schema.None,
22+
progress: schema.None,
23+
returns: schema.ContextNode,
24+
}
25+
});
26+
27+

inspector/deno.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "@effectionx/inspector",
3+
"version": "0.0.1",
4+
"exports": "./mod.ts",
5+
"license": "MIT",
6+
"imports": {
7+
"@standard-schema/spec": "npm:@standard-schema/spec@^1.0.0",
8+
"arktype": "npm:arktype@^2.1.27",
9+
"effection": "npm:effection@^3.6.1",
10+
"zod": "npm:zod@^4.1.13"
11+
}
12+
}

inspector/implementation.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./context/implementation.ts";

inspector/lib/combine.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// deno-lint-ignore-file no-explicit-any
2+
import type { Operation } from "effection";
3+
import type { Handle, Inspector, Methods, Protocol } from "./types.ts";
4+
5+
export interface Combine {
6+
protocols<A extends Methods>(protocols: [Protocol<A>]): Protocol<A>;
7+
protocols<A extends Methods, B extends Methods>(
8+
protocols: [Protocol<A>, Protocol<B>],
9+
): Protocol<A & B>;
10+
protocols<A extends Methods, B extends Methods, C extends Methods>(
11+
protocols: [Protocol<A>, Protocol<B>, Protocol<C>],
12+
): Protocol<A & B & C>;
13+
protocols<
14+
A extends Methods,
15+
B extends Methods,
16+
C extends Methods,
17+
D extends Methods,
18+
>(
19+
protocols: [Protocol<A>, Protocol<B>, Protocol<C>, Protocol<D>],
20+
): Protocol<A & B & C & D>;
21+
22+
inspectors<A extends Methods>(inspectors: [Inspector<A>]): Inspector<A>;
23+
inspectors<A extends Methods, B extends Methods>(
24+
inspectors: [Inspector<A>, Inspector<B>],
25+
): Inspector<A & B>;
26+
inspectors<A extends Methods, B extends Methods, C extends Methods>(
27+
inspectors: [Inspector<A>, Inspector<B>, Inspector<C>],
28+
): Inspector<A & B & C>;
29+
inspectors<
30+
A extends Methods,
31+
B extends Methods,
32+
C extends Methods,
33+
D extends Methods,
34+
>(
35+
inspectors: [Inspector<A>, Inspector<B>, Inspector<C>, Inspector<D>],
36+
): Inspector<A & B & C & D>;
37+
}
38+
39+
export const combine: Combine = {
40+
protocols: (...protocols: any[]) => {
41+
return protocols.reduce((acc, protocol) => {
42+
Object.assign(acc.methods, protocol.methods);
43+
return acc;
44+
}, { methods: {} }) as Protocol<Methods>;
45+
},
46+
inspectors: (...inspectors: any[]) => {
47+
return inspectors.reduce(
48+
(acc: Inspector<Methods>, inspector: Inspector<Methods>) => {
49+
let protocol = combine.protocols([acc.protocol, inspector.protocol]);
50+
let attach = function* (): Operation<Handle<Methods>> {
51+
let a = yield* acc.attach();
52+
let b = yield* inspector.attach();
53+
let methods = Object.assign(a.methods, b.methods);
54+
return {
55+
protocol,
56+
methods,
57+
invoke: ({ name, args }) => methods[name](...args),
58+
};
59+
};
60+
return { protocol, attach };
61+
},
62+
);
63+
},
64+
};

inspector/lib/impl.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { lift, type Operation, type Stream } from "effection";
2+
3+
export function fn<TArgs extends unknown[], TReturn>(
4+
fn: (...args: TArgs) => TReturn,
5+
): (...args: TArgs) => Stream<never, TReturn> {
6+
return lift((...args) => ({
7+
*next() {
8+
return { done: true, value: fn(...args) };
9+
},
10+
}));
11+
}
12+
13+
export function op<TArgs extends unknown[], TReturn>(
14+
fn: (...args: TArgs) => Operation<TReturn>,
15+
): (...args: TArgs) => Stream<never, TReturn> {
16+
return lift((...args) => ({
17+
*next() {
18+
return {
19+
done: true,
20+
value: yield* fn(...args),
21+
};
22+
},
23+
}));
24+
}

inspector/lib/implementation.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type {
2+
Implementation,
3+
Inspector,
4+
Methods,
5+
Protocol,
6+
} from "./types.ts";
7+
8+
export function createImplementation<M extends Methods>(
9+
protocol: Protocol<M>,
10+
create: Implementation<M>,
11+
): Inspector<M> {
12+
return {
13+
protocol,
14+
*attach() {
15+
let methods = yield* create();
16+
return {
17+
protocol,
18+
methods,
19+
invoke: ({ name, args }) => methods[name](...args),
20+
};
21+
},
22+
};
23+
}

inspector/lib/inspector.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

inspector/lib/mod.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./types.ts";
2+
export * from "./protocol.ts";

0 commit comments

Comments
 (0)