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

fix: inline thingies dependency #1004

Merged
merged 4 commits into from Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .prettierignore
Expand Up @@ -11,3 +11,4 @@ package-lock.json
CHANGELOG.md

src/json-joy
src/thingies
1 change: 0 additions & 1 deletion package.json
Expand Up @@ -121,7 +121,6 @@
}
},
"dependencies": {
"thingies": "^1.11.1",
"tslib": "^2.0.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/volume/readFile.test.ts
@@ -1,4 +1,4 @@
import { of } from 'thingies';
import { of } from '../../thingies';
import { memfs } from '../..';

describe('.readFile()', () => {
Expand Down
2 changes: 1 addition & 1 deletion 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';
Expand Down
2 changes: 1 addition & 1 deletion 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 = () => {
Expand Down
4 changes: 2 additions & 2 deletions 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';
Expand Down
4 changes: 2 additions & 2 deletions 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';
Expand Down
11 changes: 10 additions & 1 deletion src/fsa-to-node/__tests__/FsaNodeFs.test.ts
Expand Up @@ -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<boolean>, 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 });
Expand Down
2 changes: 1 addition & 1 deletion 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';
Expand Down
20 changes: 20 additions & 0 deletions 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<T> {
public readonly resolve!: (data: T) => void;
public readonly reject!: (error: any) => void;
public readonly promise: Promise<T> = new Promise<T>((resolve, reject) => {
(this as any).resolve = resolve;
(this as any).reject = reject;
});
}
36 changes: 36 additions & 0 deletions src/thingies/concurrency.ts
@@ -0,0 +1,36 @@
import {go} from './go';
import type {Code} from './types';

class Task<T = unknown> {
public readonly resolve!: (data: T) => void;
public readonly reject!: (error: any) => void;
public readonly promise = new Promise<T>((resolve, reject) => {
(this as any).resolve = resolve;
(this as any).reject = reject;
});
constructor(public readonly code: Code<T>) {}
}

/** Limits concurrency of async code. */
export const concurrency = (limit: number) => {
let workers = 0;
const queue = new Set<Task>();
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 <T = unknown>(code: Code<T>): Promise<T> => {
const task = new Task(code);
queue.add(task as Task<unknown>);
return workers < limit && go(work), task.promise;
};
};
6 changes: 6 additions & 0 deletions src/thingies/go.ts
@@ -0,0 +1,6 @@
import type {Code} from './types';

/** Executes code concurrently. */
export const go = <T>(code: Code<T>): void => {
code().catch(() => {});
};
4 changes: 4 additions & 0 deletions src/thingies/index.ts
@@ -0,0 +1,4 @@
export * from './concurrency';
export * from './Defer';
export * from './go';
export * from './of';
16 changes: 16 additions & 0 deletions 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 <T, E = unknown>(promise: Promise<T>): Promise<[T | undefined, E | undefined, boolean]> => {
try {
return [await promise, undefined, true];
} catch (error: unknown) {
return [undefined, error as E, false];
}
};
1 change: 1 addition & 0 deletions src/thingies/types.ts
@@ -0,0 +1 @@
export type Code<T = unknown> = () => Promise<T>;
5 changes: 0 additions & 5 deletions yarn.lock
Expand Up @@ -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"
Expand Down