Skip to content

Commit

Permalink
refactor: local-change -> commit
Browse files Browse the repository at this point in the history
  • Loading branch information
icidasset committed Dec 15, 2023
1 parent f78266e commit 345da63
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 66 deletions.
12 changes: 4 additions & 8 deletions examples/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "1.0.0",
"private": true,
"description": "",
"author": "Hugo Dias <hugomrdias@gmail.com> (hugodias.me)",
"author": "Steven Vandevelde <icid.asset@gmail.com> (tokono.ma)",
"license": "MIT",
"keywords": [],
"main": "src/main.jsx",
Expand All @@ -15,7 +15,7 @@
"serve": "vite preview --port 3000"
},
"dependencies": {
"package1": "*"
"@wnfs-wg/nest": "file:../../packages/nest"
},
"devDependencies": {
"@babel/core": "^7.23.5",
Expand All @@ -24,11 +24,7 @@
"vite": "^5.0.7"
},
"eslintConfig": {
"extends": [
"@fission-codes"
],
"ignorePatterns": [
"dist"
]
"extends": ["@fission-codes"],
"ignorePatterns": ["dist"]
}
}
2 changes: 1 addition & 1 deletion examples/demo/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { randomBytes } from 'package1'
import { randomBytes } from '@wnfs-wg/nest'

// eslint-disable-next-line no-console
console.log(randomBytes(10))
2 changes: 1 addition & 1 deletion packages/nest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@wnfs-wg/nest",
"type": "module",
"version": "0.1.0",
"description": "Example package description.",
"description": "A utility layer around the `wnfs` package.",
"author": "Steven Vandevelde <[email protected]> (tokono.ma)",
"license": "(Apache-2.0 AND MIT)",
"homepage": "https://github.com/wnfs-wg/nest/tree/main/packages/nest",
Expand Down
65 changes: 63 additions & 2 deletions packages/nest/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
[![npm (scoped)](https://img.shields.io/npm/v/%40fission-codes/eslint-config)](https://www.npmjs.com/package/@fission-codes/eslint-config)
[![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/fission-codes/stack/eslint-config.yml)](https://github.com/fission-codes/stack/actions/workflows/eslint-config.yml)

A layer around the `wnfs` package that provides a `FileSystem` class, a root tree, mounts, transactions and some other essentials.

## Features

- A file system class that allows for an easy-to-use mutable API.
Expand All @@ -22,8 +24,67 @@ pnpm install @wnfs-wg/nest

## Usage

```js
import { module } from '@wnfs-wg/nest'
```ts
import { FileSystem, Path } from '@wnfs-wg/nest'

// Provide some block store of the `Blockstore` type from the `interface-blockstore` package
import { MemoryBlockstore } from 'blockstore-core/memory'
```

Scenario 1:
🚀 Create a new file system, create a new file and read it back.

```ts
const fs = await FileSystem.create({ blockstore: new MemoryBlockstore() })

await fs.write(
Path.file('private', 'file'),
'utf8',
'🪺'
)

const contents = await fs.read(Path.file('private', 'file'), 'utf8')
```

Scenario 2:
🛰️ Listen to commit and/or publish events.

_A commit is a (optionally verified) modification to the file system,
and publishes are the debounced events resulting from the commits._

This will allow us the store the latest state of our file system,
for this we need what we call the data root. This is the top-level CID
of our root tree, the pointer to our file system.

```ts
let fsPointer: CID = await fs.calculateDataRoot()

// When we make a modification to the file system a verification is performed.
await fs.write(
Path.file('private', 'file'),
'utf8',
'🪺'
)

// If the commit is approved, the changes are reflected in the file system and
// the `commit` and `publish` events are emitted.
fs.on('commit', ({ dataRoot, modifications }) => {
// Commit approved and performed ✅
})

fs.on('publish', ({ dataRoot }) => {
// Commit approved and performed ✅
// Debounced and delayed ✅
fsPointer
})
```

Scenario 3:
🧳 Load a file system from a previous pointer.

```ts
// `blockstore` from scenario 1 & `fsPointer` from scenario 2
const fs = await FileSystem.fromCID(fsPointer, { blockstore })
```

## Docs
Expand Down
11 changes: 5 additions & 6 deletions packages/nest/src/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export class FileSystem {
static async fromCID(cid: CID, opts: Options): Promise<FileSystem> {
const { blockstore, onCommit, rootTreeClass, settleTimeBeforePublish } =
opts

const rootTree = await (rootTreeClass ?? BasicRootTree).fromCID(
blockstore,
cid
Expand Down Expand Up @@ -647,12 +648,10 @@ export class FileSystem {
const dataRoot = await this.calculateDataRoot()

// Emit events
for (const change of changes) {
await this.#eventEmitter.emit('local-change', {
dataRoot,
...change,
})
}
await this.#eventEmitter.emit('commit', {
dataRoot,
modifications: [...changes],
})

// Publish
if (
Expand Down
8 changes: 3 additions & 5 deletions packages/nest/src/events.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import type { CID } from 'multiformats/cid'
import type { DistinctivePath, Partition, Partitioned } from './path.js'
import type { MutationType } from './types.js'
import type { Modification } from './types.js'

// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type Events = {
'local-change': {
commit: {
dataRoot: CID
path: DistinctivePath<Partitioned<Partition>>
type: MutationType
modifications: Modification[]
}
publish: { dataRoot: CID }
}
Expand Down
2 changes: 2 additions & 0 deletions packages/nest/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export * from './class.js'
export * from './root-tree.js'
export * from './root-tree/basic.js'
export * from './types.js'

export * as Path from './path.js'
72 changes: 29 additions & 43 deletions packages/nest/test/class.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@ describe('File System Class', () => {
const privatePath = Path.file('private', 'nested-private', 'private.txt')

const { contentCID } = await fs.write(publicPath, 'utf8', 'public')
const { _capsuleKey, dataRoot } = await fs.write(
privatePath,
'utf8',
'private'
)
const { dataRoot } = await fs.write(privatePath, 'utf8', 'private')

const contentBytes = await Unix.exportFile(contentCID, blockstore)

Expand Down Expand Up @@ -140,7 +136,7 @@ describe('File System Class', () => {
const path = Path.file('public', 'a')
const bytes = new TextEncoder().encode('🚀')

const { _contentCID } = await fs.write(path, 'bytes', bytes)
await fs.write(path, 'bytes', bytes)

assert.equal(await fs.read(path, 'utf8'), '🚀')
await assertUnixFsFile({ blockstore }, fs, path, bytes)
Expand All @@ -149,7 +145,7 @@ describe('File System Class', () => {
it('writes and reads private files', async () => {
const path = Path.file('private', 'a')

const { _capsuleKey } = await fs.write(path, 'json', { foo: 'bar', a: 1 })
await fs.write(path, 'json', { foo: 'bar', a: 1 })

assert.deepEqual(await fs.read(path, 'json'), { foo: 'bar', a: 1 })
})
Expand Down Expand Up @@ -854,8 +850,8 @@ describe('File System Class', () => {
const fromPath = Path.file('public', 'a', 'b', 'file')
const toPath = Path.file('private', 'a', 'b', 'c', 'd', 'file')

const { _capsuleCID } = await fs.write(fromPath, 'utf8', '💃')
const { _capsuleKey } = await fs.move(fromPath, toPath)
await fs.write(fromPath, 'utf8', '💃')
await fs.move(fromPath, toPath)

assert.equal(await fs.read(toPath, 'utf8'), '💃')
assert.equal(await fs.exists(fromPath), false)
Expand All @@ -865,8 +861,8 @@ describe('File System Class', () => {
const fromPath = Path.file('private', 'a', 'b', 'file')
const toPath = Path.file('public', 'a', 'b', 'c', 'd', 'file')

const { _capsuleKey } = await fs.write(fromPath, 'utf8', '💃')
const { _capsuleCID } = await fs.move(fromPath, toPath)
await fs.write(fromPath, 'utf8', '💃')
await fs.move(fromPath, toPath)

assert.equal(await fs.read(toPath, 'utf8'), '💃')
assert.equal(await fs.exists(fromPath), false)
Expand Down Expand Up @@ -919,35 +915,27 @@ describe('File System Class', () => {
setTimeout(resolve, fsOpts.settleTimeBeforePublish * 1.5)
)

const promise = new Promise((resolve, reject) => {
const promise = new Promise<CID>((resolve, reject) => {
setTimeout(reject, 10_000)
fs.once('publish')
.then((event) => event.dataRoot)
.then(resolve, reject)
})

const a = await fs.write(
Path.file('private', 'a'),
'bytes',
new Uint8Array()
)
const b = await fs.write(
Path.file('private', 'b'),
'bytes',
new Uint8Array()
)
const c = await fs.write(
Path.file('private', 'c'),
'bytes',
new Uint8Array()
)
await fs.write(Path.file('private', 'a'), 'bytes', new Uint8Array())

await fs.write(Path.file('private', 'b'), 'bytes', new Uint8Array())

await fs.write(Path.file('private', 'c'), 'bytes', new Uint8Array())

const d = await fs.write(
Path.file('private', 'd'),
'bytes',
new Uint8Array()
)

assert.equal((await promise).toString(), d.dataRoot.toString())
const result = await promise
assert.equal(result.toString(), d.dataRoot.toString())
})

it("doesn't publish when asked not to do so", async () => {
Expand Down Expand Up @@ -986,10 +974,10 @@ describe('File System Class', () => {
// Other than "publish"

it('emits an event for a mutation', async () => {
const eventPromise: Promise<CID> = new Promise((resolve, reject) => {
setTimeout(reject, 10000)
const eventPromise = new Promise<CID>((resolve, reject) => {
setTimeout(reject, 10_000)

fs.on('local-change', ({ dataRoot }) => {
fs.on('commit', ({ dataRoot }) => {
resolve(dataRoot)
})
})
Expand All @@ -1000,10 +988,8 @@ describe('File System Class', () => {
new Uint8Array()
)

assert.equal(
(await eventPromise).toString(),
mutationResult.dataRoot.toString()
)
const eventResult = await eventPromise
assert.equal(eventResult.toString(), mutationResult.dataRoot.toString())
})

// TRANSACTIONS
Expand All @@ -1022,14 +1008,14 @@ describe('File System Class', () => {
assert.equal(await fs.read(Path.file('public', 'file'), 'utf8'), '💃')
})

async function transaction(): Promise<void> {
await fs
.transaction(async (t) => {
await t.write(Path.file('private', 'file'), 'utf8', '💃')
throw new Error('Whoops')
})
.catch((_error) => {})
}
// async function transaction(): Promise<void> {
// await fs
// .transaction(async (t) => {
// await t.write(Path.file('private', 'file'), 'utf8', '💃')
// throw new Error('Whoops')
// })
// .catch((_error) => {})
// }

// it("doesn't commit a transaction when an error occurs inside of the transaction", async () => {
// const tracker = new assert.CallTracker()
Expand Down

0 comments on commit 345da63

Please sign in to comment.