import research docs from prior conversation and scattered sources

This commit is contained in:
2026-04-29 15:11:46 +00:00
parent 9915be2ca6
commit b256fc7eb5
9 changed files with 4274 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
# Prior UJSX POC: Source Code Reference
Source: `/workspace/aui/ujsx/` (Deno/JSR package `@ade/ujsx`)
Summary: `/workspace/aui/SUMMARY.md`
## What to Preserve
### Transform Registry (`transform/registry.ts`)
Priority-based transformation with continuation-passing style:
```typescript
interface TransformRule<T, U, A> {
name: string;
match: (node: T) => boolean;
transform: (node: T, ctx: TransformContext<A>, next: TransformFn<T, U, A>) => U;
priority?: number;
}
```
Key pattern: `next` continuation allows recursive child transforms. Rules sorted by priority (higher = first). V2 extends this with `direction` and `schema` fields.
### HostConfig + Reconciler (`host/config.ts`)
React-reconciler-inspired host adapter:
```typescript
interface HostConfig<TTag, Instance, RootCtx> {
name: string;
createRootContext(container, options?): RootCtx;
createInstance(tag, props, ctx, parent?): Instance;
createTextInstance(text, ctx, parent?): Instance;
appendChild(parent, child, ctx): void;
insertBefore?(parent, child, before, ctx): void;
removeChild?(parent, child, ctx): void;
prepareUpdate?(instance, tag, prevProps, nextProps, ctx): unknown | null;
commitUpdate?(instance, payload, tag, prevProps, nextProps, ctx): void;
}
```
The `createRoot()` reconciler is mount-only (MVP). V2 needs full reconciliation with key-based diffing.
### Graphology Host (`host/graphology.ts`)
Dirty bitmask pattern on graph nodes:
```typescript
const DIRTY = { Props: 1<<0, Content: 1<<1, Structure: 1<<2 } as const;
```
Edges use `parent->child#order` keys. Version tracking on nodes. Issue: `createInstance` has commented-out append logic, `prepareUpdate` uses `JSON.stringify` diffing.
### Streaming Transformer (`streaming/transformer.ts`)
Chunk-based async iterable processor. V2 preserves this but flush should pass real ancestor context instead of empty arrays.
## What to Remove/Rewrite
### `UniversalProps` (`core/types.ts`)
HTML-specific props that don't belong in a universal IR:
- `onClick`, `onSubmit`, `onInput`, `onChange` (event handlers)
- `className`, `class` (HTML-specific)
- `data-*`, `aria-*` template keys
- `__html` (dangerouslySetInnerHTML)
V2 replaces with plain `Record<string, unknown>`.
### `genId()` (`core/jsx.ts`)
```typescript
function genId(): string {
return `e_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
}
```
Non-deterministic. V2 uses counter-based or injectable IDs.
### Metadata Injection (`core/jsx.ts`)
Every element gets `{ timestamp: new Date(), id: genId() }`. This is overhead without clear use in a universal IR. Move to host-specific concerns if needed.
## TypeBox Research Examples
Source: `/workspace/research/typebox_research/ujsx/`
### `unist.ts` - Unist schema as TypeBox Module
```typescript
export const Unist = Type.Module({
Data: Type.Object({},{additionalProperties: Type.Unknown()}),
Point: Type.Object({ line: Type.Number(), column: Type.Number(), ... }),
Position: Type.Object({ start: Type.Ref('Point'), end: Type.Ref("Point") }),
Node: Type.Object({ type: Type.String(), data: Type.Optional(...), position: Type.Optional(...) }),
Literal: Type.Composite([Type.Ref("Node"), Type.Object({ value: Type.Unknown() })]),
Parent: Type.Composite([Type.Ref("Node"), Type.Object({ children: Type.Array(Type.Ref("Node")) })]),
})
```
### `ujsx.ts` - UJSX schema as TypeBox Module
```typescript
export const UJSX = Type.Module({
ElementMetadata: Type.Object({ id: Type.Optional(Type.String()), timestamp: Type.Optional(Type.Date()) }, { additionalProperties: Type.Unknown() }),
Children: Type.Union([Type.Ref("UniversalNode"), Type.Array(Type.Ref("UniversalNode"))]),
PropValue: Type.Union([Type.String(), Type.Number(), ..., Type.Function([...Type.Rest(Type.Array(Type.Unknown()))], Type.Void())]),
UniversalProps: Type.Object({ id: Type.Optional(Type.String()), children: Type.Optional(Type.Ref("Children")) }, { additionalProperties: Type.Union([Type.Ref("PropValue"), Type.Undefined()]) }),
RootElement: Type.Object({ type: Type.Literal("root"), props: Type.Intersect([...]), children: Type.Array(Type.Ref("UniversalNode")), ... }),
UniversalElement: Type.Object({ type: Type.Union([Type.String(), Type.Function([Type.Ref("UniversalProps")], Type.Ref("UniversalNode"))]), props: Type.Ref("UniversalProps"), children: Type.Array(Type.Ref("UniversalNode")), ... }),
})
```
Key insight: `Type.Module` creates a `TModule` whose `$defs` is a live `string → TSchema` map. Access via `ValuePointer.Get(UJSX, "$defs/Children")`. Add at runtime via `ValuePointer.Set()`. Import resolved schemas via `UJSX.Import("Element")`.
Note: `ElementMetadata` is defined twice in the research file (duplicate). V2 should clean this up and likely drop metadata from the core schema entirely.
### ts2typebox
CLI tool `ts2typebox` can convert TypeScript types to TypeBox defs but has issues with complex types (JSDoc comments, linked references). Useful for basic types, unreliable for complex ones like unist/mdast type definitions.