Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

end_of_line = lf
max_line_length = 100
25 changes: 15 additions & 10 deletions eslint.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,27 @@ import markdown from "@eslint/markdown";
import { defineConfig } from "eslint/config";
import stylistic from "@stylistic/eslint-plugin";


export default defineConfig([
{
ignores: [
`dist/**.*`
]
`dist/**.*`,
],
},
{ files: [`**/*.{js,mjs,cjs,ts,mts,cts}`], plugins: { js }, extends: [`js/recommended`] },
{ files: [`**/*.{js,mjs,cjs,ts,mts,cts}`], languageOptions: { globals: { ...globals.browser, ...globals.node } } },
tseslint.configs.recommended as unknown as Parameters<typeof defineConfig>,
{
files: [`**/*.{js,mjs,cjs,ts,mts,cts}`],
plugins: {
"@stylistic": stylistic,
"tseslint": tseslint,
},
extends: [
"@stylistic/recommended",
"tseslint/recommended",
],
rules: {
"semi": [`error`],
"@stylistic/semi": ["error", "always"],
"no-unused-vars": [`off`],
"@typescript-eslint/no-unused-vars": [`error`, {
argsIgnorePattern: `^_`,
Expand All @@ -30,18 +35,18 @@ export default defineConfig([
destructuredArrayIgnorePattern: `^_`,
varsIgnorePattern: `^_`,
}],
"@stylistic/quotes": [`error`, "double", { "allowTemplateLiterals": "always" }],
}
"@stylistic/quotes": [`error`, "double", { allowTemplateLiterals: "always" }],
},
},
{ files: [`**/*.json`], ignores: [`**/tsconfig.json`, `package-lock.json`,`**/.vscode/*.json`], plugins: { json }, language: `json/json`, extends: [`json/recommended`] },
{ files: [`**/*.json`], ignores: [`**/tsconfig.json`, `package-lock.json`, `**/.vscode/*.json`], plugins: { json }, language: `json/json`, extends: [`json/recommended`] },
{
files: [
`**/tsconfig.json`,
`**/*.code-workspace`,
`**/.vscode/*.json`,
],
plugins: {json},
language: "json/jsonc",
],
plugins: { json },
language: "json/jsonc",
languageOptions: {
allowTrailingCommas: true,
},
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import "./requiredAsyncDispose.ts";
export * from "./lock.ts";
export type { ReleasableLock } from "./types/index.ts";
export type { ReleasableLock } from "./types/index.ts";
61 changes: 31 additions & 30 deletions src/lock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe("simple use", (args) => {
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
});
}
Expand Down Expand Up @@ -54,7 +54,7 @@ describe("simple use", (args) => {
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
pending: undefined,
});
Expand All @@ -68,14 +68,14 @@ describe("simple use", (args) => {
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
pending: [
{
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
});
lock2Wait.finally(() => expect(counter++).toEqual(2));
Expand Down Expand Up @@ -120,14 +120,14 @@ describe("simple use", (args) => {
clientId: expect.any(String),
mode: "shared",
name,
}
},
],
pending: [
{
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
});
await expect(lock1.release()).resolves.toBeUndefined();
Expand All @@ -139,7 +139,7 @@ describe("simple use", (args) => {
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
pending: undefined,
});
Expand All @@ -152,7 +152,7 @@ describe("simple use", (args) => {
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
pending: undefined,
});
Expand Down Expand Up @@ -197,7 +197,7 @@ describe("simple use", (args) => {
{
await using _ = await request();
await using lock2 = await request({
ifAvailable: true
ifAvailable: true,
});
expect(lock2).toBeNull();
}
Expand Down Expand Up @@ -236,7 +236,7 @@ describe("simple use", (args) => {
});
await expect(lockWait).rejects.toThrowError(expect.objectContaining({
message: "ifAvailable and steal are mutually exclusive",
name: "NotSupportedError"
name: "NotSupportedError",
}));
}
});
Expand All @@ -253,7 +253,7 @@ describe("hard error pattern", (args) => {
});
try {
expect(() => lock(name)).toThrowError(expect.objectContaining({
message: "navigator.locks is not found. required options.locks argument."
message: "navigator.locks is not found. required options.locks argument.",
}));

const { request, query } = lock(name, { locks });
Expand All @@ -265,7 +265,7 @@ describe("hard error pattern", (args) => {
clientId: expect.any(String),
mode: "exclusive",
name,
}
},
],
pending: undefined,
});
Expand All @@ -274,7 +274,8 @@ describe("hard error pattern", (args) => {
held: undefined,
pending: undefined,
});
} finally {
}
finally {
Object.defineProperty(globalThis.navigator, "locks", {
writable: true,
value: locks,
Expand All @@ -285,9 +286,9 @@ describe("hard error pattern", (args) => {

/**
* Promise base setTimeout with abort signal
* @param ms
* @param options
* @returns
* @param ms
* @param options
* @returns
*/
async function timeout(ms?: number, options?: { signal?: AbortSignal }) {
const { resolve, promise } = Promise.withResolvers<void>();
Expand All @@ -297,7 +298,8 @@ async function timeout(ms?: number, options?: { signal?: AbortSignal }) {
}
try {
return await promise;
} finally {
}
finally {
if (options?.signal) {
options.signal.removeEventListener("abort", abort);
}
Expand All @@ -310,8 +312,8 @@ async function timeout(ms?: number, options?: { signal?: AbortSignal }) {

/**
* Handle unhandledRejection event and return disposable to off the event.
* @param onUnhandledRejection
* @returns
* @param onUnhandledRejection
* @returns
*/
function unhandleRejection(onUnhandledRejection?: (reason: unknown, promise: Promise<unknown>) => void) {
onUnhandledRejection ??= () => undefined;
Expand All @@ -326,7 +328,7 @@ function unhandleRejection(onUnhandledRejection?: (reason: unknown, promise: Pro

/**
* use fake timer and return async disposable to restore real timer.
* @returns
* @returns
*/
function fakeTimeer() {
vi.useFakeTimers();
Expand All @@ -345,17 +347,16 @@ function fakeTimeer() {

/**
* describe unhandledRejection logging utility
* @param param0
* @param param0
*/
function useUnhandleRejectionLogging({ beforeEach, afterEach }
: {
beforeEach: (fn: BeforeEachListener<object>, timeout?: number) => void,
afterEach: (fn: AfterEachListener<object>, timeout?: number) => void
}) {
function useUnhandleRejectionLogging({ beforeEach, afterEach }: {
beforeEach: (fn: BeforeEachListener<object>, timeout?: number) => void
afterEach: (fn: AfterEachListener<object>, timeout?: number) => void
}) {
type HandlerInstance = {
[Symbol.dispose]: () => void,
reasones?: unknown[] | undefined,
}
[Symbol.dispose]: () => void
reasones?: unknown[] | undefined
};
const handles = new Map<string, HandlerInstance>();
beforeEach(({ task: { id } }) => {
const instance = {} as HandlerInstance;
Expand All @@ -377,4 +378,4 @@ function useUnhandleRejectionLogging({ beforeEach, afterEach }
function callback(this: HandlerInstance, reason: unknown) {
(this.reasones ??= []).push(reason);
}
}
}
4 changes: 2 additions & 2 deletions src/lock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export function lock(name: string, options?: { locks?: LockManager }) {
}
const thisArgs: InnerLock = { locks, name };
const request = originalRequest.bind(thisArgs) as {
(options: Omit<LockOptions, "ifAvailable"> & { ifAvailable: true }): Promise<ReleasableLock | null>;
(options?: Omit<LockOptions, "ifAvailable"> & { ifAvailable?: false }): Promise<ReleasableLock>;
(options: Omit<LockOptions, "ifAvailable"> & { ifAvailable: true }): Promise<ReleasableLock | null>
(options?: Omit<LockOptions, "ifAvailable"> & { ifAvailable?: false }): Promise<ReleasableLock>
};
return {
request,
Expand Down
4 changes: 2 additions & 2 deletions src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export async function request(this: InnerLock, options?: Omit<LockOptions, "ifAv
export async function request(this: InnerLock, options?: LockOptions): Promise<ReleasableLock | null> {
// #region Create resolvers to coordinate async lock lifecycle

// case1: called callback
// case1: called callback
const { resolve: callbackResolve, promise: callbackPromise } = Promise.withResolvers<Lock | null>();

// case2: called release
Expand All @@ -39,7 +39,7 @@ export async function request(this: InnerLock, options?: LockOptions): Promise<R
requestPromise
.then(
() => null,
reason => ({ reason })
reason => ({ reason }),
),
]);

Expand Down
2 changes: 1 addition & 1 deletion src/requiredAsyncDispose.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
if (typeof Symbol.asyncDispose !== "symbol") {
(Symbol as { asyncDispose: symbol }).asyncDispose = Symbol.for("Symbol.asyncDispose");
}
}
2 changes: 1 addition & 1 deletion src/types/InnerLock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
* Internal type used to bind LockManager context with the lock name.
*/

export type InnerLock = { locks: LockManager; name: string; };
export type InnerLock = { locks: LockManager, name: string };
2 changes: 1 addition & 1 deletion src/types/Releasable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
* A type representing an object that can release a lock asynchronously.
*/
export type Releasable = { release(): Promise<void>; };
export type Releasable = { release(): Promise<void> };
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export type * from "./InnerLock.ts";
export type * from "./Releasable.ts";
export type * from "./ReleasableLock.ts";
export type * from "./ReleasableLock.ts";
6 changes: 3 additions & 3 deletions utils/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ const parsed = util.parseArgs({
short: "f",
multiple: true,
},
}
},
});

const {values: {output, file}} = parsed;
const { values: { output, file } } = parsed;

if (!file || file.length <= 0) {
process.exit(0);
Expand All @@ -34,7 +34,7 @@ if (!output || output.length <= 0) {
throw new Error("required -o or --output");
}

for(const f of file) {
for (const f of file) {
const src = path.join("./", f);
const dest = path.join(output, f);

Expand Down
8 changes: 4 additions & 4 deletions utils/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ const parsed = util.parseArgs({
short: "f",
multiple: true,
},
}
},
});

const {values: {file}} = parsed;
const { values: { file } } = parsed;

if (!file || file.length <= 0) {
process.exit(0);
}

for(const f of file) {
for (const f of file) {
const exist = await fse.pathExists(f);
if (!exist) continue;
await fse.remove(f);
console.log("remove:", f);
}
}
6 changes: 3 additions & 3 deletions vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export default defineConfig({
entry: resolve(__dirname, "src/index.ts"),
name: "index",
fileName: "index",
}
}
});
},
},
});
8 changes: 4 additions & 4 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default defineConfig({
...coverageConfigDefaults.exclude,
"src/requiredAsyncDispose.ts",
"utils/**/*.ts",
]
}
}
});
],
},
},
});
Loading