Skip to content

Deno-ESM emit target + Deno-FS stdlib bindings (enable TS→AffineScript for Deno I/O modules) #122

@hyperpolymath

Description

@hyperpolymath

Motivation

Estate TS-elimination (RSR: no TypeScript in the Tier-1 estate) requires migrating Deno I/O modules, not just wasm-pure logic and VS Code extensions. Concrete blocked consumer: hyperpolymath/ubicity src/storage.ts (async ExperienceStorage class, Deno FS effects, consumed as ESM ./storage.js by ~6 .js modules) and src/wasm-bridge.ts (Deno.readFile + WebAssembly.instantiate glue). The antipattern-check gate correctly flags these as genuine violations; they cannot be migrated today.

Gap analysis

Available today (per #35, Phases 1–3, lib/codegen_node.ml):

  • ✅ wasm expression core (Int/Bool/struct/enum/match)
  • ✅ Node-CJS .cjs shim wrapping compiled wasm
  • ✅ vscode FFI bindings (stdlib/Vscode.affine, handle-table adapter)

Missing for Deno I/O module migration:

  1. Deno-ESM emit target — emit an ES module (.js, import/export) consumable by a Deno runtime, distinct from the Node-CJS .cjs path. Output-extension dispatch like the existing .cjs route.
  2. stdlib/Deno.affine FS bindingspub extern fn leaves for Deno.readTextFile/writeTextFile/readDir/stat/remove, ensureDir (@std/fs), join (@std/path), Deno.errors.NotFound discrimination. JS-side adapter mirroring the packages/affine-vscode/mod.js handle/readString pattern.
  3. Async-extern ABIstorage.ts is async/Promise-returning. Depends on / extends Async-extern ABI: bind withProgress + LanguageClient.sendRequest #103 (async-extern ABI). Required before any Deno FS binding is callable.
  4. Class/object ESM emissionExperienceStorage is an instantiable class with private fields; emit must expose a constructable object whose methods bridge to wasm + the JS adapter.

Scope

In: the four capabilities above + a migration of ubicity's two files as the proving harness. Out: non-Deno runtimes; experimental nextgen-languages; vscode work (covered by #35/#63/#104).

Acceptance criteria

  • affinescript emits a Deno-ESM module from .affine (dispatched by output ext)
  • stdlib/Deno.affine covers the FS/path surface listed above, with JS adapter
  • async-extern path (Async-extern ABI: bind withProgress + LanguageClient.sendRequest #103) sufficient for Promise-returning FS calls
  • ubicity storage.affine + wasm-bridge.affine compile to drop-in ./storage.js/./wasm-bridge.js; ubicity deno task test + antipattern-check green; no .ts in src/

Relations

Refs #35 (builds on its codegen_node.ml/shim infra). Refs #103 (async-extern prerequisite). Motivating consumer: hyperpolymath/ubicity. Surfaced during the 2026-05-16 estate PR sweep.

Metadata

Metadata

Assignees

No one assigned

    Labels

    majorMajor issue — significant scope, broader impact than a feature/bugrequirements-targetRequirements-target issue — only closes when Claude and user mutually agree the spec is satisfied

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions