@ozaco/std
// std.io@ozaco/std/io
  1. docs
  2. std
  3. io

@ozaco/std

import from

@ozaco/std/io

IO

One contract for the filesystem, paths, processes, the network, the environment and crypto, and an implementation that binds it to a host. Your operations call IO.actions; which host answers is decided by one import.

Binding a backend

Use the entry point of the host the program runs on. From then on every IO.actions call in the scope goes to it.

const { BunIO } = await import('@ozaco/std/io/impl/bun')

const result = await run(function* () {
  yield* BunIO.use()

  const cwd = yield* IO.actions.cwd()
  const platform = yield* IO.actions.platform()

  return { cwd, platform }
})

// from examples/std/io.test.ts

Files

Paths are joined by the host, text is written and read back as text, and exists says whether there is anything there. Nothing names Bun or Node.

const result = await run(function* () {
  yield* BunIO.use()

  const path = yield* IO.actions.join(dir, 'notes.txt')

  yield* IO.actions.write(path, 'first line\n')
  yield* IO.actions.append(path, new TextEncoder().encode('second line\n'))

  const text = yield* IO.actions.readText(path)
  const there = yield* IO.actions.exists(path)

  return { text, there }
})

// from examples/std/io.test.ts

Switching the runtime

Write the operation once. It names no host.

const whereAmI = function* () {
  const platform = yield* IO.actions.platform()
  const cwd = yield* IO.actions.cwd()

  return { platform, cwd }
}

// from examples/std/io.test.ts

Then bind the host it runs on: the import and the use() line are all that change.

const { BunIO } = await import('@ozaco/std/io/impl/bun')

const result = await run(function* () {
  yield* BunIO.use()

  return yield* whereAmI()
})

// from examples/std/io.test.ts

On the Web the filesystem and process calls answer IOErrors.Unsupported; paths, env, ids and hashing are there.

IO
ozaco.com
~/ozaco

Runtime-agnostic TypeScript packages, and two things built on them.

MIT