From 6fc340d83544d04c35f62bc0fa7aadf77266af12 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Sun, 18 Feb 2024 11:06:31 +1300 Subject: [PATCH] fix: inline `thingies` dependency (#1004) * fix: inline `thingies` * fix: remove unneeded code * chore: don't apply prettier to `thingies` code * refactor: inline `tick` and `until` functions --- .prettierignore | 1 + package.json | 1 - src/__tests__/volume/readFile.test.ts | 2 +- src/crud-to-cas/__tests__/testCasfs.ts | 2 +- src/crud/__tests__/testCrudfs.ts | 2 +- src/fsa-to-node/FsaNodeReadStream.ts | 4 +-- src/fsa-to-node/FsaNodeWriteStream.ts | 4 +-- src/fsa-to-node/__tests__/FsaNodeFs.test.ts | 11 +++++- .../worker/FsaNodeSyncAdapterWorker.ts | 2 +- src/thingies/Defer.ts | 20 +++++++++++ src/thingies/concurrency.ts | 36 +++++++++++++++++++ src/thingies/go.ts | 6 ++++ src/thingies/index.ts | 4 +++ src/thingies/of.ts | 16 +++++++++ src/thingies/types.ts | 1 + yarn.lock | 5 --- 16 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 src/thingies/Defer.ts create mode 100644 src/thingies/concurrency.ts create mode 100644 src/thingies/go.ts create mode 100644 src/thingies/index.ts create mode 100644 src/thingies/of.ts create mode 100644 src/thingies/types.ts diff --git a/.prettierignore b/.prettierignore index 2b323902..acf09436 100644 --- a/.prettierignore +++ b/.prettierignore @@ -11,3 +11,4 @@ package-lock.json CHANGELOG.md src/json-joy +src/thingies diff --git a/package.json b/package.json index dc617f13..056881be 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,6 @@ } }, "dependencies": { - "thingies": "^1.11.1", "tslib": "^2.0.0" }, "devDependencies": { diff --git a/src/__tests__/volume/readFile.test.ts b/src/__tests__/volume/readFile.test.ts index 16d5af9a..45d4a390 100644 --- a/src/__tests__/volume/readFile.test.ts +++ b/src/__tests__/volume/readFile.test.ts @@ -1,4 +1,4 @@ -import { of } from 'thingies'; +import { of } from '../../thingies'; import { memfs } from '../..'; describe('.readFile()', () => { diff --git a/src/crud-to-cas/__tests__/testCasfs.ts b/src/crud-to-cas/__tests__/testCasfs.ts index b03c5ac8..16c7f5cd 100644 --- a/src/crud-to-cas/__tests__/testCasfs.ts +++ b/src/crud-to-cas/__tests__/testCasfs.ts @@ -1,4 +1,4 @@ -import { of } from 'thingies'; +import { of } from '../../thingies'; import { createHash } from 'crypto'; import { hashToLocation } from '../util'; import type { CasApi } from '../../cas/types'; diff --git a/src/crud/__tests__/testCrudfs.ts b/src/crud/__tests__/testCrudfs.ts index b5c2d988..433fe251 100644 --- a/src/crud/__tests__/testCrudfs.ts +++ b/src/crud/__tests__/testCrudfs.ts @@ -1,4 +1,4 @@ -import { of } from 'thingies'; +import { of } from '../../thingies'; import type { CrudApi } from '../types'; export type Setup = () => { diff --git a/src/fsa-to-node/FsaNodeReadStream.ts b/src/fsa-to-node/FsaNodeReadStream.ts index f9ffc1ab..0949d13b 100644 --- a/src/fsa-to-node/FsaNodeReadStream.ts +++ b/src/fsa-to-node/FsaNodeReadStream.ts @@ -1,6 +1,6 @@ import { Readable } from 'stream'; -import { Defer } from 'thingies/es6/Defer'; -import { concurrency } from 'thingies/es6/concurrency'; +import { Defer } from '../thingies/Defer'; +import { concurrency } from '../thingies/concurrency'; import type { FsaNodeFsOpenFile } from './FsaNodeFsOpenFile'; import type { IReadStream } from '../node/types/misc'; import type { IReadStreamOptions } from '../node/types/options'; diff --git a/src/fsa-to-node/FsaNodeWriteStream.ts b/src/fsa-to-node/FsaNodeWriteStream.ts index 7b45ee77..1d89eb22 100644 --- a/src/fsa-to-node/FsaNodeWriteStream.ts +++ b/src/fsa-to-node/FsaNodeWriteStream.ts @@ -1,6 +1,6 @@ import { Writable } from 'stream'; -import { Defer } from 'thingies/es6/Defer'; -import { concurrency } from 'thingies/es6/concurrency'; +import { Defer } from '../thingies/Defer'; +import { concurrency } from '../thingies/concurrency'; import { flagsToNumber } from '../node/util'; import { FLAG } from '../consts/FLAG'; import { FsaNodeFsOpenFile } from './FsaNodeFsOpenFile'; diff --git a/src/fsa-to-node/__tests__/FsaNodeFs.test.ts b/src/fsa-to-node/__tests__/FsaNodeFs.test.ts index 239a98bd..052846f8 100644 --- a/src/fsa-to-node/__tests__/FsaNodeFs.test.ts +++ b/src/fsa-to-node/__tests__/FsaNodeFs.test.ts @@ -3,10 +3,19 @@ import { AMODE } from '../../consts/AMODE'; import { nodeToFsa } from '../../node-to-fsa'; import { IDirent, IStats } from '../../node/types/misc'; import { FsaNodeFs } from '../FsaNodeFs'; -import { tick, until, of } from 'thingies'; +import { of } from '../../thingies'; import { onlyOnNode20 } from '../../__tests__/util'; import { FLAG } from '../../consts/FLAG'; +const tick = (ms: number = 1) => new Promise(r => setTimeout(r, ms)); + +const until = async (check: () => boolean | Promise, pollInterval: number = 1) => { + do { + if (await check()) return; + await tick(pollInterval); + } while (true); +}; + const setup = (json: NestedDirectoryJSON | null = null, mode: 'read' | 'readwrite' = 'readwrite') => { const { fs: mfs, vol } = memfs({ mountpoint: json }); const dir = nodeToFsa(mfs, '/mountpoint', { mode, syncHandleAllowed: true }); diff --git a/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts b/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts index 1f8c4296..a59d20c7 100644 --- a/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts +++ b/src/fsa-to-node/worker/FsaNodeSyncAdapterWorker.ts @@ -1,4 +1,4 @@ -import { Defer } from 'thingies/es6/Defer'; +import { Defer } from '../../thingies/Defer'; import { FsaNodeWorkerMessageCode } from './constants'; import { SyncMessenger } from './SyncMessenger'; import { decoder, encoder } from '../json'; diff --git a/src/thingies/Defer.ts b/src/thingies/Defer.ts new file mode 100644 index 00000000..54503752 --- /dev/null +++ b/src/thingies/Defer.ts @@ -0,0 +1,20 @@ +/** + * An externally resolvable/rejectable "promise". Use it to resolve/reject + * promise at any time. + * + * ```ts + * const future = new Defer(); + * + * future.promise.then(value => console.log(value)); + * + * future.resolve(123); + * ``` + */ +export class Defer { + public readonly resolve!: (data: T) => void; + public readonly reject!: (error: any) => void; + public readonly promise: Promise = new Promise((resolve, reject) => { + (this as any).resolve = resolve; + (this as any).reject = reject; + }); +} diff --git a/src/thingies/concurrency.ts b/src/thingies/concurrency.ts new file mode 100644 index 00000000..caf40617 --- /dev/null +++ b/src/thingies/concurrency.ts @@ -0,0 +1,36 @@ +import {go} from './go'; +import type {Code} from './types'; + +class Task { + public readonly resolve!: (data: T) => void; + public readonly reject!: (error: any) => void; + public readonly promise = new Promise((resolve, reject) => { + (this as any).resolve = resolve; + (this as any).reject = reject; + }); + constructor(public readonly code: Code) {} +} + +/** Limits concurrency of async code. */ +export const concurrency = (limit: number) => { + let workers = 0; + const queue = new Set(); + const work = async () => { + const task = queue.values().next().value; + if (task) queue.delete(task); + else return; + workers++; + try { + task.resolve(await task.code()); + } catch (error) { + task.reject(error); + } finally { + workers--, queue.size && go(work); + } + }; + return async (code: Code): Promise => { + const task = new Task(code); + queue.add(task as Task); + return workers < limit && go(work), task.promise; + }; +}; diff --git a/src/thingies/go.ts b/src/thingies/go.ts new file mode 100644 index 00000000..64388af2 --- /dev/null +++ b/src/thingies/go.ts @@ -0,0 +1,6 @@ +import type {Code} from './types'; + +/** Executes code concurrently. */ +export const go = (code: Code): void => { + code().catch(() => {}); +}; diff --git a/src/thingies/index.ts b/src/thingies/index.ts new file mode 100644 index 00000000..be02252a --- /dev/null +++ b/src/thingies/index.ts @@ -0,0 +1,4 @@ +export * from './concurrency'; +export * from './Defer'; +export * from './go'; +export * from './of'; diff --git a/src/thingies/of.ts b/src/thingies/of.ts new file mode 100644 index 00000000..31a11ce5 --- /dev/null +++ b/src/thingies/of.ts @@ -0,0 +1,16 @@ +/** + * Given a promise awaits it and returns a 3-tuple, with the following members: + * + * - First entry is either the resolved value of the promise or `undefined`. + * - Second entry is either the error thrown by promise or `undefined`. + * - Third entry is a boolean, truthy if promise was resolved and falsy if rejected. + * + * @param promise Promise to convert to 3-tuple. + */ +export const of = async (promise: Promise): Promise<[T | undefined, E | undefined, boolean]> => { + try { + return [await promise, undefined, true]; + } catch (error: unknown) { + return [undefined, error as E, false]; + } +}; diff --git a/src/thingies/types.ts b/src/thingies/types.ts new file mode 100644 index 00000000..a1ec65bc --- /dev/null +++ b/src/thingies/types.ts @@ -0,0 +1 @@ +export type Code = () => Promise; diff --git a/yarn.lock b/yarn.lock index b567bee8..d25def6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6682,11 +6682,6 @@ text-table@~0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -thingies@^1.11.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/thingies/-/thingies-1.16.0.tgz#968cde87fbf0fdd69a1a3a8e9678324f634e5053" - integrity sha512-J23AVs11hSQxuJxvfQyMIaS9z1QpDxOCvMkL3ZxZl8/jmkgmnNGWrlyNxVz6Jbh0U6DuGmHqq6f7zUROfg/ncg== - through2@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764"