open-index/open-npm huggingface dataset:
npm package: @rocicorp/lock
Description: Implements Lock and RWLock synchronization primitives.
Latest version: 1.0.4

# Lock

Provides `Lock` and `RWLock` (read write lock) synchronization primitives for
protecting in-memory state across multiple tasks and/or microtasks.

# Installation

```
npm install @rocicorp/lock
```

# Usage

`Lock` is a mutex that can be used to synchronize access to a shared resource.

```ts
import {Lock} from '@rocicorp/lock';

const lock = new Lock();

async function f(n) {
  const v = await lock.withLock(async () => {
    await sleep(1000);
    return n;
  });
  console.log(n);
}

void f(1);
void f(2);
// prints 1 at t=1000
// prints 2 at t=2000
```

`RWLock` is a read write lock. There can be mutlipe readers at the same time but only one writer at the same time.

```js
import {RWLock} from '@rocicorp/lock';

const rwLock = new RWLock();

async function read(n) {
  const v = await lock.withRead(async () => {
    await sleep(1000);
    return n;
  });
  console.log('read', n);
}

async function write(n) {
  const v = await lock.withWrite(async () => {
    await sleep(1000);
    return n;
  });
  console.log('write', n);
}

void read(1);
void write(2);
void read(3);
// prints read 1 at t=1000
// prints read 3 at t=1000
// prints write 2 at t=2000
```

Both `Lock` and `RWLock` expose non "with" methods (`lock`, `read` and `write`). These returns a promise to a release function that resolves when the lock is acquired. This is useful when you cannot wrap your code in a function like the examples above. When using these For example:

```js
const lock = new Lock();

const release = await lock.lock();
// here we got the lock
// do something
release();
```
npm package: @rocicorp/logger
Description: Logging utilities
Latest version: 5.4.0

# logger

Provides a simple logging interface as well as a `LogContext` class which
carries a context around.

# Installation

```
npm install @rocicorp/logger
```

# Usage

## LogContext

`LogContext` includes a context that gets included in the log message.

```js
import {LogContext} from '@rocicorp/logger';

const lc = new LogContext('info');
lc.info('hello'); // prints "hello"

const lc2 = new LogContext('info', {name: 'alice'});
lc.info('hello'); // prints "name=alice hello"

const lc3 = lc2.withContext('bbb');
lc3.info('hello'); // prints "name=alice bbb hello"

const lc4 = lc3.withContext('ccc');
lc4.info('hello'); // prints "name=alice bbb ccc hello"

const lc5 = lc4.withContext('ddd', 'eee');
lc5.info('hello'); // prints "name=alice bbb ccc ddd=eee hello"

// Or get a context logger appropriate for the Node environment.
const nlc = newNodeLogContext('debug');
nlc.info('fff'); // prints "INF fff"
```

## OptionalLogger

```ts
interface OptionalLogger { ... }
```

This interface is used to provide conditional logging. It is intended to be used
with conditional method calling `?.()`.

```ts
import {ConsoleLogger, type OptionalLogger} from '@rocicorp/logger';

const l: OptionalLogger = new ConsoleLogger('info');
l.info?.('hello'); // prints "hello"
l.debug?.('hello'); // does not print anything
```

But more importantly it does not evaluate the arguments.

```ts
import {ConsoleLogger, type OptionalLogger} from '@rocicorp/logger';
const alwaysThrows = () => {
  throw new Error();
};
const l: OptionalLogger = new ConsoleLogger('info');
l.debug?.(alwaysThrows()); // does not print anything, but does not throw
```

# Implementing Your Own `LogSink`

There is also the `LogSink` interface which is very minimal. Its intended use is
for custom log implementations.

```ts
class ExampleLogSink implements LogSink {
  log(level: LogLevel, ...args: unknown[]): void {
    //...
  }
}
```

You can get an `OptionalLogger` from a `LogSink` using `OptionalLoggerImpl`.

```ts
import {
  OptionalLoggerImpl,
  type LogSink,
  type OptionalLogger,
} from '@rocicorp/logger';

const logSink: LogSink = new ExampleLogSink();
const l: OptionalLogger = new OptionalLoggerImpl(logSink);
```