Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implementation tmp #23

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
94 changes: 52 additions & 42 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ describe('FileSystemStorageAdapter', () => {
vi.mocked(lstat).mockResolvedValueOnce({} as any)
vi.mocked(rm).mockResolvedValueOnce(undefined)
await storage.delete('foo')
expect(rm).toHaveBeenCalledWith(join(process.cwd(), 'foo'))
expect(rm).toHaveBeenCalledWith(join(storage.baseDir, 'foo'))
})
it('should throw if the file does not exist', async () => {
const storage = new FileSystemStorageAdapter()
Expand Down Expand Up @@ -185,7 +185,7 @@ describe('FileSystemStorageAdapter', () => {
it('should return the uri', async () => {
const storage = new FileSystemStorageAdapter()
const handle = await storage.open('bar')
expect(handle.uri).toBe(`file://${process.cwd()}/bar`)
expect(handle.uri).toBe(`file://${storage.baseDir}/bar`)
})

describe('createReadStream method', () => {
Expand Down Expand Up @@ -213,7 +213,7 @@ describe('FileSystemStorageAdapter', () => {
const handle = await storage.open('bar')
await handle.createReadStream()

expect(open).toHaveBeenCalledWith(join(process.cwd(), 'bar'), 'r')
expect(open).toHaveBeenCalledWith(join(storage.baseDir, 'bar'), 'r')
})

it('should throw PermissionDeniedError without read permission on file', async () => {
Expand Down Expand Up @@ -282,14 +282,14 @@ describe('FileSystemStorageAdapter', () => {
const storage = new FileSystemStorageAdapter()
const handle = await storage.open('bar', { create: true, write: true })
await handle.createWriteStream()
expect(open).toHaveBeenCalledWith(join(process.cwd(), 'bar'), 'w', 0o666)
expect(open).toHaveBeenCalledWith(join(storage.baseDir, 'bar'), 'w', 0o666)
})

it('should open the file with given mode', async () => {
const storage = new FileSystemStorageAdapter({ mode: 0o777 })
const handle = await storage.open('bar', { create: true, write: true })
await handle.createWriteStream()
expect(open).toHaveBeenCalledWith(join(process.cwd(), 'bar'), 'w', 0o777)
expect(open).toHaveBeenCalledWith(join(storage.baseDir, 'bar'), 'w', 0o777)
})

it('should throw FileNotExistsError if the file exists and create is false', async () => {
Expand All @@ -315,7 +315,7 @@ describe('FileSystemStorageAdapter', () => {

const handle = await storage.open('bar', { write: true, create: true })
await handle.createWriteStream()
expect(mkdir).toHaveBeenCalledWith(join(process.cwd()), { recursive: true })
expect(mkdir).toHaveBeenCalledWith(join(storage.baseDir), { recursive: true })
})

it('should not create the directory if createDirectoryIfNotExists is false', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class FileSystemStorageAdapter implements Storage {
public readonly createDirectoryIfNotExists: boolean

public get url(): URL {
return new URL(this.baseDir, `${this.urlSchema}/`)
return new URL(this.baseDir, `${this.urlSchema}//`)
}
constructor({
urlSchema = DEFAULT_SCHEMA,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it, vi, beforeEach } from 'vitest'
import { FileSystemStoragePlugin } from './FileSystemStoragePlugin.js'
import { join } from 'node:path'
import { join, resolve } from 'node:path'
import { FileSystemStorageAdapter } from '../adapters/FileSystemStorageAdapter.js'
import { mkdir } from 'node:fs/promises'

Expand Down Expand Up @@ -64,12 +64,18 @@ describe('FileSystemStoragePlugin', () => {
expect(storage.urlSchema).toBe('file:')
})

it('should set the baseDir to the host and pathname of the url', async () => {
it('should set the baseDir to the host and absolute pathname of the url', async () => {
const plugin = new FileSystemStoragePlugin({ createDirectoryIfNotExists: false })
const storage = await plugin.build(new URL('file:///foo/bar'))
expect(storage.baseDir).toBe('/foo/bar')
})

it('should set the baseDir to the host and relative pathname of the url', async () => {
const plugin = new FileSystemStoragePlugin({ createDirectoryIfNotExists: false })
const storage = await plugin.build(new URL('file://../foo/bar'))
expect(storage.baseDir).toBe(`${join(resolve(process.cwd(), '..'), 'foo', 'bar')}`)
})

it('should create the directory if createDirectoryIfNotExists is true(default)', async () => {
const plugin = new FileSystemStoragePlugin()
const mocked = vi.mocked(mkdir)
Expand Down
4 changes: 2 additions & 2 deletions packages/@connectable-io/storage-plugin-file/src/pnp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { Storage } from '@connectable-io/storage'
import { FileSystemStoragePlugin } from './plugins/FileSystemStoragePlugin.js'
import { DEFAULT_SCHEMA } from './constant.js'

declare module '@connectable-io/storage' {
type URLString = `file://${string}`
type URLString = `${typeof DEFAULT_SCHEMA}//${string}`

declare module '@connectable-io/storage' {
export interface StorageStatic {
/**
* Build a storage based on local FileSystem from a URL
Expand Down
1 change: 1 addition & 0 deletions packages/@connectable-io/storage-plugin-tmp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# @connectable-io/storage-plugin-tmp
21 changes: 21 additions & 0 deletions packages/@connectable-io/storage-plugin-tmp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@connectable-io/storage-plugin-tmp",
"version": "0.0.0",
"type": "module",
"module": "./lib/index.js",
"types": "./lib/index.d.ts",
"exports": {
".": {
"import": "./lib/index.js",
"types": "./lib/index.d.ts"
},
"./pnp": {
"import": "./lib/pnp.js",
"types": "./lib/pnp.d.ts"
}
},
"dependencies": {
"@connectable-io/core": "^0.0.1",
"@connectable-io/storage": "^0.0.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, it, expect } from 'vitest'
import { join } from 'node:path'
import { tmpdir } from 'node:os'

import { TmpStorageAdapter } from './TmpStorageAdapter.js'

describe('TmpStorageAdapter', () => {
describe('constructor', () => {
it('should use the default base directory', () => {
const storage = new TmpStorageAdapter()
expect(storage.url.pathname).toBe(tmpdir())
})
it('should use the default url schema', () => {
const storage = new TmpStorageAdapter()
expect(storage.url.protocol).toBe('tmp:')
})
it('should resolve relative paths', () => {
const storage = new TmpStorageAdapter({ baseDir: 'foo' })
expect(storage.url.pathname).toBe(join(tmpdir(), 'foo'))
})
it('should use absolute paths as is', () => {
const storage = new TmpStorageAdapter({ baseDir: '/foo' })
expect(storage.url.pathname).toBe('/foo')
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/// <reference lib="esnext" />
import { tmpdir } from 'node:os'
import { isAbsolute, resolve } from 'node:path'

import { FileSystemStorageAdapter, type FileSystemStorageAdapterOptions } from '@connectable-io/storage-plugin-file'

import { DEFAULT_SCHEMA } from '../constant.js'

/**
* Options for TmpStorageAdapter
*/
export interface TmpStorageAdapterOptions extends FileSystemStorageAdapterOptions {
/**
* The schema to use for the url.
* This is used to create the url for the storage.
* The schema is used as the protocol part of the url.
* @example
* ```ts
* const storage = new TmpStorageAdapter({ urlSchema: 'tmp:', baseDir: 'foo' })
* console.log(storage.url.toString()) // 'tmp://foo'
* ```
* @default `tmp:`
*/
urlSchema?: string

/**
* The base directory to use for the storage.
* Absolute paths are used as is.
* Paths given as relative paths are resolved starting from `os.tmpdir()`.
* @default `os.tmpdir()`
*/
baseDir?: string
}

/**
* A Storage implementation for the tmp directory
*/
export class TmpStorageAdapter extends FileSystemStorageAdapter {
constructor({ urlSchema = DEFAULT_SCHEMA, baseDir = tmpdir(), ...options }: TmpStorageAdapterOptions = {}) {
super({ urlSchema, baseDir: isAbsolute(baseDir) ? baseDir : resolve(tmpdir(), baseDir), ...options })
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEFAULT_SCHEMA = 'tmp:'
2 changes: 2 additions & 0 deletions packages/@connectable-io/storage-plugin-tmp/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './adapters/TmpStorageAdapter.js'
export * from './plugins/TmpStoragePlugin.js'
Loading
Loading