mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
docs: reorganize docs (#2658)
This commit is contained in:
parent
4d16c30f38
commit
aba5017d43
@ -1,63 +0,0 @@
|
||||
# Usage
|
||||
|
||||
## Tar
|
||||
|
||||
```ts
|
||||
import { Tar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
|
||||
import { Buffer } from "https://deno.land/std@$STD_VERSION/io/buffer.ts";
|
||||
import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
|
||||
|
||||
const tar = new Tar();
|
||||
const content = new TextEncoder().encode("Deno.land");
|
||||
await tar.append("deno.txt", {
|
||||
reader: new Buffer(content),
|
||||
contentSize: content.byteLength,
|
||||
});
|
||||
|
||||
// Or specifying a filePath.
|
||||
await tar.append("land.txt", {
|
||||
filePath: "./land.txt",
|
||||
});
|
||||
|
||||
// use tar.getReader() to read the contents.
|
||||
|
||||
const writer = await Deno.open("./out.tar", { write: true, create: true });
|
||||
await copy(tar.getReader(), writer);
|
||||
writer.close();
|
||||
```
|
||||
|
||||
## Untar
|
||||
|
||||
```ts
|
||||
import { Untar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
|
||||
import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/ensure_file.ts";
|
||||
import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/ensure_dir.ts";
|
||||
import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
|
||||
|
||||
const reader = await Deno.open("./out.tar", { read: true });
|
||||
const untar = new Untar(reader);
|
||||
|
||||
for await (const entry of untar) {
|
||||
console.log(entry); // metadata
|
||||
/*
|
||||
fileName: "archive/deno.txt",
|
||||
fileMode: 33204,
|
||||
mtime: 1591657305,
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
size: 24400,
|
||||
type: 'file'
|
||||
*/
|
||||
|
||||
if (entry.type === "directory") {
|
||||
await ensureDir(entry.fileName);
|
||||
continue;
|
||||
}
|
||||
|
||||
await ensureFile(entry.fileName);
|
||||
const file = await Deno.open(entry.fileName, { write: true });
|
||||
// <entry> is a reader.
|
||||
await copy(entry, file);
|
||||
}
|
||||
reader.close();
|
||||
```
|
106
archive/tar.ts
106
archive/tar.ts
@ -33,61 +33,6 @@
|
||||
* Provides a `Tar` and `Untar` classes for compressing and decompressing
|
||||
* arbitrary data.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ### Tar
|
||||
*
|
||||
* ```ts
|
||||
* import { Tar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
|
||||
* import { Buffer } from "https://deno.land/std@$STD_VERSION/io/buffer.ts";
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
|
||||
*
|
||||
* const tar = new Tar();
|
||||
* const content = new TextEncoder().encode("Deno.land");
|
||||
* await tar.append("deno.txt", {
|
||||
* reader: new Buffer(content),
|
||||
* contentSize: content.byteLength,
|
||||
* });
|
||||
*
|
||||
* // Or specifying a filePath.
|
||||
* await tar.append("land.txt", {
|
||||
* filePath: "./land.txt",
|
||||
* });
|
||||
*
|
||||
* // use tar.getReader() to read the contents.
|
||||
*
|
||||
* const writer = await Deno.open("./out.tar", { write: true, create: true });
|
||||
* await copy(tar.getReader(), writer);
|
||||
* writer.close();
|
||||
* ```
|
||||
*
|
||||
* ### Untar
|
||||
*
|
||||
* ```ts
|
||||
* import { Untar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
|
||||
* import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/ensure_file.ts";
|
||||
* import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/ensure_dir.ts";
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
|
||||
*
|
||||
* const reader = await Deno.open("./out.tar", { read: true });
|
||||
* const untar = new Untar(reader);
|
||||
*
|
||||
* for await (const entry of untar) {
|
||||
* console.log(entry); // metadata
|
||||
*
|
||||
* if (entry.type === "directory") {
|
||||
* await ensureDir(entry.fileName);
|
||||
* continue;
|
||||
* }
|
||||
*
|
||||
* await ensureFile(entry.fileName);
|
||||
* const file = await Deno.open(entry.fileName, { write: true });
|
||||
* // <entry> is a reader.
|
||||
* await copy(entry, file);
|
||||
* }
|
||||
* reader.close();
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
@ -368,6 +313,31 @@ interface TarEntry extends TarMeta {}
|
||||
|
||||
/**
|
||||
* A class to create a tar archive
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Tar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
|
||||
* import { Buffer } from "https://deno.land/std@$STD_VERSION/io/buffer.ts";
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
|
||||
*
|
||||
* const tar = new Tar();
|
||||
* const content = new TextEncoder().encode("Deno.land");
|
||||
* await tar.append("deno.txt", {
|
||||
* reader: new Buffer(content),
|
||||
* contentSize: content.byteLength,
|
||||
* });
|
||||
*
|
||||
* // Or specifying a filePath.
|
||||
* await tar.append("land.txt", {
|
||||
* filePath: "./land.txt",
|
||||
* });
|
||||
*
|
||||
* // use tar.getReader() to read the contents.
|
||||
*
|
||||
* const writer = await Deno.open("./out.tar", { write: true, create: true });
|
||||
* await copy(tar.getReader(), writer);
|
||||
* writer.close();
|
||||
* ```
|
||||
*/
|
||||
export class Tar {
|
||||
data: TarDataWithSource[];
|
||||
@ -592,6 +562,32 @@ class TarEntry implements Reader {
|
||||
|
||||
/**
|
||||
* A class to extract a tar archive
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Untar } from "https://deno.land/std@$STD_VERSION/archive/tar.ts";
|
||||
* import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/ensure_file.ts";
|
||||
* import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/ensure_dir.ts";
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/streams/conversion.ts";
|
||||
*
|
||||
* const reader = await Deno.open("./out.tar", { read: true });
|
||||
* const untar = new Untar(reader);
|
||||
*
|
||||
* for await (const entry of untar) {
|
||||
* console.log(entry); // metadata
|
||||
*
|
||||
* if (entry.type === "directory") {
|
||||
* await ensureDir(entry.fileName);
|
||||
* continue;
|
||||
* }
|
||||
*
|
||||
* await ensureFile(entry.fileName);
|
||||
* const file = await Deno.open(entry.fileName, { write: true });
|
||||
* // <entry> is a reader.
|
||||
* await copy(entry, file);
|
||||
* }
|
||||
* reader.close();
|
||||
* ```
|
||||
*/
|
||||
export class Untar {
|
||||
reader: Reader;
|
||||
|
238
async/README.md
238
async/README.md
@ -1,238 +0,0 @@
|
||||
# async
|
||||
|
||||
async is a module to provide help with asynchronous tasks.
|
||||
|
||||
# Usage
|
||||
|
||||
The following functions and class are exposed in `mod.ts`:
|
||||
|
||||
## abortable
|
||||
|
||||
The `abortable` is a wrapper function that makes `Promise` and `AsyncIterable`
|
||||
cancelable.
|
||||
|
||||
For example, in the case of `Promise`, it looks like this
|
||||
|
||||
```typescript
|
||||
import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const p = delay(1000);
|
||||
const c = new AbortController();
|
||||
setTimeout(() => c.abort(), 100);
|
||||
|
||||
// Below throws `DOMException` after 100 ms
|
||||
await abortable(p, c.signal);
|
||||
```
|
||||
|
||||
and for `AsyncIterable` as follows
|
||||
|
||||
```typescript
|
||||
import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const p = async function* () {
|
||||
yield "Hello";
|
||||
await delay(1000);
|
||||
yield "World";
|
||||
};
|
||||
const c = new AbortController();
|
||||
setTimeout(() => c.abort(), 100);
|
||||
|
||||
// Below throws `DOMException` after 100 ms
|
||||
// and items become `["Hello"]`
|
||||
const items: string[] = [];
|
||||
for await (const item of abortable(p(), c.signal)) {
|
||||
items.push(item);
|
||||
}
|
||||
```
|
||||
|
||||
## abortablePromise
|
||||
|
||||
`abortablePromise` takes the promise and `AbortSignal` and returns the
|
||||
cancelable version of the promise.
|
||||
|
||||
```typescript
|
||||
import { abortablePromise } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const request = fetch("https://example.com");
|
||||
|
||||
const c = new AbortController();
|
||||
setTimeout(() => c.abort(), 100);
|
||||
|
||||
const p = abortablePromise(request, c.signal);
|
||||
|
||||
// The below throws if the request didn't resolve in 100ms
|
||||
await p;
|
||||
```
|
||||
|
||||
## abortableAsyncIterable
|
||||
|
||||
`abortableAsyncIterable` takes the async iterable and `AbortSignal` and returns
|
||||
the cancelable version of the async iterable.
|
||||
|
||||
```typescript
|
||||
import { abortableAsyncIterable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const p = async function* () {
|
||||
yield "Hello";
|
||||
await delay(1000);
|
||||
yield "World";
|
||||
};
|
||||
const c = new AbortController();
|
||||
setTimeout(() => c.abort(), 100);
|
||||
|
||||
// Below throws `DOMException` after 100 ms
|
||||
// and items become `["Hello"]`
|
||||
const items: string[] = [];
|
||||
for await (const item of abortableAsyncIterable(p(), c.signal)) {
|
||||
items.push(item);
|
||||
}
|
||||
```
|
||||
|
||||
## debounce
|
||||
|
||||
Debounces a given function by a given time.
|
||||
|
||||
```typescript
|
||||
import { debounce } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const p = debounce(
|
||||
(value: string) =>
|
||||
console.log("Function debounced after 200ms with %s", value),
|
||||
200,
|
||||
);
|
||||
p("foo");
|
||||
p("bar");
|
||||
p("baz");
|
||||
// wait 200ms ...
|
||||
// output: Function debounced after 200ms with baz
|
||||
```
|
||||
|
||||
## deferred
|
||||
|
||||
Create a Promise with the `reject` and `resolve` functions.
|
||||
|
||||
```typescript
|
||||
import { deferred } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const p = deferred<number>();
|
||||
// ...
|
||||
p.resolve(42);
|
||||
```
|
||||
|
||||
## delay
|
||||
|
||||
Resolve a Promise after a given amount of milliseconds.
|
||||
|
||||
```typescript
|
||||
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
// ...
|
||||
const delayedPromise = delay(100);
|
||||
const result = await delayedPromise;
|
||||
// ...
|
||||
```
|
||||
|
||||
To allow the process to continue to run as long as the timer exists. Requires
|
||||
`--unstable` flag.
|
||||
|
||||
```typescript
|
||||
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
// ...
|
||||
await delay(100, { persistent: false });
|
||||
// ...
|
||||
```
|
||||
|
||||
## MuxAsyncIterator
|
||||
|
||||
The MuxAsyncIterator class multiplexes multiple async iterators into a single
|
||||
stream.
|
||||
|
||||
The class makes an assumption that the final result (the value returned and not
|
||||
yielded from the iterator) does not matter. If there is any result, it is
|
||||
discarded.
|
||||
|
||||
```typescript
|
||||
import { MuxAsyncIterator } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
async function* gen123(): AsyncIterableIterator<number> {
|
||||
yield 1;
|
||||
yield 2;
|
||||
yield 3;
|
||||
}
|
||||
|
||||
async function* gen456(): AsyncIterableIterator<number> {
|
||||
yield 4;
|
||||
yield 5;
|
||||
yield 6;
|
||||
}
|
||||
|
||||
const mux = new MuxAsyncIterator<number>();
|
||||
mux.add(gen123());
|
||||
mux.add(gen456());
|
||||
for await (const value of mux) {
|
||||
// ...
|
||||
}
|
||||
// ..
|
||||
```
|
||||
|
||||
## pooledMap
|
||||
|
||||
Transform values from an (async) iterable into another async iterable. The
|
||||
transforms are done concurrently, with a max concurrency defined by the
|
||||
poolLimit.
|
||||
|
||||
```typescript
|
||||
import { pooledMap } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const results = pooledMap(
|
||||
2,
|
||||
[1, 2, 3],
|
||||
(i) => new Promise((r) => setTimeout(() => r(i), 1000)),
|
||||
);
|
||||
|
||||
for await (const value of results) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## tee
|
||||
|
||||
Branches the given async iterable into the n branches.
|
||||
|
||||
```typescript
|
||||
import { tee } from "https://deno.land/std@$STD_VERSION/async/tee.ts";
|
||||
|
||||
const gen = async function* gen() {
|
||||
yield 1;
|
||||
yield 2;
|
||||
yield 3;
|
||||
};
|
||||
|
||||
const [branch1, branch2] = tee(gen());
|
||||
|
||||
for await (const n of branch1) {
|
||||
console.log(n); // => 1, 2, 3
|
||||
}
|
||||
|
||||
for await (const n of branch2) {
|
||||
console.log(n); // => 1, 2, 3
|
||||
}
|
||||
```
|
||||
|
||||
## deadline
|
||||
|
||||
Create a promise which will be rejected with `DeadlineError` when a given delay
|
||||
is exceeded.
|
||||
|
||||
```typescript
|
||||
import { deadline } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
|
||||
const delayedPromise = delay(1000);
|
||||
// Below throws `DeadlineError` after 10 ms
|
||||
const result = await deadline(delayedPromise, 10);
|
||||
```
|
@ -1,8 +1,47 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { deferred } from "./deferred.ts";
|
||||
|
||||
/** Make Promise or AsyncIterable abortable with the given signal. */
|
||||
/**
|
||||
* Make Promise abortable with the given signal.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
*
|
||||
* const p = delay(1000);
|
||||
* const c = new AbortController();
|
||||
* setTimeout(() => c.abort(), 100);
|
||||
*
|
||||
* // Below throws `DOMException` after 100 ms
|
||||
* await abortable(p, c.signal);
|
||||
* ```
|
||||
*/
|
||||
export function abortable<T>(p: Promise<T>, signal: AbortSignal): Promise<T>;
|
||||
/**
|
||||
* Make AsyncIterable abortable with the given signal.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { abortable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
*
|
||||
* const p = async function* () {
|
||||
* yield "Hello";
|
||||
* await delay(1000);
|
||||
* yield "World";
|
||||
* };
|
||||
* const c = new AbortController();
|
||||
* setTimeout(() => c.abort(), 100);
|
||||
*
|
||||
* // Below throws `DOMException` after 100 ms
|
||||
* // and items become `["Hello"]`
|
||||
* const items: string[] = [];
|
||||
* for await (const item of abortable(p(), c.signal)) {
|
||||
* items.push(item);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function abortable<T>(
|
||||
p: AsyncIterable<T>,
|
||||
signal: AbortSignal,
|
||||
@ -18,7 +57,24 @@ export function abortable<T>(
|
||||
}
|
||||
}
|
||||
|
||||
/** Make Promise abortable with the given signal. */
|
||||
/**
|
||||
* Make Promise abortable with the given signal.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { abortablePromise } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
*
|
||||
* const request = fetch("https://example.com");
|
||||
*
|
||||
* const c = new AbortController();
|
||||
* setTimeout(() => c.abort(), 100);
|
||||
*
|
||||
* const p = abortablePromise(request, c.signal);
|
||||
*
|
||||
* // The below throws if the request didn't resolve in 100ms
|
||||
* await p;
|
||||
* ```
|
||||
*/
|
||||
export function abortablePromise<T>(
|
||||
p: Promise<T>,
|
||||
signal: AbortSignal,
|
||||
@ -37,7 +93,30 @@ export function abortablePromise<T>(
|
||||
]);
|
||||
}
|
||||
|
||||
/** Make AsyncIterable abortable with the given signal. */
|
||||
/**
|
||||
* Make AsyncIterable abortable with the given signal.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { abortableAsyncIterable } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
* import { delay } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
*
|
||||
* const p = async function* () {
|
||||
* yield "Hello";
|
||||
* await delay(1000);
|
||||
* yield "World";
|
||||
* };
|
||||
* const c = new AbortController();
|
||||
* setTimeout(() => c.abort(), 100);
|
||||
*
|
||||
* // Below throws `DOMException` after 100 ms
|
||||
* // and items become `["Hello"]`
|
||||
* const items: string[] = [];
|
||||
* for await (const item of abortableAsyncIterable(p(), c.signal)) {
|
||||
* items.push(item);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export async function* abortableAsyncIterable<T>(
|
||||
p: AsyncIterable<T>,
|
||||
signal: AbortSignal,
|
||||
|
@ -11,7 +11,17 @@ export class DeadlineError extends Error {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a promise which will be rejected with DeadlineError when a given delay is exceeded.
|
||||
* Create a promise which will be rejected with {@linkcode DeadlineError} when a given delay is exceeded.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { deadline } from "https://deno.land/std@$STD_VERSION/async/deadline.ts";
|
||||
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
|
||||
*
|
||||
* const delayedPromise = delay(1000);
|
||||
* // Below throws `DeadlineError` after 10 ms
|
||||
* const result = await deadline(delayedPromise, 10);
|
||||
* ```
|
||||
*/
|
||||
export function deadline<T>(p: Promise<T>, delay: number): Promise<T> {
|
||||
const d = deferred<never>();
|
||||
|
@ -12,7 +12,7 @@ export interface DebouncedFunction<T extends Array<unknown>> {
|
||||
clear(): void;
|
||||
/** Clears the debounce timeout and calls the debounced function immediately. */
|
||||
flush(): void;
|
||||
/** Returns a boolean wether a debounce call is pending or not. */
|
||||
/** Returns a boolean whether a debounce call is pending or not. */
|
||||
readonly pending: boolean;
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ export interface DebouncedFunction<T extends Array<unknown>> {
|
||||
* again before the timeout expires, the previous call will be
|
||||
* aborted.
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* import { debounce } from "https://deno.land/std@$STD_VERSION/async/debounce.ts";
|
||||
*
|
||||
@ -34,6 +35,8 @@ export interface DebouncedFunction<T extends Array<unknown>> {
|
||||
* for await (const event of Deno.watchFs("./")) {
|
||||
* log(event);
|
||||
* }
|
||||
* // wait 200ms ...
|
||||
* // output: Function debounced after 200ms with baz
|
||||
* ```
|
||||
*
|
||||
* @param fn The function to debounce.
|
||||
|
@ -13,15 +13,17 @@ export interface Deferred<T> extends Promise<T> {
|
||||
reject(reason?: any): void;
|
||||
}
|
||||
|
||||
/** Creates a Promise with the `reject` and `resolve` functions
|
||||
* placed as methods on the promise object itself. It allows you to do:
|
||||
/**
|
||||
* Creates a Promise with the `reject` and `resolve` functions placed as methods
|
||||
* on the promise object itself.
|
||||
*
|
||||
* ```ts
|
||||
* import { deferred } from "https://deno.land/std@$STD_VERSION/async/deferred.ts";
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { deferred } from "https://deno.land/std@$STD_VERSION/async/deferred.ts";
|
||||
*
|
||||
* const p = deferred<number>();
|
||||
* // ...
|
||||
* p.resolve(42);
|
||||
* const p = deferred<number>();
|
||||
* // ...
|
||||
* p.resolve(42);
|
||||
* ```
|
||||
*/
|
||||
export function deferred<T>(): Deferred<T> {
|
||||
|
@ -2,12 +2,40 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
export interface DelayOptions {
|
||||
/** Signal used to abort the delay. */
|
||||
signal?: AbortSignal;
|
||||
/** Indicates whether the process should continue to run as long as the timer exists. This is `true` by default. */
|
||||
/** Indicates whether the process should continue to run as long as the timer exists.
|
||||
*
|
||||
* @default {true}
|
||||
*/
|
||||
persistent?: boolean;
|
||||
}
|
||||
|
||||
/* Resolves after the given number of milliseconds. */
|
||||
/**
|
||||
* Resolve a Promise after a given amount of milliseconds.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ```typescript
|
||||
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
|
||||
*
|
||||
* // ...
|
||||
* const delayedPromise = delay(100);
|
||||
* const result = await delayedPromise;
|
||||
* // ...
|
||||
* ```
|
||||
*
|
||||
* To allow the process to continue to run as long as the timer exists. Requires
|
||||
* `--unstable` flag.
|
||||
*
|
||||
* ```typescript
|
||||
* import { delay } from "https://deno.land/std@$STD_VERSION/async/delay.ts";
|
||||
*
|
||||
* // ...
|
||||
* await delay(100, { persistent: false });
|
||||
* // ...
|
||||
* ```
|
||||
*/
|
||||
export function delay(ms: number, options: DelayOptions = {}): Promise<void> {
|
||||
const { signal, persistent } = options;
|
||||
if (signal?.aborted) {
|
||||
|
@ -8,10 +8,36 @@ interface TaggedYieldedValue<T> {
|
||||
value: T;
|
||||
}
|
||||
|
||||
/** The MuxAsyncIterator class multiplexes multiple async iterators into a
|
||||
* single stream. It currently makes an assumption:
|
||||
* - The final result (the value returned and not yielded from the iterator)
|
||||
* does not matter; if there is any, it is discarded.
|
||||
/**
|
||||
* The MuxAsyncIterator class multiplexes multiple async iterators into a single
|
||||
* stream. It currently makes an assumption that the final result (the value
|
||||
* returned and not yielded from the iterator) does not matter; if there is any
|
||||
* result, it is discarded.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { MuxAsyncIterator } from "https://deno.land/std@$STD_VERSION/async/mod.ts";
|
||||
*
|
||||
* async function* gen123(): AsyncIterableIterator<number> {
|
||||
* yield 1;
|
||||
* yield 2;
|
||||
* yield 3;
|
||||
* }
|
||||
*
|
||||
* async function* gen456(): AsyncIterableIterator<number> {
|
||||
* yield 4;
|
||||
* yield 5;
|
||||
* yield 6;
|
||||
* }
|
||||
*
|
||||
* const mux = new MuxAsyncIterator<number>();
|
||||
* mux.add(gen123());
|
||||
* mux.add(gen456());
|
||||
* for await (const value of mux) {
|
||||
* // ...
|
||||
* }
|
||||
* // ..
|
||||
* ```
|
||||
*/
|
||||
export class MuxAsyncIterator<T> implements AsyncIterable<T> {
|
||||
#iteratorCount = 0;
|
||||
|
@ -12,6 +12,21 @@ export const ERROR_WHILE_MAPPING_MESSAGE = "Threw while mapping.";
|
||||
* yielded on success. After that, the rejections among them are gathered and
|
||||
* thrown by the iterator in an `AggregateError`.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { pooledMap } from "https://deno.land/std@$STD_VERSION/async/pool.ts";
|
||||
*
|
||||
* const results = pooledMap(
|
||||
* 2,
|
||||
* [1, 2, 3],
|
||||
* (i) => new Promise((r) => setTimeout(() => r(i), 1000)),
|
||||
* );
|
||||
*
|
||||
* for await (const value of results) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param poolLimit The maximum count of items being processed concurrently.
|
||||
* @param array The input array for mapping.
|
||||
* @param iteratorFn The function to call for every item of the array.
|
||||
|
29
async/tee.ts
29
async/tee.ts
@ -49,26 +49,25 @@ class Queue<T> {
|
||||
/**
|
||||
* Branches the given async iterable into the n branches.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { tee } from "https://deno.land/std@$STD_VERSION/async/tee.ts";
|
||||
* import { tee } from "https://deno.land/std@$STD_VERSION/async/tee.ts";
|
||||
*
|
||||
* const gen = async function* gen() {
|
||||
* yield 1;
|
||||
* yield 2;
|
||||
* yield 3;
|
||||
* }
|
||||
* const gen = async function* gen() {
|
||||
* yield 1;
|
||||
* yield 2;
|
||||
* yield 3;
|
||||
* };
|
||||
*
|
||||
* const [branch1, branch2] = tee(gen());
|
||||
* const [branch1, branch2] = tee(gen());
|
||||
*
|
||||
* for await (const n of branch1) {
|
||||
* console.log(n); // => 1, 2, 3
|
||||
* }
|
||||
* for await (const n of branch1) {
|
||||
* console.log(n); // => 1, 2, 3
|
||||
* }
|
||||
*
|
||||
* for await (const n of branch2) {
|
||||
* console.log(n); // => 1, 2, 3
|
||||
* }
|
||||
* for await (const n of branch2) {
|
||||
* console.log(n); // => 1, 2, 3
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function tee<T, N extends number = 2>(
|
||||
|
@ -1,8 +0,0 @@
|
||||
# Bytes
|
||||
|
||||
The bytes module provides helper functions to manipulate `Uint8Array` byte
|
||||
slices that are not included on the `Uint8Array` prototype.
|
||||
|
||||
View the
|
||||
[documentation](https://doc.deno.land/https://deno.land/std@$STD_VERSION/bytes/mod.ts)
|
||||
for details information.
|
File diff suppressed because it is too large
Load Diff
@ -4,29 +4,33 @@
|
||||
import { mapEntries } from "./map_entries.ts";
|
||||
|
||||
/**
|
||||
* Applies the given aggregator to each group in the given Grouping, returning the results together with the respective group keys
|
||||
* Applies the given aggregator to each group in the given grouping, returning the
|
||||
* results together with the respective group keys
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { aggregateGroups } from "https://deno.land/std@$STD_VERSION/collections/aggregate_groups.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const foodProperties = {
|
||||
* 'Curry': [ 'spicy', 'vegan' ],
|
||||
* 'Omelette': [ 'creamy', 'vegetarian' ],
|
||||
* }
|
||||
* const descriptions = aggregateGroups(foodProperties,
|
||||
* (current, key, first, acc) => {
|
||||
* if (first)
|
||||
* return `${key} is ${current}`
|
||||
* "Curry": ["spicy", "vegan"],
|
||||
* "Omelette": ["creamy", "vegetarian"],
|
||||
* };
|
||||
* const descriptions = aggregateGroups(
|
||||
* foodProperties,
|
||||
* (current, key, first, acc) => {
|
||||
* if (first) {
|
||||
* return `${key} is ${current}`;
|
||||
* }
|
||||
*
|
||||
* return `${acc} and ${current}`
|
||||
* },
|
||||
* )
|
||||
* return `${acc} and ${current}`;
|
||||
* },
|
||||
* );
|
||||
*
|
||||
* assertEquals(descriptions, {
|
||||
* 'Curry': 'Curry is spicy and vegan',
|
||||
* 'Omelette': 'Omelette is creamy and vegetarian',
|
||||
* })
|
||||
* "Curry": "Curry is spicy and vegan",
|
||||
* "Omelette": "Omelette is creamy and vegetarian",
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function aggregateGroups<T, A>(
|
||||
|
@ -2,28 +2,27 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Transforms the given array into a Record, extracting the key of each element using the given selector.
|
||||
* If the selector produces the same key for multiple elements, the latest one will be used (overriding the
|
||||
* ones before it).
|
||||
*
|
||||
* Example:
|
||||
* Transforms the given array into a Record, extracting the key of each element
|
||||
* using the given selector. If the selector produces the same key for multiple
|
||||
* elements, the latest one will be used (overriding the ones before it).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { associateBy } from "https://deno.land/std@$STD_VERSION/collections/associate_by.ts"
|
||||
* import { associateBy } from "https://deno.land/std@$STD_VERSION/collections/associate_by.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const users = [
|
||||
* { id: 'a2e', userName: 'Anna' },
|
||||
* { id: '5f8', userName: 'Arnold' },
|
||||
* { id: 'd2c', userName: 'Kim' },
|
||||
* ]
|
||||
* const usersById = associateBy(users, it => it.id)
|
||||
* { id: "a2e", userName: "Anna" },
|
||||
* { id: "5f8", userName: "Arnold" },
|
||||
* { id: "d2c", userName: "Kim" },
|
||||
* ];
|
||||
* const usersById = associateBy(users, (it) => it.id);
|
||||
*
|
||||
* assertEquals(usersById, {
|
||||
* 'a2e': { id: 'a2e', userName: 'Anna' },
|
||||
* '5f8': { id: '5f8', userName: 'Arnold' },
|
||||
* 'd2c': { id: 'd2c', userName: 'Kim' },
|
||||
* })
|
||||
* "a2e": { id: "a2e", userName: "Anna" },
|
||||
* "5f8": { id: "5f8", userName: "Arnold" },
|
||||
* "d2c": { id: "d2c", userName: "Kim" },
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function associateBy<T>(
|
||||
|
@ -2,24 +2,23 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Builds a new Record using the given array as keys and choosing a value for each
|
||||
* key using the given selector. If any of two pairs would have the same value
|
||||
* the latest on will be used (overriding the ones before it).
|
||||
*
|
||||
* Example:
|
||||
* Builds a new Record using the given array as keys and choosing a value for
|
||||
* each key using the given selector. If any of two pairs would have the same
|
||||
* value the latest on will be used (overriding the ones before it).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { associateWith } from "https://deno.land/std@$STD_VERSION/collections/associate_with.ts"
|
||||
* import { associateWith } from "https://deno.land/std@$STD_VERSION/collections/associate_with.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const names = [ 'Kim', 'Lara', 'Jonathan' ]
|
||||
* const namesToLength = associateWith(names, it => it.length)
|
||||
* const names = ["Kim", "Lara", "Jonathan"];
|
||||
* const namesToLength = associateWith(names, (it) => it.length);
|
||||
*
|
||||
* assertEquals(namesToLength, {
|
||||
* 'Kim': 3,
|
||||
* 'Lara': 4,
|
||||
* 'Jonathan': 8,
|
||||
* })
|
||||
* "Kim": 3,
|
||||
* "Lara": 4,
|
||||
* "Jonathan": 8,
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function associateWith<T>(
|
||||
|
@ -17,8 +17,46 @@ function getParentIndex(index: number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A priority queue implemented with a binary heap. The heap is in decending order by default,
|
||||
* using JavaScript's built in comparison operators to sort the values.
|
||||
* A priority queue implemented with a binary heap. The heap is in descending
|
||||
* order by default, using JavaScript's built-in comparison operators to sort
|
||||
* the values.
|
||||
*
|
||||
* | Method | Average Case | Worst Case |
|
||||
* | ----------- | ------------ | ---------- |
|
||||
* | peek() | O(1) | O(1) |
|
||||
* | pop() | O(log n) | O(log n) |
|
||||
* | push(value) | O(1) | O(log n) |
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* ascend,
|
||||
* BinaryHeap,
|
||||
* descend,
|
||||
* } from "https://deno.land/std@$STD_VERSION/collections/binary_heap.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const maxHeap = new BinaryHeap<number>();
|
||||
* maxHeap.push(4, 1, 3, 5, 2);
|
||||
* assertEquals(maxHeap.peek(), 5);
|
||||
* assertEquals(maxHeap.pop(), 5);
|
||||
* assertEquals([...maxHeap], [4, 3, 2, 1]);
|
||||
* assertEquals([...maxHeap], []);
|
||||
*
|
||||
* const minHeap = new BinaryHeap<number>(ascend);
|
||||
* minHeap.push(4, 1, 3, 5, 2);
|
||||
* assertEquals(minHeap.peek(), 1);
|
||||
* assertEquals(minHeap.pop(), 1);
|
||||
* assertEquals([...minHeap], [2, 3, 4, 5]);
|
||||
* assertEquals([...minHeap], []);
|
||||
*
|
||||
* const words = new BinaryHeap<string>((a, b) => descend(a.length, b.length));
|
||||
* words.push("truck", "car", "helicopter", "tank");
|
||||
* assertEquals(words.peek(), "helicopter");
|
||||
* assertEquals(words.pop(), "helicopter");
|
||||
* assertEquals([...words], ["truck", "tank", "car"]);
|
||||
* assertEquals([...words], []);
|
||||
* ```
|
||||
*/
|
||||
export class BinaryHeap<T> implements Iterable<T> {
|
||||
#data: T[] = [];
|
||||
|
@ -7,7 +7,84 @@ export * from "./_comparators.ts";
|
||||
|
||||
/**
|
||||
* An unbalanced binary search tree. The values are in ascending order by default,
|
||||
* using JavaScript's built in comparison operators to sort the values.
|
||||
* using JavaScript's built-in comparison operators to sort the values.
|
||||
*
|
||||
* For performance, it's recommended that you use a self-balancing binary search
|
||||
* tree instead of this one unless you are extending this to create a
|
||||
* self-balancing tree. See RedBlackTree for an example of how BinarySearchTree
|
||||
* can be extended to create a self-balancing binary search tree.
|
||||
*
|
||||
* | Method | Average Case | Worst Case |
|
||||
* | ------------- | ------------ | ---------- |
|
||||
* | find(value) | O(log n) | O(n) |
|
||||
* | insert(value) | O(log n) | O(n) |
|
||||
* | remove(value) | O(log n) | O(n) |
|
||||
* | min() | O(log n) | O(n) |
|
||||
* | max() | O(log n) | O(n) |
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* ascend,
|
||||
* BinarySearchTree,
|
||||
* descend,
|
||||
* } from "https://deno.land/std@$STD_VERSION/collections/binary_search_tree.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const values = [3, 10, 13, 4, 6, 7, 1, 14];
|
||||
* const tree = new BinarySearchTree<number>();
|
||||
* values.forEach((value) => tree.insert(value));
|
||||
* assertEquals([...tree], [1, 3, 4, 6, 7, 10, 13, 14]);
|
||||
* assertEquals(tree.min(), 1);
|
||||
* assertEquals(tree.max(), 14);
|
||||
* assertEquals(tree.find(42), null);
|
||||
* assertEquals(tree.find(7), 7);
|
||||
* assertEquals(tree.remove(42), false);
|
||||
* assertEquals(tree.remove(7), true);
|
||||
* assertEquals([...tree], [1, 3, 4, 6, 10, 13, 14]);
|
||||
*
|
||||
* const invertedTree = new BinarySearchTree<number>(descend);
|
||||
* values.forEach((value) => invertedTree.insert(value));
|
||||
* assertEquals([...invertedTree], [14, 13, 10, 7, 6, 4, 3, 1]);
|
||||
* assertEquals(invertedTree.min(), 14);
|
||||
* assertEquals(invertedTree.max(), 1);
|
||||
* assertEquals(invertedTree.find(42), null);
|
||||
* assertEquals(invertedTree.find(7), 7);
|
||||
* assertEquals(invertedTree.remove(42), false);
|
||||
* assertEquals(invertedTree.remove(7), true);
|
||||
* assertEquals([...invertedTree], [14, 13, 10, 6, 4, 3, 1]);
|
||||
*
|
||||
* const words = new BinarySearchTree<string>((a, b) =>
|
||||
* ascend(a.length, b.length) || ascend(a, b)
|
||||
* );
|
||||
* ["truck", "car", "helicopter", "tank", "train", "suv", "semi", "van"]
|
||||
* .forEach((value) => words.insert(value));
|
||||
* assertEquals([...words], [
|
||||
* "car",
|
||||
* "suv",
|
||||
* "van",
|
||||
* "semi",
|
||||
* "tank",
|
||||
* "train",
|
||||
* "truck",
|
||||
* "helicopter",
|
||||
* ]);
|
||||
* assertEquals(words.min(), "car");
|
||||
* assertEquals(words.max(), "helicopter");
|
||||
* assertEquals(words.find("scooter"), null);
|
||||
* assertEquals(words.find("tank"), "tank");
|
||||
* assertEquals(words.remove("scooter"), false);
|
||||
* assertEquals(words.remove("tank"), true);
|
||||
* assertEquals([...words], [
|
||||
* "car",
|
||||
* "suv",
|
||||
* "van",
|
||||
* "semi",
|
||||
* "train",
|
||||
* "truck",
|
||||
* "helicopter",
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
export class BinarySearchTree<T> implements Iterable<T> {
|
||||
protected root: BinarySearchNode<T> | null = null;
|
||||
|
@ -2,22 +2,32 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Splits the given array into chunks of the given size and returns them
|
||||
*
|
||||
* Example:
|
||||
* Splits the given array into chunks of the given size and returns them.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { chunk } from "https://deno.land/std@$STD_VERSION/collections/chunk.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const words = [ 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consetetur', 'sadipscing' ]
|
||||
* const chunks = chunk(words, 3)
|
||||
* const words = [
|
||||
* "lorem",
|
||||
* "ipsum",
|
||||
* "dolor",
|
||||
* "sit",
|
||||
* "amet",
|
||||
* "consetetur",
|
||||
* "sadipscing",
|
||||
* ];
|
||||
* const chunks = chunk(words, 3);
|
||||
*
|
||||
* assertEquals(chunks, [
|
||||
* [ 'lorem', 'ipsum', 'dolor' ],
|
||||
* [ 'sit', 'amet', 'consetetur' ],
|
||||
* [ 'sadipscing' ],
|
||||
* ])
|
||||
* assertEquals(
|
||||
* chunks,
|
||||
* [
|
||||
* ["lorem", "ipsum", "dolor"],
|
||||
* ["sit", "amet", "consetetur"],
|
||||
* ["sadipscing"],
|
||||
* ],
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function chunk<T>(array: readonly T[], size: number): T[][] {
|
||||
|
@ -8,23 +8,22 @@ import { filterInPlace } from "./_utils.ts";
|
||||
const { hasOwn } = Object;
|
||||
|
||||
/**
|
||||
* Merges the two given Records, recursively merging any nested Records with
|
||||
* the second collection overriding the first in case of conflict
|
||||
* Merges the two given Records, recursively merging any nested Records with the
|
||||
* second collection overriding the first in case of conflict
|
||||
*
|
||||
* For arrays, maps and sets, a merging strategy can be specified to either
|
||||
* "replace" values, or "merge" them instead.
|
||||
* Use "includeNonEnumerable" option to include non enumerable properties too.
|
||||
*
|
||||
* Example:
|
||||
* `replace` values, or `merge` them instead. Use `includeNonEnumerable` option
|
||||
* to include non-enumerable properties too.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { deepMerge } from "https://deno.land/std@$STD_VERSION/collections/deep_merge.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const a = {foo: true}
|
||||
* const b = {foo: {bar: true}}
|
||||
* const a = { foo: true };
|
||||
* const b = { foo: { bar: true } };
|
||||
*
|
||||
* assertEquals(deepMerge(a, b), {foo: {bar: true}});
|
||||
* assertEquals(deepMerge(a, b), { foo: { bar: true } });
|
||||
* ```
|
||||
*/
|
||||
export function deepMerge<
|
||||
|
@ -2,18 +2,18 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns all distinct elements in the given array, preserving order by first occurrence
|
||||
*
|
||||
* Example:
|
||||
* Returns all distinct elements in the given array, preserving order by first
|
||||
* occurrence.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { distinct } from "https://deno.land/std@$STD_VERSION/collections/distinct.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const numbers = [ 3, 2, 5, 2, 5 ]
|
||||
* const distinctNumbers = distinct(numbers)
|
||||
* const numbers = [3, 2, 5, 2, 5];
|
||||
* const distinctNumbers = distinct(numbers);
|
||||
*
|
||||
* assertEquals(distinctNumbers, [ 3, 2, 5 ])
|
||||
* assertEquals(distinctNumbers, [3, 2, 5]);
|
||||
* ```
|
||||
*/
|
||||
export function distinct<T>(array: readonly T[]): T[] {
|
||||
|
@ -2,18 +2,18 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns all elements in the given array that produce a distinct value using the given selector, preserving order by first occurrence
|
||||
*
|
||||
* Example:
|
||||
* Returns all elements in the given array that produce a distinct value using
|
||||
* the given selector, preserving order by first occurrence.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { distinctBy } from "https://deno.land/std@$STD_VERSION/collections/distinct_by.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const names = [ 'Anna', 'Kim', 'Arnold', 'Kate' ]
|
||||
* const exampleNamesByFirstLetter = distinctBy(names, it => it.charAt(0))
|
||||
* const names = ["Anna", "Kim", "Arnold", "Kate"];
|
||||
* const exampleNamesByFirstLetter = distinctBy(names, (it) => it.charAt(0));
|
||||
*
|
||||
* assertEquals(exampleNamesByFirstLetter, [ 'Anna', 'Kim' ])
|
||||
* assertEquals(exampleNamesByFirstLetter, ["Anna", "Kim"]);
|
||||
* ```
|
||||
*/
|
||||
export function distinctBy<T, D>(
|
||||
|
@ -5,18 +5,18 @@
|
||||
* Returns a new array that drops all elements in the given collection until the
|
||||
* last element that does not match the given predicate
|
||||
*
|
||||
* Example:
|
||||
* @example
|
||||
* ```ts
|
||||
* import { dropLastWhile } from "https://deno.land/std@$STD_VERSION/collections/drop_last_while.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const numbers = [22, 30, 44];
|
||||
*
|
||||
* const notFortyFour = dropLastWhile(numbers, i => i != 44);
|
||||
* const notFortyFour = dropLastWhile(numbers, (i) => i != 44);
|
||||
*
|
||||
* assertEquals(
|
||||
* notFortyFour,
|
||||
* [22, 30]
|
||||
* [22, 30],
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
|
@ -3,18 +3,17 @@
|
||||
|
||||
/**
|
||||
* Returns a new array that drops all elements in the given collection until the
|
||||
* first element that does not match the given predicate
|
||||
*
|
||||
* Example:
|
||||
* first element that does not match the given predicate.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { dropWhile } from "https://deno.land/std@$STD_VERSION/collections/drop_while.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const numbers = [ 3, 2, 5, 2, 5 ]
|
||||
* const dropWhileNumbers = dropWhile(numbers, i => i !== 2)
|
||||
* const numbers = [3, 2, 5, 2, 5];
|
||||
* const dropWhileNumbers = dropWhile(numbers, (i) => i !== 2);
|
||||
*
|
||||
* assertEquals(dropWhileNumbers, [2, 5, 2, 5 ])
|
||||
* assertEquals(dropWhileNumbers, [2, 5, 2, 5]);
|
||||
* ```
|
||||
*/
|
||||
export function dropWhile<T>(
|
||||
|
@ -2,26 +2,30 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns a new record with all entries of the given record except the ones that do not match the given predicate
|
||||
*
|
||||
* Example:
|
||||
* Returns a new record with all entries of the given record except the ones
|
||||
* that do not match the given predicate.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { filterEntries } from "https://deno.land/std@$STD_VERSION/collections/filter_entries.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const menu = {
|
||||
* 'Salad': 11,
|
||||
* 'Soup': 8,
|
||||
* 'Pasta': 13,
|
||||
* "Salad": 11,
|
||||
* "Soup": 8,
|
||||
* "Pasta": 13,
|
||||
* } as const;
|
||||
* const myOptions = filterEntries(menu,
|
||||
* ([ item, price ]) => item !== 'Pasta' && price < 10,
|
||||
* )
|
||||
* const myOptions = filterEntries(
|
||||
* menu,
|
||||
* ([item, price]) => item !== "Pasta" && price < 10,
|
||||
* );
|
||||
*
|
||||
* assertEquals(myOptions, {
|
||||
* 'Soup': 8,
|
||||
* })
|
||||
* assertEquals(
|
||||
* myOptions,
|
||||
* {
|
||||
* "Soup": 8,
|
||||
* },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function filterEntries<T>(
|
||||
|
@ -2,25 +2,28 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns a new record with all entries of the given record except the ones that have a key that does not match the given predicate
|
||||
*
|
||||
* Example:
|
||||
* Returns a new record with all entries of the given record except the ones that
|
||||
* have a key that does not match the given predicate.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { filterKeys } from "https://deno.land/std@$STD_VERSION/collections/filter_keys.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const menu = {
|
||||
* 'Salad': 11,
|
||||
* 'Soup': 8,
|
||||
* 'Pasta': 13,
|
||||
* }
|
||||
* const menuWithoutSalad = filterKeys(menu, it => it !== 'Salad')
|
||||
* "Salad": 11,
|
||||
* "Soup": 8,
|
||||
* "Pasta": 13,
|
||||
* };
|
||||
* const menuWithoutSalad = filterKeys(menu, (it) => it !== "Salad");
|
||||
*
|
||||
* assertEquals(menuWithoutSalad, {
|
||||
* 'Soup': 8,
|
||||
* 'Pasta': 13,
|
||||
* })
|
||||
* assertEquals(
|
||||
* menuWithoutSalad,
|
||||
* {
|
||||
* "Soup": 8,
|
||||
* "Pasta": 13,
|
||||
* },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function filterKeys<T>(
|
||||
|
@ -2,27 +2,28 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns a new record with all entries of the given record except the ones that have a value that does not match the given predicate
|
||||
*
|
||||
* Example:
|
||||
* Returns a new record with all entries of the given record except the ones
|
||||
* that have a value that does not match the given predicate.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { filterValues } from "https://deno.land/std@$STD_VERSION/collections/filter_values.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* type Person = { age: number };
|
||||
*
|
||||
* const people: Record<string, Person> = {
|
||||
* 'Arnold': { age: 37 },
|
||||
* 'Sarah': { age: 7 },
|
||||
* 'Kim': { age: 23 },
|
||||
* const people = {
|
||||
* "Arnold": 37,
|
||||
* "Sarah": 7,
|
||||
* "Kim": 23,
|
||||
* };
|
||||
* const adults = filterValues(people, it => it.age >= 18)
|
||||
* const adults = filterValues(people, (it) => it >= 18);
|
||||
*
|
||||
* assertEquals(adults, {
|
||||
* 'Arnold': { age: 37 },
|
||||
* 'Kim': { age: 23 },
|
||||
* })
|
||||
* assertEquals(
|
||||
* adults,
|
||||
* {
|
||||
* "Arnold": 37,
|
||||
* "Kim": 23,
|
||||
* },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function filterValues<T>(
|
||||
|
@ -2,18 +2,18 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns an element if and only if that element is the only one matching the given condition. Returns `undefined` otherwise.
|
||||
*
|
||||
* Example:
|
||||
* Returns an element if and only if that element is the only one matching the
|
||||
* given condition. Returns `undefined` otherwise.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { findSingle } from "https://deno.land/std@$STD_VERSION/collections/find_single.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const bookings = [
|
||||
* { month: 'January', active: false },
|
||||
* { month: 'March', active: false },
|
||||
* { month: 'June', active: true },
|
||||
* { month: "January", active: false },
|
||||
* { month: "March", active: false },
|
||||
* { month: "June", active: true },
|
||||
* ];
|
||||
* const activeBooking = findSingle(bookings, (it) => it.active);
|
||||
* const inactiveBooking = findSingle(bookings, (it) => !it.active);
|
||||
|
@ -2,23 +2,23 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Applies the given selector to elements in the given array until a value is produced that is neither `null` nor `undefined` and returns that value
|
||||
* Returns `undefined` if no such value is produced
|
||||
*
|
||||
* Example:
|
||||
* Applies the given selector to elements in the given array until a value is
|
||||
* produced that is neither `null` nor `undefined` and returns that value.
|
||||
* Returns `undefined` if no such value is produced.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { firstNotNullishOf } from "https://deno.land/std@$STD_VERSION/collections/first_not_nullish_of.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const tables = [
|
||||
* { number: 11, order: null },
|
||||
* { number: 12, order: 'Soup' },
|
||||
* { number: 13, order: 'Salad' },
|
||||
* ]
|
||||
* const nextOrder = firstNotNullishOf(tables, it => it.order)
|
||||
* { number: 11, order: null },
|
||||
* { number: 12, order: "Soup" },
|
||||
* { number: 13, order: "Salad" },
|
||||
* ];
|
||||
* const nextOrder = firstNotNullishOf(tables, (it) => it.order);
|
||||
*
|
||||
* assertEquals(nextOrder, 'Soup')
|
||||
* assertEquals(nextOrder, "Soup");
|
||||
* ```
|
||||
*/
|
||||
export function firstNotNullishOf<T, O>(
|
||||
|
@ -2,30 +2,29 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Applies the given selector to each element in the given array, returning a Record containing the results as keys
|
||||
* and all values that produced that key as values.
|
||||
*
|
||||
* Example:
|
||||
* Applies the given selector to each element in the given array, returning a
|
||||
* Record containing the results as keys and all values that produced that key
|
||||
* as values.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { groupBy } from "https://deno.land/std@$STD_VERSION/collections/group_by.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* type Person = {
|
||||
* name: string;
|
||||
* };
|
||||
*
|
||||
* const people: Person[] = [
|
||||
* { name: 'Anna' },
|
||||
* { name: 'Arnold' },
|
||||
* { name: 'Kim' },
|
||||
* const people = [
|
||||
* { name: "Anna" },
|
||||
* { name: "Arnold" },
|
||||
* { name: "Kim" },
|
||||
* ];
|
||||
* const peopleByFirstLetter = groupBy(people, it => it.name.charAt(0))
|
||||
* const peopleByFirstLetter = groupBy(people, (it) => it.name.charAt(0));
|
||||
*
|
||||
* assertEquals(peopleByFirstLetter, {
|
||||
* 'A': [ { name: 'Anna' }, { name: 'Arnold' } ],
|
||||
* 'K': [ { name: 'Kim' } ],
|
||||
* })
|
||||
* assertEquals(
|
||||
* peopleByFirstLetter,
|
||||
* {
|
||||
* "A": [{ name: "Anna" }, { name: "Arnold" }],
|
||||
* "K": [{ name: "Kim" }],
|
||||
* },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function groupBy<T, K extends string>(
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
/**
|
||||
* If the given value is part of the given object it returns true, otherwise it
|
||||
* returns false.
|
||||
* Doesn't work with non-primitive values: includesValue({x: {}}, {}) returns false.
|
||||
* returns false. Doesn't work with non-primitive values: includesValue({x: {}},
|
||||
* {}) returns false.
|
||||
*
|
||||
* Example:
|
||||
* @example
|
||||
* ```ts
|
||||
* import { includesValue } from "https://deno.land/std@$STD_VERSION/collections/includes_value.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
@ -19,7 +19,6 @@
|
||||
* assertEquals(includesValue(input, 34), true);
|
||||
* ```
|
||||
*/
|
||||
|
||||
export function includesValue<T>(
|
||||
record: Readonly<Record<string, T>>,
|
||||
value: T,
|
||||
|
@ -4,19 +4,19 @@
|
||||
import { filterInPlace } from "./_utils.ts";
|
||||
|
||||
/**
|
||||
* Returns all distinct elements that appear at least once in each of the given arrays
|
||||
*
|
||||
* Example:
|
||||
* Returns all distinct elements that appear at least once in each of the given
|
||||
* arrays.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { intersect } from "https://deno.land/std@$STD_VERSION/collections/intersect.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const lisaInterests = [ 'Cooking', 'Music', 'Hiking' ]
|
||||
* const kimInterests = [ 'Music', 'Tennis', 'Cooking' ]
|
||||
* const commonInterests = intersect(lisaInterests, kimInterests)
|
||||
* const lisaInterests = ["Cooking", "Music", "Hiking"];
|
||||
* const kimInterests = ["Music", "Tennis", "Cooking"];
|
||||
* const commonInterests = intersect(lisaInterests, kimInterests);
|
||||
*
|
||||
* assertEquals(commonInterests, [ 'Cooking', 'Music' ])
|
||||
* assertEquals(commonInterests, ["Cooking", "Music"]);
|
||||
* ```
|
||||
*/
|
||||
export function intersect<T>(...arrays: (readonly T[])[]): T[] {
|
||||
|
@ -13,13 +13,14 @@ export type JoinToStringOptions = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms the elements in the given array to strings using the given selector.
|
||||
* Joins the produced strings into one using the given `separator` and applying the given `prefix` and `suffix` to the whole string afterwards.
|
||||
* If the array could be huge, you can specify a non-negative value of `limit`, in which case only the first `limit` elements will be appended, followed by the `truncated` string.
|
||||
* Returns the resulting string.
|
||||
*
|
||||
* Example:
|
||||
* Transforms the elements in the given array to strings using the given
|
||||
* selector. Joins the produced strings into one using the given `separator`
|
||||
* and applying the given `prefix` and `suffix` to the whole string afterwards.
|
||||
* If the array could be huge, you can specify a non-negative value of `limit`,
|
||||
* in which case only the first `limit` elements will be appended, followed by
|
||||
* the `truncated` string. Returns the resulting string.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { joinToString } from "https://deno.land/std@$STD_VERSION/collections/join_to_string.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
@ -30,7 +31,7 @@ export type JoinToStringOptions = {
|
||||
* { name: "Tim" },
|
||||
* ];
|
||||
*
|
||||
* const message = joinToString(users, (it) => it.name, {
|
||||
* const message = joinToString(users, (it) => it.name, {
|
||||
* suffix: " are winners",
|
||||
* prefix: "result: ",
|
||||
* separator: " and ",
|
||||
|
@ -2,29 +2,29 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Applies the given transformer to all entries in the given record and returns a new record containing the results
|
||||
*
|
||||
* Example:
|
||||
* Applies the given transformer to all entries in the given record and returns
|
||||
* a new record containing the results.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { mapEntries } from "https://deno.land/std@$STD_VERSION/collections/map_entries.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const usersById = {
|
||||
* 'a2e': { name: 'Kim', age: 22 },
|
||||
* 'dfe': { name: 'Anna', age: 31 },
|
||||
* '34b': { name: 'Tim', age: 58 },
|
||||
* "a2e": { name: "Kim", age: 22 },
|
||||
* "dfe": { name: "Anna", age: 31 },
|
||||
* "34b": { name: "Tim", age: 58 },
|
||||
* } as const;
|
||||
* const agesByNames = mapEntries(usersById, ([id, { name, age }]) => [name, age]);
|
||||
*
|
||||
* const agesByNames = mapEntries(usersById,
|
||||
* ([ id, { name, age } ]) => [ name, age ],
|
||||
* )
|
||||
*
|
||||
* assertEquals(agesByNames, {
|
||||
* 'Kim': 22,
|
||||
* 'Anna': 31,
|
||||
* 'Tim': 58,
|
||||
* })
|
||||
* assertEquals(
|
||||
* agesByNames,
|
||||
* {
|
||||
* "Kim": 22,
|
||||
* "Anna": 31,
|
||||
* "Tim": 58,
|
||||
* },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function mapEntries<T, O>(
|
||||
|
@ -2,24 +2,27 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Applies the given transformer to all keys in the given record's entries and returns a new record containing the
|
||||
* transformed entries.
|
||||
* Applies the given transformer to all keys in the given record's entries and
|
||||
* returns a new record containing the transformed entries.
|
||||
*
|
||||
* If the transformed entries contain the same key multiple times, only the last one will appear in the returned record.
|
||||
*
|
||||
* Example:
|
||||
* If the transformed entries contain the same key multiple times, only the last
|
||||
* one will appear in the returned record.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { mapKeys } from "https://deno.land/std@$STD_VERSION/collections/map_keys.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const counts = { a: 5, b: 3, c: 8 }
|
||||
* const counts = { a: 5, b: 3, c: 8 };
|
||||
*
|
||||
* assertEquals(mapKeys(counts, it => it.toUpperCase()), {
|
||||
* assertEquals(
|
||||
* mapKeys(counts, (it) => it.toUpperCase()),
|
||||
* {
|
||||
* A: 5,
|
||||
* B: 3,
|
||||
* C: 8,
|
||||
* })
|
||||
* },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function mapKeys<T>(
|
||||
|
@ -2,24 +2,24 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns a new array, containing all elements in the given array transformed using the given transformer, except the ones
|
||||
* that were transformed to `null` or `undefined`
|
||||
*
|
||||
* Example:
|
||||
* Returns a new array, containing all elements in the given array transformed
|
||||
* using the given transformer, except the ones that were transformed to `null`
|
||||
* or `undefined`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { mapNotNullish } from "https://deno.land/std@$STD_VERSION/collections/map_not_nullish.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const people = [
|
||||
* { middleName: null },
|
||||
* { middleName: 'William' },
|
||||
* { middleName: undefined },
|
||||
* { middleName: 'Martha' },
|
||||
* ]
|
||||
* const foundMiddleNames = mapNotNullish(people, it => it.middleName)
|
||||
* { middleName: null },
|
||||
* { middleName: "William" },
|
||||
* { middleName: undefined },
|
||||
* { middleName: "Martha" },
|
||||
* ];
|
||||
* const foundMiddleNames = mapNotNullish(people, (it) => it.middleName);
|
||||
*
|
||||
* assertEquals(foundMiddleNames, [ 'William', 'Martha' ])
|
||||
* assertEquals(foundMiddleNames, ["William", "Martha"]);
|
||||
* ```
|
||||
*/
|
||||
export function mapNotNullish<T, O>(
|
||||
|
@ -2,25 +2,28 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Applies the given transformer to all values in the given record and returns a new record containing the resulting keys
|
||||
* associated to the last value that produced them.
|
||||
*
|
||||
* Example:
|
||||
* Applies the given transformer to all values in the given record and returns a
|
||||
* new record containing the resulting keys associated to the last value that
|
||||
* produced them.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { mapValues } from "https://deno.land/std@$STD_VERSION/collections/map_values.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const usersById = {
|
||||
* 'a5ec': { name: 'Mischa' },
|
||||
* 'de4f': { name: 'Kim' },
|
||||
* }
|
||||
* const namesById = mapValues(usersById, it => it.name)
|
||||
* "a5ec": { name: "Mischa" },
|
||||
* "de4f": { name: "Kim" },
|
||||
* };
|
||||
* const namesById = mapValues(usersById, (it) => it.name);
|
||||
*
|
||||
* assertEquals(namesById, {
|
||||
* 'a5ec': 'Mischa',
|
||||
* 'de4f': 'Kim',
|
||||
* });
|
||||
* assertEquals(
|
||||
* namesById,
|
||||
* {
|
||||
* "a5ec": "Mischa",
|
||||
* "de4f": "Kim",
|
||||
* },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export function mapValues<T, O>(
|
||||
|
@ -2,23 +2,23 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns the first element that is the largest value of the given function or undefined if there are no elements.
|
||||
*
|
||||
* Example:
|
||||
* Returns the first element that is the largest value of the given function or
|
||||
* undefined if there are no elements.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { maxBy } from "https://deno.land/std@$STD_VERSION/collections/max_by.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const people = [
|
||||
* { name: 'Anna', age: 34 },
|
||||
* { name: 'Kim', age: 42 },
|
||||
* { name: 'John', age: 23 },
|
||||
* { name: "Anna", age: 34 },
|
||||
* { name: "Kim", age: 42 },
|
||||
* { name: "John", age: 23 },
|
||||
* ];
|
||||
*
|
||||
* const personWithMaxAge = maxBy(people, i => i.age);
|
||||
* const personWithMaxAge = maxBy(people, (i) => i.age);
|
||||
*
|
||||
* assertEquals(personWithMaxAge, { name: 'Kim', age: 42 });
|
||||
* assertEquals(personWithMaxAge, { name: "Kim", age: 42 });
|
||||
* ```
|
||||
*/
|
||||
export function maxBy<T>(
|
||||
|
@ -2,21 +2,21 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Applies the given selector to all elements of the given collection and
|
||||
* Applies the given selector to all elements of the provided collection and
|
||||
* returns the max value of all elements. If an empty array is provided the
|
||||
* function will return undefined
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { maxOf } from "https://deno.land/std@$STD_VERSION/collections/max_of.ts"
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
|
||||
* import { maxOf } from "https://deno.land/std@$STD_VERSION/collections/max_of.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const inventory = [
|
||||
* { name: "mustard", count: 2 },
|
||||
* { name: "soy", count: 4 },
|
||||
* { name: "tomato", count: 32 },
|
||||
* { name: "mustard", count: 2 },
|
||||
* { name: "soy", count: 4 },
|
||||
* { name: "tomato", count: 32 },
|
||||
* ];
|
||||
*
|
||||
* const maxCount = maxOf(inventory, (i) => i.count);
|
||||
*
|
||||
* assertEquals(maxCount, 32);
|
||||
|
@ -5,12 +5,11 @@
|
||||
* Returns the first element having the largest value according to the provided
|
||||
* comparator or undefined if there are no elements.
|
||||
*
|
||||
* The comparator is expected to work exactly like one passed to `Array.sort`, which means
|
||||
* that `comparator(a, b)` should return a negative number if `a < b`, a positive number if `a > b`
|
||||
* and `0` if `a == b`.
|
||||
*
|
||||
* Example:
|
||||
* The comparator is expected to work exactly like one passed to `Array.sort`,
|
||||
* which means that `comparator(a, b)` should return a negative number if `a < b`,
|
||||
* a positive number if `a > b` and `0` if `a == b`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { maxWith } from "https://deno.land/std@$STD_VERSION/collections/max_with.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
@ -2,23 +2,23 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns the first element that is the smallest value of the given function or undefined if there are no elements.
|
||||
*
|
||||
* Example:
|
||||
* Returns the first element that is the smallest value of the given function or
|
||||
* undefined if there are no elements
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { minBy } from "https://deno.land/std@$STD_VERSION/collections/min_by.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const people = [
|
||||
* { name: 'Anna', age: 34 },
|
||||
* { name: 'Kim', age: 42 },
|
||||
* { name: 'John', age: 23 },
|
||||
* { name: "Anna", age: 34 },
|
||||
* { name: "Kim", age: 42 },
|
||||
* { name: "John", age: 23 },
|
||||
* ];
|
||||
*
|
||||
* const personWithMinAge = minBy(people, i => i.age);
|
||||
* const personWithMinAge = minBy(people, (i) => i.age);
|
||||
*
|
||||
* assertEquals(personWithMinAge, { name: 'John', age: 23 });
|
||||
* assertEquals(personWithMinAge, { name: "John", age: 23 });
|
||||
* ```
|
||||
*/
|
||||
export function minBy<T>(
|
||||
|
@ -4,18 +4,17 @@
|
||||
/**
|
||||
* Applies the given selector to all elements of the given collection and
|
||||
* returns the min value of all elements. If an empty array is provided the
|
||||
* function will return undefined
|
||||
*
|
||||
* Example:
|
||||
* function will return undefined.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { minOf } from "https://deno.land/std@$STD_VERSION/collections/min_of.ts"
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
|
||||
* import { minOf } from "https://deno.land/std@$STD_VERSION/collections/min_of.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const inventory = [
|
||||
* { name: "mustard", count: 2 },
|
||||
* { name: "soy", count: 4 },
|
||||
* { name: "tomato", count: 32 },
|
||||
* { name: "mustard", count: 2 },
|
||||
* { name: "soy", count: 4 },
|
||||
* { name: "tomato", count: 32 },
|
||||
* ];
|
||||
* const minCount = minOf(inventory, (i) => i.count);
|
||||
*
|
||||
|
@ -2,10 +2,10 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns the first element having the smallest value according to the provided comparator or undefined if there are no elements
|
||||
*
|
||||
* Example:
|
||||
* Returns the first element having the smallest value according to the provided
|
||||
* comparator or undefined if there are no elements
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { minWith } from "https://deno.land/std@$STD_VERSION/collections/min_with.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
@ -1,12 +1,17 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/** Functions for specific common tasks around collection types like `Array` and
|
||||
* `Record`.
|
||||
* `Record`. This module is heavily inspired by `kotlin`s stdlib.
|
||||
*
|
||||
* - All provided functions are **pure**, which also means that they do **not
|
||||
* mutate** your inputs, **returning a new value** instead.
|
||||
* - All functions are importable on their own by referencing their snake_case
|
||||
* named file (e.g. `collections/sort_by.ts`)
|
||||
*
|
||||
* This module re-exports several modules, and importing this module directly
|
||||
* will likely include a lot of code that you might not use.
|
||||
*
|
||||
* Consider importing the function directly. For example to import
|
||||
* Consider importing the function directly. For example to import
|
||||
* {@linkcode groupBy} import the module using the snake cased version of the
|
||||
* module:
|
||||
*
|
||||
|
@ -2,20 +2,20 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns a tuple of two arrays with the first one containing all elements in the given array that match the given predicate
|
||||
* and the second one containing all that do not
|
||||
*
|
||||
* Example:
|
||||
* Returns a tuple of two arrays with the first one containing all elements in
|
||||
* the given array that match the given predicate and the second one containing
|
||||
* all that do not.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { partition } from "https://deno.land/std@$STD_VERSION/collections/partition.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const numbers = [ 5, 6, 7, 8, 9 ]
|
||||
* const [ even, odd ] = partition(numbers, it => it % 2 == 0)
|
||||
* const numbers = [5, 6, 7, 8, 9];
|
||||
* const [even, odd] = partition(numbers, (it) => it % 2 == 0);
|
||||
*
|
||||
* assertEquals(even, [ 6, 8 ])
|
||||
* assertEquals(odd, [ 5, 7, 9 ])
|
||||
* assertEquals(even, [6, 8]);
|
||||
* assertEquals(odd, [5, 7, 9]);
|
||||
* ```
|
||||
*/
|
||||
export function partition<T, U extends T>(
|
||||
|
@ -6,19 +6,18 @@
|
||||
* Ignores equality of elements, meaning this will always return the same
|
||||
* number of permutations for a given length of input.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { permutations } from "https://deno.land/std@$STD_VERSION/collections/permutations.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const numbers = [ 1, 2 ]
|
||||
* const windows = permutations(numbers)
|
||||
* const numbers = [ 1, 2 ];
|
||||
* const windows = permutations(numbers);
|
||||
*
|
||||
* assertEquals(windows, [
|
||||
* [ 1, 2 ],
|
||||
* [ 2, 1 ],
|
||||
* ])
|
||||
* [ 1, 2 ],
|
||||
* [ 2, 1 ],
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
export function permutations<T>(inputArray: readonly T[]): T[][] {
|
||||
|
@ -6,9 +6,86 @@ import { Direction, RedBlackNode } from "./red_black_node.ts";
|
||||
export * from "./_comparators.ts";
|
||||
|
||||
/**
|
||||
* A red-black tree. This is a kind of self-balancing binary search tree.
|
||||
* The values are in ascending order by default,
|
||||
* using JavaScript's built in comparison operators to sort the values.
|
||||
* A red-black tree. This is a kind of self-balancing binary search tree. The
|
||||
* values are in ascending order by default, using JavaScript's built-in
|
||||
* comparison operators to sort the values.
|
||||
*
|
||||
* Red-Black Trees require fewer rotations than AVL Trees, so they can provide
|
||||
* faster insertions and removal operations. If you need faster lookups, you
|
||||
* should use an AVL Tree instead. AVL Trees are more strictly balanced than
|
||||
* Red-Black Trees, so they can provide faster lookups.
|
||||
*
|
||||
* | Method | Average Case | Worst Case |
|
||||
* | ------------- | ------------ | ---------- |
|
||||
* | find(value) | O(log n) | O(log n) |
|
||||
* | insert(value) | O(log n) | O(log n) |
|
||||
* | remove(value) | O(log n) | O(log n) |
|
||||
* | min() | O(log n) | O(log n) |
|
||||
* | max() | O(log n) | O(log n) |
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* ascend,
|
||||
* descend,
|
||||
* RedBlackTree,
|
||||
* } from "https://deno.land/std@$STD_VERSION/collections/red_black_tree.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const values = [3, 10, 13, 4, 6, 7, 1, 14];
|
||||
* const tree = new RedBlackTree<number>();
|
||||
* values.forEach((value) => tree.insert(value));
|
||||
* assertEquals([...tree], [1, 3, 4, 6, 7, 10, 13, 14]);
|
||||
* assertEquals(tree.min(), 1);
|
||||
* assertEquals(tree.max(), 14);
|
||||
* assertEquals(tree.find(42), null);
|
||||
* assertEquals(tree.find(7), 7);
|
||||
* assertEquals(tree.remove(42), false);
|
||||
* assertEquals(tree.remove(7), true);
|
||||
* assertEquals([...tree], [1, 3, 4, 6, 10, 13, 14]);
|
||||
*
|
||||
* const invertedTree = new RedBlackTree<number>(descend);
|
||||
* values.forEach((value) => invertedTree.insert(value));
|
||||
* assertEquals([...invertedTree], [14, 13, 10, 7, 6, 4, 3, 1]);
|
||||
* assertEquals(invertedTree.min(), 14);
|
||||
* assertEquals(invertedTree.max(), 1);
|
||||
* assertEquals(invertedTree.find(42), null);
|
||||
* assertEquals(invertedTree.find(7), 7);
|
||||
* assertEquals(invertedTree.remove(42), false);
|
||||
* assertEquals(invertedTree.remove(7), true);
|
||||
* assertEquals([...invertedTree], [14, 13, 10, 6, 4, 3, 1]);
|
||||
*
|
||||
* const words = new RedBlackTree<string>((a, b) =>
|
||||
* ascend(a.length, b.length) || ascend(a, b)
|
||||
* );
|
||||
* ["truck", "car", "helicopter", "tank", "train", "suv", "semi", "van"]
|
||||
* .forEach((value) => words.insert(value));
|
||||
* assertEquals([...words], [
|
||||
* "car",
|
||||
* "suv",
|
||||
* "van",
|
||||
* "semi",
|
||||
* "tank",
|
||||
* "train",
|
||||
* "truck",
|
||||
* "helicopter",
|
||||
* ]);
|
||||
* assertEquals(words.min(), "car");
|
||||
* assertEquals(words.max(), "helicopter");
|
||||
* assertEquals(words.find("scooter"), null);
|
||||
* assertEquals(words.find("tank"), "tank");
|
||||
* assertEquals(words.remove("scooter"), false);
|
||||
* assertEquals(words.remove("tank"), true);
|
||||
* assertEquals([...words], [
|
||||
* "car",
|
||||
* "suv",
|
||||
* "van",
|
||||
* "semi",
|
||||
* "train",
|
||||
* "truck",
|
||||
* "helicopter",
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
export class RedBlackTree<T> extends BinarySearchTree<T> {
|
||||
declare protected root: RedBlackNode<T> | null;
|
||||
|
@ -4,22 +4,25 @@
|
||||
import { mapValues } from "./map_values.ts";
|
||||
|
||||
/**
|
||||
* Applies the given reducer to each group in the given Grouping, returning the results together with the respective group keys
|
||||
* Applies the given reducer to each group in the given Grouping, returning the
|
||||
* results together with the respective group keys.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { reduceGroups } from "https://deno.land/std@$STD_VERSION/collections/reduce_groups.ts"
|
||||
* import { reduceGroups } from "https://deno.land/std@$STD_VERSION/collections/reduce_groups.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const votes = {
|
||||
* 'Woody': [ 2, 3, 1, 4 ],
|
||||
* 'Buzz': [ 5, 9 ],
|
||||
* }
|
||||
* const totalVotes = reduceGroups(votes, (sum, it) => sum + it, 0)
|
||||
* "Woody": [2, 3, 1, 4],
|
||||
* "Buzz": [5, 9],
|
||||
* };
|
||||
*
|
||||
* const totalVotes = reduceGroups(votes, (sum, it) => sum + it, 0);
|
||||
*
|
||||
* assertEquals(totalVotes, {
|
||||
* 'Woody': 10,
|
||||
* 'Buzz': 14,
|
||||
* })
|
||||
* "Woody": 10,
|
||||
* "Buzz": 14,
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function reduceGroups<T, A>(
|
||||
|
@ -2,12 +2,11 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Calls the given reducer on each element of the given collection, passing it's
|
||||
* result as the accumulator to the next respective call, starting with the given
|
||||
* initialValue. Returns all intermediate accumulator results.
|
||||
*
|
||||
* Example:
|
||||
* Calls the given reducer on each element of the given collection, passing its
|
||||
* result as the accumulator to the next respective call, starting with the
|
||||
* given initialValue. Returns all intermediate accumulator results.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { runningReduce } from "https://deno.land/std@$STD_VERSION/collections/running_reduce.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
@ -4,12 +4,11 @@
|
||||
import { randomInteger } from "./_utils.ts";
|
||||
|
||||
/**
|
||||
* Returns a random element from the given array.
|
||||
*
|
||||
* Example:
|
||||
* Returns a random element from the given array
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { sample } from "https://deno.land/std@$STD_VERSION/collections/sample.ts"
|
||||
* import { sample } from "https://deno.land/std@$STD_VERSION/collections/sample.ts";
|
||||
* import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const numbers = [1, 2, 3, 4];
|
||||
|
@ -2,18 +2,16 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Generates sliding views of the given array of the given size and returns a new
|
||||
* array containing all of them.
|
||||
* Generates sliding views of the given array of the given size and returns a
|
||||
* new array containing all of them.
|
||||
*
|
||||
* If step is set, each window will start that many elements after the last
|
||||
* window's start. (Default: 1)
|
||||
*
|
||||
* If partial is set, windows will be generated for the last elements of the
|
||||
* collection, resulting in some undefined values if size is greater than 1.
|
||||
* (Default: false)
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { slidingWindows } from "https://deno.land/std@$STD_VERSION/collections/sliding_windows.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
@ -48,13 +46,16 @@ export function slidingWindows<T>(
|
||||
{ step = 1, partial = false }: {
|
||||
/**
|
||||
* If step is set, each window will start that many elements after the last
|
||||
* window's start. (Default: 1)
|
||||
* window's start.
|
||||
*
|
||||
* @default {1}
|
||||
*/
|
||||
step?: number;
|
||||
/**
|
||||
* If partial is set, windows will be generated for the last elements of the
|
||||
* collection, resulting in some undefined values if size is greater than 1.
|
||||
* (Default: false)
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
partial?: boolean;
|
||||
} = {},
|
||||
|
@ -2,26 +2,27 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns all elements in the given collection, sorted stably by their result using the given selector. The selector function is called only once for each element.
|
||||
*
|
||||
* Example:
|
||||
* Returns all elements in the given collection, sorted by their result using
|
||||
* the given selector. The selector function is called only once for each
|
||||
* element.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { sortBy } from "https://deno.land/std@$STD_VERSION/collections/sort_by.ts"
|
||||
* import { sortBy } from "https://deno.land/std@$STD_VERSION/collections/sort_by.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const people = [
|
||||
* { name: 'Anna', age: 34 },
|
||||
* { name: 'Kim', age: 42 },
|
||||
* { name: 'John', age: 23 },
|
||||
* ]
|
||||
* const sortedByAge = sortBy(people, it => it.age)
|
||||
* { name: "Anna", age: 34 },
|
||||
* { name: "Kim", age: 42 },
|
||||
* { name: "John", age: 23 },
|
||||
* ];
|
||||
* const sortedByAge = sortBy(people, (it) => it.age);
|
||||
*
|
||||
* assertEquals(sortedByAge, [
|
||||
* { name: 'John', age: 23 },
|
||||
* { name: 'Anna', age: 34 },
|
||||
* { name: 'Kim', age: 42 },
|
||||
* ])
|
||||
* { name: "John", age: 23 },
|
||||
* { name: "Anna", age: 34 },
|
||||
* { name: "Kim", age: 42 },
|
||||
* ]);
|
||||
* ```
|
||||
*/
|
||||
export function sortBy<T>(
|
||||
|
@ -2,22 +2,22 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Applies the given selector to all elements in the given collection and calculates the sum of the results
|
||||
*
|
||||
* Example:
|
||||
* Applies the given selector to all elements in the given collection and
|
||||
* calculates the sum of the results.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { sumOf } from "https://deno.land/std@$STD_VERSION/collections/sum_of.ts"
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts"
|
||||
* import { sumOf } from "https://deno.land/std@$STD_VERSION/collections/sum_of.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const people = [
|
||||
* { name: 'Anna', age: 34 },
|
||||
* { name: 'Kim', age: 42 },
|
||||
* { name: 'John', age: 23 },
|
||||
* ]
|
||||
* const totalAge = sumOf(people, i => i.age)
|
||||
* { name: "Anna", age: 34 },
|
||||
* { name: "Kim", age: 42 },
|
||||
* { name: "John", age: 23 },
|
||||
* ];
|
||||
* const totalAge = sumOf(people, (i) => i.age);
|
||||
*
|
||||
* assertEquals(totalAge, 99)
|
||||
* assertEquals(totalAge, 99);
|
||||
* ```
|
||||
*/
|
||||
export function sumOf<T>(
|
||||
|
@ -5,7 +5,7 @@
|
||||
* Returns all elements in the given array after the last element that does not
|
||||
* match the given predicate.
|
||||
*
|
||||
* Example:
|
||||
* @example
|
||||
* ```ts
|
||||
* import { takeLastWhile } from "https://deno.land/std@$STD_VERSION/collections/take_last_while.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
@ -2,9 +2,10 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Returns all elements in the given collection until the first element that does not match the given predicate.
|
||||
* Returns all elements in the given collection until the first element that
|
||||
* does not match the given predicate.
|
||||
*
|
||||
* Example:
|
||||
* @example
|
||||
* ```ts
|
||||
* import { takeWhile } from "https://deno.land/std@$STD_VERSION/collections/take_while.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
@ -4,17 +4,16 @@
|
||||
/**
|
||||
* Returns all distinct elements that appear in any of the given arrays
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { union } from "https://deno.land/std@$STD_VERSION/collections/union.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const soupIngredients = [ 'Pepper', 'Carrots', 'Leek' ]
|
||||
* const saladIngredients = [ 'Carrots', 'Radicchio', 'Pepper' ]
|
||||
* const shoppingList = union(soupIngredients, saladIngredients)
|
||||
* const soupIngredients = ["Pepper", "Carrots", "Leek"];
|
||||
* const saladIngredients = ["Carrots", "Radicchio", "Pepper"];
|
||||
* const shoppingList = union(soupIngredients, saladIngredients);
|
||||
*
|
||||
* assertEquals(shoppingList, [ 'Pepper', 'Carrots', 'Leek', 'Radicchio' ])
|
||||
* assertEquals(shoppingList, ["Pepper", "Carrots", "Leek", "Radicchio"]);
|
||||
* ```
|
||||
*/
|
||||
export function union<T>(...arrays: (readonly T[])[]): T[] {
|
||||
|
@ -2,25 +2,24 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Builds two separate arrays from the given array of 2-tuples, with the first returned array holding all first
|
||||
* tuple elements and the second one holding all the second elements
|
||||
*
|
||||
* Example:
|
||||
* Builds two separate arrays from the given array of 2-tuples, with the first
|
||||
* returned array holding all first tuple elements and the second one holding
|
||||
* all the second elements.
|
||||
*
|
||||
* ```ts
|
||||
* import { unzip } from "https://deno.land/std@$STD_VERSION/collections/unzip.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const parents = [
|
||||
* [ 'Maria', 'Jeff' ],
|
||||
* [ 'Anna', 'Kim' ],
|
||||
* [ 'John', 'Leroy' ],
|
||||
* ["Maria", "Jeff"],
|
||||
* ["Anna", "Kim"],
|
||||
* ["John", "Leroy"],
|
||||
* ] as [string, string][];
|
||||
*
|
||||
* const [ moms, dads ] = unzip(parents);
|
||||
* const [moms, dads] = unzip(parents);
|
||||
*
|
||||
* assertEquals(moms, [ 'Maria', 'Anna', 'John' ]);
|
||||
* assertEquals(dads, [ 'Jeff', 'Kim', 'Leroy' ]);
|
||||
* assertEquals(moms, ["Maria", "Anna", "John"]);
|
||||
* assertEquals(dads, ["Jeff", "Kim", "Leroy"]);
|
||||
* ```
|
||||
*/
|
||||
export function unzip<T, U>(pairs: readonly [T, U][]): [T[], U[]] {
|
||||
|
@ -4,8 +4,7 @@
|
||||
/**
|
||||
* Returns an array excluding all given values.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { withoutAll } from "https://deno.land/std@$STD_VERSION/collections/without_all.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
@ -2,23 +2,27 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
/**
|
||||
* Builds N-tuples of elements from the given N arrays with matching indices, stopping when the smallest array's end is reached
|
||||
* Example:
|
||||
* Builds N-tuples of elements from the given N arrays with matching indices,
|
||||
* stopping when the smallest array's end is reached.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { zip } from "https://deno.land/std@$STD_VERSION/collections/zip.ts";
|
||||
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const numbers = [ 1, 2, 3, 4 ];
|
||||
* const letters = [ 'a', 'b', 'c', 'd' ];
|
||||
* const numbers = [1, 2, 3, 4];
|
||||
* const letters = ["a", "b", "c", "d"];
|
||||
* const pairs = zip(numbers, letters);
|
||||
*
|
||||
* assertEquals(pairs, [
|
||||
* [ 1, 'a' ],
|
||||
* [ 2, 'b' ],
|
||||
* [ 3, 'c' ],
|
||||
* [ 4, 'd' ],
|
||||
* ]);
|
||||
* assertEquals(
|
||||
* pairs,
|
||||
* [
|
||||
* [1, "a"],
|
||||
* [2, "b"],
|
||||
* [3, "c"],
|
||||
* [4, "d"],
|
||||
* ],
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
|
||||
|
178
crypto/README.md
178
crypto/README.md
@ -1,178 +0,0 @@
|
||||
# crypto
|
||||
|
||||
Extensions to the WebCrypto interface, which provides additional encryption
|
||||
algorithms that are not part of the web standard, as well as a
|
||||
`subtle.digest()`, `subtle.digestSync()`, and `subtle.timingSafeEqual()` methods
|
||||
which provide additional functionality not covered by web crypto.
|
||||
|
||||
It also includes some utilities for key management.
|
||||
|
||||
## `crypto` usage
|
||||
|
||||
The `crypto` export provides an enhanced version of the built-in
|
||||
[Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
|
||||
providing additional cryptographic algorithms using the same interface as the
|
||||
Web Crypto API, but also delegating to the built in APIs when possible.
|
||||
|
||||
```ts
|
||||
import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
|
||||
|
||||
// This will delegate to the runtime's WebCrypto implementation.
|
||||
console.log(
|
||||
new Uint8Array(
|
||||
await crypto.subtle.digest(
|
||||
"SHA-384",
|
||||
new TextEncoder().encode("hello world"),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// This will use a bundled Wasm/Rust implementation.
|
||||
console.log(
|
||||
new Uint8Array(
|
||||
await crypto.subtle.digest(
|
||||
"BLAKE3",
|
||||
new TextEncoder().encode("hello world"),
|
||||
),
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
### Supported algorithms
|
||||
|
||||
Here is a list of supported algorithms. If the algorithm name in WebCrypto and
|
||||
Wasm/Rust is the same, this library prefers to use algorithms that are supported
|
||||
by WebCrypto.
|
||||
|
||||
WebCrypto
|
||||
|
||||
```ts
|
||||
// https://deno.land/std/crypto/mod.ts
|
||||
const webCryptoDigestAlgorithms = [
|
||||
"SHA-384",
|
||||
"SHA-256",
|
||||
"SHA-512",
|
||||
// insecure (length-extendable and collidable):
|
||||
"SHA-1",
|
||||
] as const;
|
||||
```
|
||||
|
||||
Wasm/Rust
|
||||
|
||||
```ts
|
||||
// https://deno.land/std/_wasm_crypto/mod.ts
|
||||
export const digestAlgorithms = [
|
||||
"BLAKE2B-256",
|
||||
"BLAKE2B-384",
|
||||
"BLAKE2B",
|
||||
"BLAKE2S",
|
||||
"BLAKE3",
|
||||
"KECCAK-224",
|
||||
"KECCAK-256",
|
||||
"KECCAK-384",
|
||||
"KECCAK-512",
|
||||
"SHA-384",
|
||||
"SHA3-224",
|
||||
"SHA3-256",
|
||||
"SHA3-384",
|
||||
"SHA3-512",
|
||||
"SHAKE128",
|
||||
"SHAKE256",
|
||||
"TIGER",
|
||||
// insecure (length-extendable):
|
||||
"RIPEMD-160",
|
||||
"SHA-224",
|
||||
"SHA-256",
|
||||
"SHA-512",
|
||||
// insecure (collidable and length-extendable):
|
||||
"MD5",
|
||||
"SHA-1",
|
||||
] as const;
|
||||
```
|
||||
|
||||
## Timing safe comparison
|
||||
|
||||
When checking the values of cryptographic hashes are equal, default comparisons
|
||||
can be susceptible to timing based attacks, where attacker is able to find out
|
||||
information about the host system by repeatedly checking response times to to
|
||||
equality comparisons of values.
|
||||
|
||||
It is likely some form of timing safe equality will make its way to the
|
||||
WebCrypto standard (see:
|
||||
[w3c/webcrypto#270](https://github.com/w3c/webcrypto/issues/270)), but until
|
||||
that time, `timingSafeEqual()` is provided:
|
||||
|
||||
```ts
|
||||
import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
|
||||
import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
||||
const a = await crypto.subtle.digest(
|
||||
"SHA-384",
|
||||
new TextEncoder().encode("hello world"),
|
||||
);
|
||||
const b = await crypto.subtle.digest(
|
||||
"SHA-384",
|
||||
new TextEncoder().encode("hello world"),
|
||||
);
|
||||
const c = await crypto.subtle.digest(
|
||||
"SHA-384",
|
||||
new TextEncoder().encode("hello deno"),
|
||||
);
|
||||
|
||||
assert(crypto.subtle.timingSafeEqual(a, b));
|
||||
assert(!crypto.subtle.timingSafeEqual(a, c));
|
||||
```
|
||||
|
||||
In addition to the method being part of the `crypto.subtle` interface, it is
|
||||
also loadable directly:
|
||||
|
||||
```ts
|
||||
import { timingSafeEqual } from "https://deno.land/std@$STD_VERSION/crypto/timing_safe_equal.ts";
|
||||
import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
|
||||
const a = await crypto.subtle.digest(
|
||||
"SHA-384",
|
||||
new TextEncoder().encode("hello world"),
|
||||
);
|
||||
const b = await crypto.subtle.digest(
|
||||
"SHA-384",
|
||||
new TextEncoder().encode("hello world"),
|
||||
);
|
||||
|
||||
assert(timingSafeEqual(a, b));
|
||||
```
|
||||
|
||||
## `KeyStack` usage
|
||||
|
||||
The `KeyStack` export implements the `KeyRing` interface for managing rotatable
|
||||
keys for signing data to prevent tampering, like with HTTP cookies.
|
||||
|
||||
```ts
|
||||
import { KeyStack } from "https://deno.land/std@$STD_VERSION/crypto/keystack.ts";
|
||||
|
||||
const keyStack = new KeyStack(["hello", "world"]);
|
||||
const digest = await keyStack.sign("some data");
|
||||
|
||||
const rotatedStack = new KeyStack(["deno", "says", "hello", "world"]);
|
||||
await rotatedStack.verify("some data", digest); // true
|
||||
```
|
||||
|
||||
## Convert hash to a string
|
||||
|
||||
```ts
|
||||
import {
|
||||
crypto,
|
||||
toHashString,
|
||||
} from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
|
||||
|
||||
const hash = await crypto.subtle.digest(
|
||||
"SHA-384",
|
||||
new TextEncoder().encode("You hear that Mr. Anderson?"),
|
||||
);
|
||||
|
||||
// Hex encoding by default
|
||||
console.log(toHashString(hash));
|
||||
|
||||
// Or with base64 encoding
|
||||
console.log(toHashString(hash, "base64"));
|
||||
```
|
@ -72,8 +72,7 @@ async function compare(a: Data, b: Data): Promise<boolean> {
|
||||
*
|
||||
* This was inspired by [keygrip](https://github.com/crypto-utils/keygrip/).
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { KeyStack } from "https://deno.land/std@$STD_VERSION/crypto/keystack.ts";
|
||||
*
|
||||
|
154
crypto/mod.ts
154
crypto/mod.ts
@ -3,11 +3,12 @@
|
||||
/**
|
||||
* Extensions to the
|
||||
* [Web Crypto](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)
|
||||
* supporting additional encryption APIs.
|
||||
* supporting additional encryption APIs, but also delegating to the built-in
|
||||
* APIs when possible.
|
||||
*
|
||||
* Provides additional digest algorithms that are not part of the WebCrypto
|
||||
* standard as well as a `subtle.digest` and `subtle.digestSync` methods. It
|
||||
* also provide a `subtle.timingSafeEqual()` method to compare array buffers
|
||||
* also provides a `subtle.timingSafeEqual()` method to compare array buffers
|
||||
* or data views in a way that isn't prone to timing based attacks.
|
||||
*
|
||||
* The "polyfill" delegates to `WebCrypto` where possible.
|
||||
@ -16,6 +17,155 @@
|
||||
* for managing rotatable keys for signing data to prevent tampering, like with
|
||||
* HTTP cookies.
|
||||
*
|
||||
* ## Supported algorithms
|
||||
*
|
||||
* Here is a list of supported algorithms. If the algorithm name in WebCrypto
|
||||
* and Wasm/Rust is the same, this library prefers to use algorithms that are
|
||||
* supported by WebCrypto.
|
||||
*
|
||||
* WebCrypto
|
||||
*
|
||||
* ```ts
|
||||
* // https://deno.land/std/crypto/mod.ts
|
||||
* const webCryptoDigestAlgorithms = [
|
||||
* "SHA-384",
|
||||
* "SHA-256",
|
||||
* "SHA-512",
|
||||
* // insecure (length-extendable and collidable):
|
||||
* "SHA-1",
|
||||
* ] as const;
|
||||
* ```
|
||||
*
|
||||
* Wasm/Rust
|
||||
*
|
||||
* ```ts
|
||||
* // https://deno.land/std/_wasm_crypto/mod.ts
|
||||
* export const digestAlgorithms = [
|
||||
* "BLAKE2B-256",
|
||||
* "BLAKE2B-384",
|
||||
* "BLAKE2B",
|
||||
* "BLAKE2S",
|
||||
* "BLAKE3",
|
||||
* "KECCAK-224",
|
||||
* "KECCAK-256",
|
||||
* "KECCAK-384",
|
||||
* "KECCAK-512",
|
||||
* "SHA-384",
|
||||
* "SHA3-224",
|
||||
* "SHA3-256",
|
||||
* "SHA3-384",
|
||||
* "SHA3-512",
|
||||
* "SHAKE128",
|
||||
* "SHAKE256",
|
||||
* "TIGER",
|
||||
* // insecure (length-extendable):
|
||||
* "RIPEMD-160",
|
||||
* "SHA-224",
|
||||
* "SHA-256",
|
||||
* "SHA-512",
|
||||
* // insecure (collidable and length-extendable):
|
||||
* "MD5",
|
||||
* "SHA-1",
|
||||
* ] as const;
|
||||
* ```
|
||||
*
|
||||
* ## Timing safe comparison
|
||||
*
|
||||
* When checking the values of cryptographic hashes are equal, default
|
||||
* comparisons can be susceptible to timing based attacks, where attacker is
|
||||
* able to find out information about the host system by repeatedly checking
|
||||
* response times to equality comparisons of values.
|
||||
*
|
||||
* It is likely some form of timing safe equality will make its way to the
|
||||
* WebCrypto standard (see:
|
||||
* [w3c/webcrypto#270](https://github.com/w3c/webcrypto/issues/270)), but until
|
||||
* that time, `timingSafeEqual()` is provided:
|
||||
*
|
||||
* ```ts
|
||||
* import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
|
||||
* import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const a = await crypto.subtle.digest(
|
||||
* "SHA-384",
|
||||
* new TextEncoder().encode("hello world"),
|
||||
* );
|
||||
* const b = await crypto.subtle.digest(
|
||||
* "SHA-384",
|
||||
* new TextEncoder().encode("hello world"),
|
||||
* );
|
||||
* const c = await crypto.subtle.digest(
|
||||
* "SHA-384",
|
||||
* new TextEncoder().encode("hello deno"),
|
||||
* );
|
||||
*
|
||||
* assert(crypto.subtle.timingSafeEqual(a, b));
|
||||
* assert(!crypto.subtle.timingSafeEqual(a, c));
|
||||
* ```
|
||||
*
|
||||
* In addition to the method being part of the `crypto.subtle` interface, it is
|
||||
* also loadable directly:
|
||||
*
|
||||
* ```ts
|
||||
* import { timingSafeEqual } from "https://deno.land/std@$STD_VERSION/crypto/timing_safe_equal.ts";
|
||||
* import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
|
||||
*
|
||||
* const a = await crypto.subtle.digest(
|
||||
* "SHA-384",
|
||||
* new TextEncoder().encode("hello world"),
|
||||
* );
|
||||
* const b = await crypto.subtle.digest(
|
||||
* "SHA-384",
|
||||
* new TextEncoder().encode("hello world"),
|
||||
* );
|
||||
*
|
||||
* assert(timingSafeEqual(a, b));
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { crypto } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
|
||||
*
|
||||
* // This will delegate to the runtime's WebCrypto implementation.
|
||||
* console.log(
|
||||
* new Uint8Array(
|
||||
* await crypto.subtle.digest(
|
||||
* "SHA-384",
|
||||
* new TextEncoder().encode("hello world"),
|
||||
* ),
|
||||
* ),
|
||||
* );
|
||||
*
|
||||
* // This will use a bundled Wasm/Rust implementation.
|
||||
* console.log(
|
||||
* new Uint8Array(
|
||||
* await crypto.subtle.digest(
|
||||
* "BLAKE3",
|
||||
* new TextEncoder().encode("hello world"),
|
||||
* ),
|
||||
* ),
|
||||
* );
|
||||
* ```
|
||||
*
|
||||
* @example Convert hash to a string
|
||||
*
|
||||
* ```ts
|
||||
* import {
|
||||
* crypto,
|
||||
* toHashString,
|
||||
* } from "https://deno.land/std@$STD_VERSION/crypto/mod.ts";
|
||||
*
|
||||
* const hash = await crypto.subtle.digest(
|
||||
* "SHA-384",
|
||||
* new TextEncoder().encode("You hear that Mr. Anderson?"),
|
||||
* );
|
||||
*
|
||||
* // Hex encoding by default
|
||||
* console.log(toHashString(hash));
|
||||
*
|
||||
* // Or with base64 encoding
|
||||
* console.log(toHashString(hash, "base64"));
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -1,187 +0,0 @@
|
||||
# datetime
|
||||
|
||||
Simple helper to help parse date strings into `Date`, with additional functions.
|
||||
|
||||
## Usage
|
||||
|
||||
The following symbols from
|
||||
[unicode LDML](http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
|
||||
are supported:
|
||||
|
||||
- `yyyy` - numeric year.
|
||||
- `yy` - 2-digit year.
|
||||
- `M` - numeric month.
|
||||
- `MM` - 2-digit month.
|
||||
- `d` - numeric day.
|
||||
- `dd` - 2-digit day.
|
||||
|
||||
- `H` - numeric hour (0-23 hours).
|
||||
- `HH` - 2-digit hour (00-23 hours).
|
||||
- `h` - numeric hour (1-12 hours).
|
||||
- `hh` - 2-digit hour (01-12 hours).
|
||||
- `m` - numeric minute.
|
||||
- `mm` - 2-digit minute.
|
||||
- `s` - numeric second.
|
||||
- `ss` - 2-digit second.
|
||||
- `S` - 1-digit fractionalSecond.
|
||||
- `SS` - 2-digit fractionalSecond.
|
||||
- `SSS` - 3-digit fractionalSecond.
|
||||
|
||||
- `a` - dayPeriod, either `AM` or `PM`.
|
||||
|
||||
- `'foo'` - quoted literal.
|
||||
- `./-` - unquoted literal.
|
||||
|
||||
## Methods
|
||||
|
||||
### parse
|
||||
|
||||
Takes an input `string` and a `formatString` to parse to a `date`.
|
||||
|
||||
```ts
|
||||
import { parse } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
parse("20-01-2019", "dd-MM-yyyy"); // output : new Date(2019, 0, 20)
|
||||
parse("2019-01-20", "yyyy-MM-dd"); // output : new Date(2019, 0, 20)
|
||||
parse("20.01.2019", "dd.MM.yyyy"); // output : new Date(2019, 0, 20)
|
||||
parse("01-20-2019 16:34", "MM-dd-yyyy HH:mm"); // output : new Date(2019, 0, 20, 16, 34)
|
||||
parse("01-20-2019 04:34 PM", "MM-dd-yyyy hh:mm a"); // output : new Date(2019, 0, 20, 16, 34)
|
||||
parse("16:34 01-20-2019", "HH:mm MM-dd-yyyy"); // output : new Date(2019, 0, 20, 16, 34)
|
||||
parse("01-20-2019 16:34:23.123", "MM-dd-yyyy HH:mm:ss.SSS"); // output : new Date(2019, 0, 20, 16, 34, 23, 123)
|
||||
```
|
||||
|
||||
### format
|
||||
|
||||
Takes an input `date` and a `formatString` to format to a `string`.
|
||||
|
||||
```ts
|
||||
import { format } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
format(new Date(2019, 0, 20), "dd-MM-yyyy"); // output : "20-01-2019"
|
||||
format(new Date(2019, 0, 20), "yyyy-MM-dd"); // output : "2019-01-20"
|
||||
format(new Date(2019, 0, 20), "dd.MM.yyyy"); // output : "20.01.2019"
|
||||
format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy HH:mm"); // output : "01-20-2019 16:34"
|
||||
format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy hh:mm a"); // output : "01-20-2019 04:34 PM"
|
||||
format(new Date(2019, 0, 20, 16, 34), "HH:mm MM-dd-yyyy"); // output : "16:34 01-20-2019"
|
||||
format(new Date(2019, 0, 20, 16, 34, 23, 123), "MM-dd-yyyy HH:mm:ss.SSS"); // output : "01-20-2019 16:34:23.123"
|
||||
format(new Date(2019, 0, 20), "'today:' yyyy-MM-dd"); // output : "today: 2019-01-20"
|
||||
```
|
||||
|
||||
### dayOfYear
|
||||
|
||||
Returns the number of the day in the year.
|
||||
|
||||
```ts
|
||||
import { dayOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
dayOfYear(new Date("2019-03-11T03:24:00")); // output: 70
|
||||
```
|
||||
|
||||
### weekOfYear
|
||||
|
||||
Returns the ISO week number of the provided date (1-53).
|
||||
|
||||
```ts
|
||||
import { weekOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
weekOfYear(new Date("2020-12-28T03:24:00")); // Returns 53
|
||||
```
|
||||
|
||||
### toIMF
|
||||
|
||||
Formats the given date to IMF date time format. (Reference:
|
||||
https://tools.ietf.org/html/rfc7231#section-7.1.1.1 )
|
||||
|
||||
```ts
|
||||
import { toIMF } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
toIMF(new Date(0)); // => returns "Thu, 01 Jan 1970 00:00:00 GMT"
|
||||
```
|
||||
|
||||
### isLeap
|
||||
|
||||
Returns true if the given date or year (in number) is a leap year. Returns false
|
||||
otherwise.
|
||||
|
||||
```ts
|
||||
import { isLeap } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
isLeap(new Date("1970-01-01")); // => returns false
|
||||
isLeap(new Date("1972-01-01")); // => returns true
|
||||
isLeap(new Date("2000-01-01")); // => returns true
|
||||
isLeap(new Date("2100-01-01")); // => returns false
|
||||
isLeap(1972); // => returns true
|
||||
```
|
||||
|
||||
### difference
|
||||
|
||||
Returns the difference of the 2 given dates in the given units. If the units are
|
||||
omitted, it returns the difference in the all available units.
|
||||
|
||||
Available units: "milliseconds", "seconds", "minutes", "hours", "days", "weeks",
|
||||
"months", "quarters", "years"
|
||||
|
||||
```ts
|
||||
import { difference } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
const date0 = new Date("2018-05-14");
|
||||
const date1 = new Date("2020-05-13");
|
||||
|
||||
difference(date0, date1, { units: ["days", "months", "years"] });
|
||||
// => returns { days: 730, months: 23, years: 1 }
|
||||
|
||||
difference(date0, date1);
|
||||
// => returns {
|
||||
// milliseconds: 63072000000,
|
||||
// seconds: 63072000,
|
||||
// minutes: 1051200,
|
||||
// hours: 17520,
|
||||
// days: 730,
|
||||
// weeks: 104,
|
||||
// months: 23,
|
||||
// quarters: 5,
|
||||
// years: 1
|
||||
// }
|
||||
```
|
||||
|
||||
## Constants
|
||||
|
||||
### SECOND
|
||||
|
||||
```ts
|
||||
import { SECOND } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
console.log(SECOND); // => 1000
|
||||
```
|
||||
|
||||
### MINUTE
|
||||
|
||||
```ts
|
||||
import { MINUTE } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
console.log(MINUTE); // => 60000 (60 * 1000)
|
||||
```
|
||||
|
||||
### HOUR
|
||||
|
||||
```ts
|
||||
import { HOUR } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
console.log(HOUR); // => 3600000 (60 * 60 * 1000)
|
||||
```
|
||||
|
||||
### DAY
|
||||
|
||||
```ts
|
||||
import { DAY } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
console.log(DAY); // => 86400000 (24 * 60 * 60 * 1000)
|
||||
```
|
||||
|
||||
### WEEK
|
||||
|
||||
```ts
|
||||
import { WEEK } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
|
||||
console.log(WEEK); // => 604800000 (7 * 24 * 60 * 60 * 1000)
|
||||
```
|
198
datetime/mod.ts
198
datetime/mod.ts
@ -3,6 +3,34 @@
|
||||
/**
|
||||
* Utilities for dealing with {@linkcode Date} objects.
|
||||
*
|
||||
* The following symbols from
|
||||
* [unicode LDML](http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
|
||||
* are supported:
|
||||
*
|
||||
* - `yyyy` - numeric year.
|
||||
* - `yy` - 2-digit year.
|
||||
* - `M` - numeric month.
|
||||
* - `MM` - 2-digit month.
|
||||
* - `d` - numeric day.
|
||||
* - `dd` - 2-digit day.
|
||||
*
|
||||
* - `H` - numeric hour (0-23 hours).
|
||||
* - `HH` - 2-digit hour (00-23 hours).
|
||||
* - `h` - numeric hour (1-12 hours).
|
||||
* - `hh` - 2-digit hour (01-12 hours).
|
||||
* - `m` - numeric minute.
|
||||
* - `mm` - 2-digit minute.
|
||||
* - `s` - numeric second.
|
||||
* - `ss` - 2-digit second.
|
||||
* - `S` - 1-digit fractionalSecond.
|
||||
* - `SS` - 2-digit fractionalSecond.
|
||||
* - `SSS` - 3-digit fractionalSecond.
|
||||
*
|
||||
* - `a` - dayPeriod, either `AM` or `PM`.
|
||||
*
|
||||
* - `'foo'` - quoted literal.
|
||||
* - `./-` - unquoted literal.
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @module
|
||||
@ -10,10 +38,60 @@
|
||||
|
||||
import { DateTimeFormatter } from "./formatter.ts";
|
||||
|
||||
/**
|
||||
* The number of milliseconds in a second.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { SECOND } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* console.log(SECOND); // => 1000
|
||||
* ```
|
||||
*/
|
||||
export const SECOND = 1e3;
|
||||
/**
|
||||
* The number of milliseconds in a minute.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { MINUTE } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* console.log(MINUTE); // => 60000 (60 * 1000)
|
||||
* ```
|
||||
*/
|
||||
export const MINUTE = SECOND * 60;
|
||||
/**
|
||||
* The number of milliseconds in an hour.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { HOUR } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* console.log(HOUR); // => 3600000 (60 * 60 * 1000)
|
||||
* ```
|
||||
*/
|
||||
export const HOUR = MINUTE * 60;
|
||||
/**
|
||||
* The number of milliseconds in a day.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { DAY } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* console.log(DAY); // => 86400000 (24 * 60 * 60 * 1000)
|
||||
* ```
|
||||
*/
|
||||
export const DAY = HOUR * 24;
|
||||
/**
|
||||
* The number of milliseconds in a week.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { WEEK } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* console.log(WEEK); // => 604800000 (7 * 24 * 60 * 60 * 1000)
|
||||
* ```
|
||||
*/
|
||||
export const WEEK = DAY * 7;
|
||||
const DAYS_PER_WEEK = 7;
|
||||
|
||||
@ -28,9 +106,23 @@ enum Day {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse date from string using format string
|
||||
* Takes an input `string` and a `formatString` to parse to a `date`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { parse } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* parse("20-01-2019", "dd-MM-yyyy"); // output : new Date(2019, 0, 20)
|
||||
* parse("2019-01-20", "yyyy-MM-dd"); // output : new Date(2019, 0, 20)
|
||||
* parse("20.01.2019", "dd.MM.yyyy"); // output : new Date(2019, 0, 20)
|
||||
* parse("01-20-2019 16:34", "MM-dd-yyyy HH:mm"); // output : new Date(2019, 0, 20, 16, 34)
|
||||
* parse("01-20-2019 04:34 PM", "MM-dd-yyyy hh:mm a"); // output : new Date(2019, 0, 20, 16, 34)
|
||||
* parse("16:34 01-20-2019", "HH:mm MM-dd-yyyy"); // output : new Date(2019, 0, 20, 16, 34)
|
||||
* parse("01-20-2019 16:34:23.123", "MM-dd-yyyy HH:mm:ss.SSS"); // output : new Date(2019, 0, 20, 16, 34, 23, 123)
|
||||
* ```
|
||||
*
|
||||
* @param dateString Date string
|
||||
* @param format Format string
|
||||
* @param formatString Format string
|
||||
* @return Parsed date
|
||||
*/
|
||||
export function parse(dateString: string, formatString: string): Date {
|
||||
@ -41,9 +133,24 @@ export function parse(dateString: string, formatString: string): Date {
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date using format string
|
||||
* Takes an input `date` and a `formatString` to format to a `string`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { format } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* format(new Date(2019, 0, 20), "dd-MM-yyyy"); // output : "20-01-2019"
|
||||
* format(new Date(2019, 0, 20), "yyyy-MM-dd"); // output : "2019-01-20"
|
||||
* format(new Date(2019, 0, 20), "dd.MM.yyyy"); // output : "20.01.2019"
|
||||
* format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy HH:mm"); // output : "01-20-2019 16:34"
|
||||
* format(new Date(2019, 0, 20, 16, 34), "MM-dd-yyyy hh:mm a"); // output : "01-20-2019 04:34 PM"
|
||||
* format(new Date(2019, 0, 20, 16, 34), "HH:mm MM-dd-yyyy"); // output : "16:34 01-20-2019"
|
||||
* format(new Date(2019, 0, 20, 16, 34, 23, 123), "MM-dd-yyyy HH:mm:ss.SSS"); // output : "01-20-2019 16:34:23.123"
|
||||
* format(new Date(2019, 0, 20), "'today:' yyyy-MM-dd"); // output : "today: 2019-01-20"
|
||||
* ```
|
||||
*
|
||||
* @param date Date
|
||||
* @param format Format string
|
||||
* @param formatString Format string
|
||||
* @return formatted date string
|
||||
*/
|
||||
export function format(date: Date, formatString: string): string {
|
||||
@ -52,7 +159,15 @@ export function format(date: Date, formatString: string): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of the day in the year
|
||||
* Returns the number of the day in the year.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { dayOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* dayOfYear(new Date("2019-03-11T03:24:00")); // output: 70
|
||||
* ```
|
||||
*
|
||||
* @return Number of the day in year
|
||||
*/
|
||||
export function dayOfYear(date: Date): number {
|
||||
@ -68,7 +183,15 @@ export function dayOfYear(date: Date): number {
|
||||
return Math.floor(diff / DAY);
|
||||
}
|
||||
/**
|
||||
* Get number of the week in the year (ISO-8601)
|
||||
* Returns the ISO week number of the provided date (1-53).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { weekOfYear } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* weekOfYear(new Date("2020-12-28T03:24:00")); // Returns 53
|
||||
* ```
|
||||
*
|
||||
* @return Number of the week in year
|
||||
*/
|
||||
export function weekOfYear(date: Date): number {
|
||||
@ -92,11 +215,18 @@ export function weekOfYear(date: Date): number {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a date to return a IMF formatted string date
|
||||
* RFC: https://tools.ietf.org/html/rfc7231#section-7.1.1.1
|
||||
* Formats the given date to IMF date time format. (Reference:
|
||||
* https://tools.ietf.org/html/rfc7231#section-7.1.1.1).
|
||||
* IMF is the time format to use when generating times in HTTP
|
||||
* headers. The time being formatted must be in UTC for Format to
|
||||
* generate the correct format.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { toIMF } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* toIMF(new Date(0)); // => returns "Thu, 01 Jan 1970 00:00:00 GMT"
|
||||
* ```
|
||||
* @param date Date to parse
|
||||
* @return IMF date formatted string
|
||||
*/
|
||||
@ -130,8 +260,20 @@ export function toIMF(date: Date): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check given year is a leap year or not.
|
||||
* based on : https://docs.microsoft.com/en-us/office/troubleshoot/excel/determine-a-leap-year
|
||||
* Returns whether the given date or year (in number) is a leap year or not.
|
||||
* based on: https://docs.microsoft.com/en-us/office/troubleshoot/excel/determine-a-leap-year
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { isLeap } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* isLeap(new Date("1970-01-01")); // => returns false
|
||||
* isLeap(new Date("1972-01-01")); // => returns true
|
||||
* isLeap(new Date("2000-01-01")); // => returns true
|
||||
* isLeap(new Date("2100-01-01")); // => returns false
|
||||
* isLeap(1972); // => returns true
|
||||
* ```
|
||||
*
|
||||
* @param year year in number or Date format
|
||||
*/
|
||||
export function isLeap(year: Date | number): boolean {
|
||||
@ -159,18 +301,36 @@ export type DifferenceOptions = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate difference between two dates.
|
||||
* Returns the difference of the 2 given dates in the given units. If the units
|
||||
* are omitted, it returns the difference in the all available units.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { difference } from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* const date0 = new Date("2018-05-14");
|
||||
* const date1 = new Date("2020-05-13");
|
||||
*
|
||||
* difference(date0, date1, { units: ["days", "months", "years"] });
|
||||
* // => returns { days: 730, months: 23, years: 1 }
|
||||
*
|
||||
* difference(date0, date1);
|
||||
* // => returns {
|
||||
* // milliseconds: 63072000000,
|
||||
* // seconds: 63072000,
|
||||
* // minutes: 1051200,
|
||||
* // hours: 17520,
|
||||
* // days: 730,
|
||||
* // weeks: 104,
|
||||
* // months: 23,
|
||||
* // quarters: 5,
|
||||
* // years: 1
|
||||
* // }
|
||||
* ```
|
||||
*
|
||||
* @param from Year to calculate difference
|
||||
* @param to Year to calculate difference with
|
||||
* @param options Options for determining how to respond
|
||||
*
|
||||
* example :
|
||||
*
|
||||
* ```typescript
|
||||
* import * as datetime from "https://deno.land/std@$STD_VERSION/datetime/mod.ts";
|
||||
*
|
||||
* datetime.difference(new Date("2020/1/1"),new Date("2020/2/2"),{ units : ["days","months"] })
|
||||
* ```
|
||||
*/
|
||||
export function difference(
|
||||
from: Date,
|
||||
|
166
dotenv/README.md
166
dotenv/README.md
@ -1,166 +0,0 @@
|
||||
# Dotenv handling for deno.
|
||||
|
||||
## Usage
|
||||
|
||||
Setup a `.env` file in the root of your project.
|
||||
|
||||
```sh
|
||||
# .env
|
||||
GREETING=hello world
|
||||
```
|
||||
|
||||
Then import the configuration using the `config` function.
|
||||
|
||||
```ts
|
||||
// app.ts
|
||||
import { config } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
|
||||
|
||||
console.log(await config());
|
||||
```
|
||||
|
||||
Then run your app.
|
||||
|
||||
```
|
||||
> deno run --allow-env --allow-read app.ts
|
||||
{ GREETING: "hello world" }
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
- `path?: string`: Optional path to `.env` file. Defaults to `./.env`.
|
||||
- `export?: boolean`: Set to `true` to export all `.env` variables to the
|
||||
current processes environment. Variables are then accessable via
|
||||
`Deno.env.get(<key>)`. Defaults to `false`.
|
||||
- `safe?: boolean`: Set to `true` to ensure that all necessary environment
|
||||
variables are defined after reading from `.env`. It will read `.env.example`
|
||||
to get the list of needed variables.
|
||||
- `example?: string`: Optional path to `.env.example` file. Defaults to
|
||||
`./.env.example`.
|
||||
- `allowEmptyValues?: boolean`: Set to `true` to allow required env variables to
|
||||
be empty. Otherwise it will throw an error if any variable is empty. Defaults
|
||||
to `false`.
|
||||
- `defaults?: string`: Optional path to `.env.defaults` file which defaults to
|
||||
`./.env.defaults`.
|
||||
- `restrictEnvAccessTo?: Array<string>`: Optional list of Env variables to read
|
||||
from process. Alternatively the complete Env is looked up. This allows to
|
||||
permit access to only specific Env variables with `--allow-env=ENV_VAR_NAME`.
|
||||
|
||||
### Auto loading
|
||||
|
||||
`load.ts` automatically loads the local `.env` file on import and exports it to
|
||||
the process environment:
|
||||
|
||||
```sh
|
||||
# .env
|
||||
GREETING=hello world
|
||||
```
|
||||
|
||||
```ts
|
||||
// app.ts
|
||||
import "https://deno.land/std@$STD_VERSION/dotenv/load.ts";
|
||||
|
||||
console.log(Deno.env.get("GREETING"));
|
||||
```
|
||||
|
||||
```
|
||||
> deno run --allow-env --allow-read app.ts
|
||||
hello world
|
||||
```
|
||||
|
||||
### Safe Mode
|
||||
|
||||
To enable safe mode, create a `.env.example` file in the root of the project.
|
||||
|
||||
```sh
|
||||
# .env.example
|
||||
GREETING=
|
||||
```
|
||||
|
||||
Then import the configuration with `safe` option set to `true`.
|
||||
|
||||
```ts
|
||||
// app.ts
|
||||
import { config } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
|
||||
|
||||
console.log(await config({ safe: true }));
|
||||
```
|
||||
|
||||
If any of the defined variables is not in `.env`, an error will occur. This
|
||||
method is preferred because it prevents runtime errors in a production
|
||||
application due to improper configuration.
|
||||
|
||||
Another way to supply required variables is externally, like so:
|
||||
|
||||
```sh
|
||||
GREETING="hello world" deno run --allow-env app.ts
|
||||
```
|
||||
|
||||
## Default Values
|
||||
|
||||
Default values can be easily added via creating a `.env.defaults` file and using
|
||||
the same format as an`.env` file.
|
||||
|
||||
```sh
|
||||
# .env.defaults
|
||||
# Will not be set if GREETING is set in base .env file
|
||||
GREETING="a secret to everybody"
|
||||
```
|
||||
|
||||
## Parsing Rules
|
||||
|
||||
The parsing engine currently supports the following rules:
|
||||
|
||||
- Variables that already exist in the environment are not overridden with
|
||||
`export: true`
|
||||
- `BASIC=basic` becomes `{ BASIC: "basic" }`
|
||||
- empty lines are skipped
|
||||
- lines beginning with `#` are treated as comments
|
||||
- empty values become empty strings (`EMPTY=` becomes `{ EMPTY: "" }`)
|
||||
- single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes
|
||||
`{ SINGLE_QUOTE: "quoted" }`)
|
||||
- new lines are expanded in double quoted values (`MULTILINE="new\nline"`
|
||||
becomes
|
||||
|
||||
```
|
||||
{ MULTILINE: "new
|
||||
line" }
|
||||
```
|
||||
|
||||
- inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes
|
||||
`{ JSON: "{\"foo\": \"bar\"}" }`)
|
||||
- whitespace is removed from both ends of unquoted values (see more on
|
||||
[`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim))
|
||||
(`FOO= some value` becomes `{ FOO: "some value" }`)
|
||||
- whitespace is preserved on both ends of quoted values (`FOO=" some value "`
|
||||
becomes `{ FOO: " some value " }`)
|
||||
- dollar sign with an environment key in or without curly braces in unquoted
|
||||
values will expand the environment key (`KEY=$KEY` or `KEY=${KEY}` becomes
|
||||
`{ KEY: "<KEY_VALUE_FROM_ENV>" }`)
|
||||
- escaped dollar sign with an environment key in unquoted values will escape the
|
||||
environment key rather than expand (`KEY=\$KEY` becomes `{ KEY: "\\$KEY" }`)
|
||||
- colon and a minus sign with a default value(which can also be another expand
|
||||
value) in expanding construction in unquoted values will first attempt to
|
||||
expand the environment key. If it’s not found, then it will return the default
|
||||
value (`KEY=${KEY:-default}` If KEY exists it becomes
|
||||
`{ KEY: "<KEY_VALUE_FROM_ENV>" }` If not, then it becomes
|
||||
`{ KEY: "default" }`. Also there is possible to do this case
|
||||
`KEY=${NO_SUCH_KEY:-${EXISTING_KEY:-default}}` which becomes
|
||||
`{ KEY: "<EXISTING_KEY_VALUE_FROM_ENV>" }`)
|
||||
|
||||
## Stringify
|
||||
|
||||
```ts
|
||||
import { stringify } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
|
||||
|
||||
const string = stringify({ GREETING: "hello world" });
|
||||
|
||||
console.log(string);
|
||||
/*
|
||||
GREETING='hello world'
|
||||
*/
|
||||
```
|
||||
|
||||
## Credit
|
||||
|
||||
- Inspired by the node module [`dotenv`](https://github.com/motdotla/dotenv)and
|
||||
[`dotenv-expand`](https://github.com/motdotla/dotenv-expand).
|
143
dotenv/mod.ts
143
dotenv/mod.ts
@ -1,6 +1,91 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
/**
|
||||
* Load environment variables from `.env` files.
|
||||
* Inspired by the node module [`dotenv`](https://github.com/motdotla/dotenv) and
|
||||
* [`dotenv-expand`](https://github.com/motdotla/dotenv-expand).
|
||||
*
|
||||
* ```sh
|
||||
* # .env
|
||||
* GREETING=hello world
|
||||
* ```
|
||||
*
|
||||
* Then import the configuration using the `config` function.
|
||||
*
|
||||
* ```ts
|
||||
* // app.ts
|
||||
* import { config } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
|
||||
*
|
||||
* console.log(await config());
|
||||
* ```
|
||||
*
|
||||
* Then run your app.
|
||||
*
|
||||
* ```sh
|
||||
* > deno run --allow-env --allow-read app.ts
|
||||
* { GREETING: "hello world" }
|
||||
* ```
|
||||
*
|
||||
* ## Auto loading
|
||||
*
|
||||
* `load.ts` automatically loads the local `.env` file on import and exports it to
|
||||
* the process environment:
|
||||
*
|
||||
* ```sh
|
||||
* # .env
|
||||
* GREETING=hello world
|
||||
* ```
|
||||
*
|
||||
* ```ts
|
||||
* // app.ts
|
||||
* import "https://deno.land/std@$STD_VERSION/dotenv/load.ts";
|
||||
*
|
||||
* console.log(Deno.env.get("GREETING"));
|
||||
* ```
|
||||
*
|
||||
* ```sh
|
||||
* > deno run --allow-env --allow-read app.ts
|
||||
* hello world
|
||||
* ```
|
||||
*
|
||||
* ## Parsing Rules
|
||||
*
|
||||
* The parsing engine currently supports the following rules:
|
||||
*
|
||||
* - Variables that already exist in the environment are not overridden with
|
||||
* `export: true`
|
||||
* - `BASIC=basic` becomes `{ BASIC: "basic" }`
|
||||
* - empty lines are skipped
|
||||
* - lines beginning with `#` are treated as comments
|
||||
* - empty values become empty strings (`EMPTY=` becomes `{ EMPTY: "" }`)
|
||||
* - single and double quoted values are escaped (`SINGLE_QUOTE='quoted'` becomes
|
||||
* `{ SINGLE_QUOTE: "quoted" }`)
|
||||
* - new lines are expanded in double quoted values (`MULTILINE="new\nline"`
|
||||
* becomes
|
||||
*
|
||||
* ```
|
||||
* { MULTILINE: "new\nline" }
|
||||
* ```
|
||||
*
|
||||
* - inner quotes are maintained (think JSON) (`JSON={"foo": "bar"}` becomes
|
||||
* `{ JSON: "{\"foo\": \"bar\"}" }`)
|
||||
* - whitespace is removed from both ends of unquoted values (see more on
|
||||
* [`trim`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim))
|
||||
* (`FOO= some value` becomes `{ FOO: "some value" }`)
|
||||
* - whitespace is preserved on both ends of quoted values (`FOO=" some value "`
|
||||
* becomes `{ FOO: " some value " }`)
|
||||
* - dollar sign with an environment key in or without curly braces in unquoted
|
||||
* values will expand the environment key (`KEY=$KEY` or `KEY=${KEY}` becomes
|
||||
* `{ KEY: "<KEY_VALUE_FROM_ENV>" }`)
|
||||
* - escaped dollar sign with an environment key in unquoted values will escape the
|
||||
* environment key rather than expand (`KEY=\$KEY` becomes `{ KEY: "\\$KEY" }`)
|
||||
* - colon and a minus sign with a default value(which can also be another expand
|
||||
* value) in expanding construction in unquoted values will first attempt to
|
||||
* expand the environment key. If it’s not found, then it will return the default
|
||||
* value (`KEY=${KEY:-default}` If KEY exists it becomes
|
||||
* `{ KEY: "<KEY_VALUE_FROM_ENV>" }` If not, then it becomes
|
||||
* `{ KEY: "default" }`. Also there is possible to do this case
|
||||
* `KEY=${NO_SUCH_KEY:-${EXISTING_KEY:-default}}` which becomes
|
||||
* `{ KEY: "<EXISTING_KEY_VALUE_FROM_ENV>" }`)
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
@ -14,12 +99,62 @@ export interface DotenvConfig {
|
||||
type StringList = Array<string> | undefined;
|
||||
|
||||
export interface ConfigOptions {
|
||||
/** Optional path to `.env` file.
|
||||
*
|
||||
* @default {"./.env"}
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* Set to `true` to export all `.env` variables to the current processes
|
||||
* environment. Variables are then accessable via `Deno.env.get(<key>)`.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
export?: boolean;
|
||||
/**
|
||||
* Set to `true` to ensure that all necessary environment variables are
|
||||
* defined after reading from `.env`. It will read {@linkcode example} to get the
|
||||
* list of needed variables.
|
||||
*
|
||||
* If any of the defined variables is not in `.env`, an error will occur. This
|
||||
* method is preferred because it prevents runtime errors in a production
|
||||
* application due to improper configuration.
|
||||
* Another way to supply required variables is externally, like so:
|
||||
*
|
||||
* ```sh
|
||||
* GREETING="hello world" deno run --allow-env app.ts
|
||||
* ```
|
||||
*/
|
||||
safe?: boolean;
|
||||
/** Optional path to `.env.example` file.
|
||||
*
|
||||
* @default {"./.env.example"}
|
||||
*/
|
||||
example?: string;
|
||||
/**
|
||||
* Set to `true` to allow required env variables to be empty. Otherwise, it
|
||||
* will throw an error if any variable is empty.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
allowEmptyValues?: boolean;
|
||||
/**
|
||||
* Path to `.env.defaults` file which is used to define default values.
|
||||
*
|
||||
* ```sh
|
||||
* # .env.defaults
|
||||
* # Will not be set if GREETING is set in base .env file
|
||||
* GREETING="a secret to everybody"
|
||||
* ```
|
||||
*
|
||||
* @default {"./.env.defaults"}
|
||||
*/
|
||||
defaults?: string;
|
||||
/**
|
||||
* List of Env variables to read from process. By default, the complete Env is
|
||||
* looked up. This allows to permit access to only specific Env variables with
|
||||
* `--allow-env=ENV_VAR_NAME`.
|
||||
*/
|
||||
restrictEnvAccessTo?: StringList;
|
||||
}
|
||||
|
||||
@ -279,14 +414,16 @@ function expand(str: string, variablesMap: { [key: string]: string }): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object object to be stringified
|
||||
* @returns string of object
|
||||
* @example
|
||||
* ```ts
|
||||
* import { stringify } from "https://deno.land/std@$STD_VERSION/dotenv/mod.ts";
|
||||
*
|
||||
* const object = { GREETING: "hello world" };
|
||||
* const string = stringify(object);
|
||||
* const string = stringify(object); // GREETING='hello world'
|
||||
* ```
|
||||
*
|
||||
* @param object object to be stringified
|
||||
* @returns string of object
|
||||
*/
|
||||
export function stringify(object: DotenvConfig) {
|
||||
const lines: string[] = [];
|
||||
|
@ -1,952 +0,0 @@
|
||||
# encoding
|
||||
|
||||
Helper module for dealing with external data structures.
|
||||
|
||||
- [`ascii85`](#ascii85)
|
||||
- [`base32`](#base32)
|
||||
- [`base64`](#base64)
|
||||
- [`base64url`](#base64url)
|
||||
- [`binary`](#binary)
|
||||
- [`csv`](#csv)
|
||||
- [`front matter`](#front-matter)
|
||||
- [`JSON streaming`](#json-streaming)
|
||||
- [`jsonc`](#jsonc)
|
||||
- [`toml`](#toml)
|
||||
- [`yaml`](#yaml)
|
||||
|
||||
## Binary
|
||||
|
||||
Implements equivalent methods to Go's `encoding/binary` package.
|
||||
|
||||
Available Functions:
|
||||
|
||||
- `sizeof(dataType: DataTypes): number`
|
||||
- `getNBytes(r: Deno.Reader, n: number): Promise<Uint8Array>`
|
||||
- `varnum(b: Uint8Array, o: VarnumOptions = {}): number | null`
|
||||
- `varbig(b: Uint8Array, o: VarbigOptions = {}): bigint | null`
|
||||
- `putVarnum(b: Uint8Array, x: number, o: VarnumOptions = {}): number`
|
||||
- `putVarbig(b: Uint8Array, x: bigint, o: VarbigOptions = {}): number`
|
||||
- `readVarnum(r: Deno.Reader, o: VarnumOptions = {}): Promise<number>`
|
||||
- `readVarbig(r: Deno.Reader, o: VarbigOptions = {}): Promise<bigint>`
|
||||
- `writeVarnum(w: Deno.Writer, x: number, o: VarnumOptions = {}): Promise<number>`
|
||||
- `writeVarbig(w: Deno.Writer, x: bigint, o: VarbigOptions = {}): Promise<number>`
|
||||
|
||||
## CSV
|
||||
|
||||
### API
|
||||
|
||||
#### `readMatrix`
|
||||
|
||||
Parse the CSV from the `reader` with the options provided and return
|
||||
`string[][]`.
|
||||
|
||||
#### `parse`
|
||||
|
||||
Parse the CSV string/buffer with the options provided. The result of this
|
||||
function is as follows:
|
||||
|
||||
- If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns
|
||||
`string[][]`.
|
||||
- If you provide `opt.skipFirstRow` or `opt.columns` it returns
|
||||
`Record<string, unknown>[]`.
|
||||
|
||||
##### `ParseOptions`
|
||||
|
||||
- **`skipFirstRow: boolean;`**: If you provide `skipFirstRow: true` and
|
||||
`columns`, the first line will be skipped. If you provide `skipFirstRow: true`
|
||||
but not `columns`, the first line will be skipped and used as header
|
||||
definitions.
|
||||
- **`columns: string[] | ColumnOptions[];`**: If you provide `string[]` or
|
||||
`ColumnOptions[]`, those names will be used for header definition.
|
||||
|
||||
##### `ColumnOptions`
|
||||
|
||||
- **`name: string;`**: Name of the header to be used as property.
|
||||
|
||||
##### `ReadOptions`
|
||||
|
||||
- **`comma?: string;`**: Character which separates values. Default: `","`.
|
||||
- **`comment?: string;`**: Character to start a comment. Default: `"#"`.
|
||||
- **`trimLeadingSpace?: boolean;`**: Flag to trim the leading space of the
|
||||
value. Default: `false`.
|
||||
- **`lazyQuotes?: boolean;`**: Allow unquoted quote in a quoted field or non
|
||||
double quoted quotes in quoted field. Default: `false`.
|
||||
- **`fieldsPerRecord?`**: Enabling the check of fields for each row. If == 0,
|
||||
first row is used as referral for the number of fields.
|
||||
|
||||
#### `stringify`
|
||||
|
||||
- **`data`** is the source data to stringify. It's an array of items which are
|
||||
plain objects or arrays.
|
||||
|
||||
`DataItem: Record<string, unknown> | unknown[]`
|
||||
|
||||
```ts
|
||||
const data = [
|
||||
{
|
||||
name: "Deno",
|
||||
repo: { org: "denoland", name: "deno" },
|
||||
runsOn: ["Rust", "TypeScript"],
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
- **`columns`** is a list of instructions for how to target and transform the
|
||||
data for each column of output. This is also where you can provide an explicit
|
||||
header name for the column.
|
||||
|
||||
`Column`:
|
||||
|
||||
- The most essential aspect of a column is accessing the property holding the
|
||||
data for that column on each object in the data array. If that member is at
|
||||
the top level, `Column` can simply be a property accessor, which is either a
|
||||
`string` (if it's a plain object) or a `number` (if it's an array).
|
||||
|
||||
```ts
|
||||
const columns = [
|
||||
"name",
|
||||
];
|
||||
```
|
||||
|
||||
Each property accessor will be used as the header for the column:
|
||||
|
||||
| name |
|
||||
| :--: |
|
||||
| Deno |
|
||||
|
||||
- If the required data is not at the top level (it's nested in other
|
||||
objects/arrays), then a simple property accessor won't work, so an array of
|
||||
them will be required.
|
||||
|
||||
```ts
|
||||
const columns = [
|
||||
["repo", "name"],
|
||||
["repo", "org"],
|
||||
];
|
||||
```
|
||||
|
||||
When using arrays of property accessors, the header names inherit the value
|
||||
of the last accessor in each array:
|
||||
|
||||
| name | org |
|
||||
| :--: | :------: |
|
||||
| deno | denoland |
|
||||
|
||||
- If a different column header is desired, then a `ColumnDetails` object type
|
||||
can be used for each column:
|
||||
|
||||
- **`header?: string`** is the optional value to use for the column header
|
||||
name
|
||||
|
||||
- **`prop: PropertyAccessor | PropertyAccessor[]`** is the property accessor
|
||||
(`string` or `number`) or array of property accessors used to access the
|
||||
data on each object
|
||||
|
||||
```ts
|
||||
const columns = [
|
||||
"name",
|
||||
{
|
||||
prop: ["runsOn", 0],
|
||||
header: "language 1",
|
||||
},
|
||||
{
|
||||
prop: ["runsOn", 1],
|
||||
header: "language 2",
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
| name | language 1 | language 2 |
|
||||
| :--: | :--------: | :--------: |
|
||||
| Deno | Rust | TypeScript |
|
||||
|
||||
- **`options`** are options for the delimiter-separated output.
|
||||
|
||||
- **`headers?: boolean`**: Whether or not to include the row of headers.
|
||||
Default: `true`
|
||||
|
||||
- **`separator?: string`**: Delimiter used to separate values. Examples:
|
||||
- `","` _comma_ (Default)
|
||||
- `"\t"` _tab_
|
||||
- `"|"` _pipe_
|
||||
- etc.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```ts
|
||||
import { parse } from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
|
||||
const string = "a,b,c\nd,e,f";
|
||||
|
||||
console.log(
|
||||
parse(string, {
|
||||
skipFirstRow: false,
|
||||
}),
|
||||
);
|
||||
// output:
|
||||
// [["a", "b", "c"], ["d", "e", "f"]]
|
||||
```
|
||||
|
||||
```ts
|
||||
import {
|
||||
Column,
|
||||
stringify,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
|
||||
|
||||
type Character = {
|
||||
age: number;
|
||||
name: {
|
||||
first: string;
|
||||
last: string;
|
||||
};
|
||||
};
|
||||
|
||||
const data: Character[] = [
|
||||
{
|
||||
age: 70,
|
||||
name: {
|
||||
first: "Rick",
|
||||
last: "Sanchez",
|
||||
},
|
||||
},
|
||||
{
|
||||
age: 14,
|
||||
name: {
|
||||
first: "Morty",
|
||||
last: "Smith",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let columns: Column[] = [
|
||||
["name", "first"],
|
||||
"age",
|
||||
];
|
||||
|
||||
console.log(stringify(data, { columns }));
|
||||
// first,age
|
||||
// Rick,70
|
||||
// Morty,14
|
||||
```
|
||||
|
||||
## TOML
|
||||
|
||||
This module parse TOML files. It follows as much as possible the
|
||||
[TOML specs](https://toml.io/en/latest). Be sure to read the supported types as
|
||||
not every specs is supported at the moment and the handling in TypeScript side
|
||||
is a bit different.
|
||||
|
||||
### Supported types and handling
|
||||
|
||||
- :heavy_check_mark: [Keys](https://toml.io/en/latest#keys)
|
||||
- :exclamation: [String](https://toml.io/en/latest#string)
|
||||
- :heavy_check_mark: [Multiline String](https://toml.io/en/latest#string)
|
||||
- :heavy_check_mark: [Literal String](https://toml.io/en/latest#string)
|
||||
- :exclamation: [Integer](https://toml.io/en/latest#integer)
|
||||
- :heavy_check_mark: [Float](https://toml.io/en/latest#float)
|
||||
- :heavy_check_mark: [Boolean](https://toml.io/en/latest#boolean)
|
||||
- :heavy_check_mark:
|
||||
[Offset Date-time](https://toml.io/en/latest#offset-date-time)
|
||||
- :heavy_check_mark:
|
||||
[Local Date-time](https://toml.io/en/latest#local-date-time)
|
||||
- :heavy_check_mark: [Local Date](https://toml.io/en/latest#local-date)
|
||||
- :exclamation: [Local Time](https://toml.io/en/latest#local-time)
|
||||
- :heavy_check_mark: [Table](https://toml.io/en/latest#table)
|
||||
- :heavy_check_mark: [Inline Table](https://toml.io/en/latest#inline-table)
|
||||
- :exclamation: [Array of Tables](https://toml.io/en/latest#array-of-tables)
|
||||
|
||||
:exclamation: _Supported with warnings see [Warning](#Warning)._
|
||||
|
||||
#### :warning: Warning
|
||||
|
||||
##### String
|
||||
|
||||
- Regex : Due to the spec, there is no flag to detect regex properly in a TOML
|
||||
declaration. So the regex is stored as string.
|
||||
|
||||
##### Integer
|
||||
|
||||
For **Binary** / **Octal** / **Hexadecimal** numbers, they are stored as string
|
||||
to be not interpreted as Decimal.
|
||||
|
||||
##### Local Time
|
||||
|
||||
Because local time does not exist in JavaScript, the local time is stored as a
|
||||
string.
|
||||
|
||||
##### Inline Table
|
||||
|
||||
Inline tables are supported. See below:
|
||||
|
||||
```toml
|
||||
animal = { type = { name = "pug" } }
|
||||
## Output { animal: { type: { name: "pug" } } }
|
||||
animal = { type.name = "pug" }
|
||||
## Output { animal: { type : { name : "pug" } }
|
||||
animal.as.leaders = "tosin"
|
||||
## Output { animal: { as: { leaders: "tosin" } } }
|
||||
"tosin.abasi" = "guitarist"
|
||||
## Output { tosin.abasi: "guitarist" }
|
||||
```
|
||||
|
||||
##### Array of Tables
|
||||
|
||||
At the moment only simple declarations like below are supported:
|
||||
|
||||
```toml
|
||||
[[bin]]
|
||||
name = "deno"
|
||||
path = "cli/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "deno_core"
|
||||
path = "src/foo.rs"
|
||||
|
||||
[[nib]]
|
||||
name = "node"
|
||||
path = "not_found"
|
||||
```
|
||||
|
||||
will output:
|
||||
|
||||
```json
|
||||
{
|
||||
"bin": [
|
||||
{ "name": "deno", "path": "cli/main.rs" },
|
||||
{ "name": "deno_core", "path": "src/foo.rs" }
|
||||
],
|
||||
"nib": [{ "name": "node", "path": "not_found" }]
|
||||
}
|
||||
```
|
||||
|
||||
### Basic usage
|
||||
|
||||
```ts
|
||||
import {
|
||||
parse,
|
||||
stringify,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
|
||||
const obj = {
|
||||
bin: [
|
||||
{ name: "deno", path: "cli/main.rs" },
|
||||
{ name: "deno_core", path: "src/foo.rs" },
|
||||
],
|
||||
nib: [{ name: "node", path: "not_found" }],
|
||||
};
|
||||
const tomlString = stringify(obj);
|
||||
console.log(tomlString);
|
||||
|
||||
// =>
|
||||
// [[bin]]
|
||||
// name = "deno"
|
||||
// path = "cli/main.rs"
|
||||
|
||||
// [[bin]]
|
||||
// name = "deno_core"
|
||||
// path = "src/foo.rs"
|
||||
|
||||
// [[nib]]
|
||||
// name = "node"
|
||||
// path = "not_found"
|
||||
|
||||
const tomlObject = parse(tomlString);
|
||||
console.log(tomlObject);
|
||||
|
||||
// =>
|
||||
// {
|
||||
// bin: [
|
||||
// { name: "deno", path: "cli/main.rs" },
|
||||
// { name: "deno_core", path: "src/foo.rs" }
|
||||
// ],
|
||||
// nib: [ { name: "node", path: "not_found" } ]
|
||||
// }
|
||||
```
|
||||
|
||||
## YAML
|
||||
|
||||
YAML parser / dumper for Deno.
|
||||
|
||||
Heavily inspired from [`js-yaml`](https://github.com/nodeca/js-yaml).
|
||||
|
||||
### Basic usage
|
||||
|
||||
`parse` parses the yaml string, and `stringify` dumps the given object to YAML
|
||||
string.
|
||||
|
||||
```ts
|
||||
import {
|
||||
parse,
|
||||
stringify,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
|
||||
|
||||
const data = parse(`
|
||||
foo: bar
|
||||
baz:
|
||||
- qux
|
||||
- quux
|
||||
`);
|
||||
console.log(data);
|
||||
// => { foo: "bar", baz: [ "qux", "quux" ] }
|
||||
|
||||
const yaml = stringify({ foo: "bar", baz: ["qux", "quux"] });
|
||||
console.log(yaml);
|
||||
// =>
|
||||
// foo: bar
|
||||
// baz:
|
||||
// - qux
|
||||
// - quux
|
||||
```
|
||||
|
||||
If your YAML contains multiple documents in it, you can use `parseAll` for
|
||||
handling it.
|
||||
|
||||
```ts
|
||||
import { parseAll } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
|
||||
|
||||
const data = parseAll(`
|
||||
---
|
||||
id: 1
|
||||
name: Alice
|
||||
---
|
||||
id: 2
|
||||
name: Bob
|
||||
---
|
||||
id: 3
|
||||
name: Eve
|
||||
`);
|
||||
console.log(data);
|
||||
// => [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, { id: 3, name: "Eve" } ]
|
||||
```
|
||||
|
||||
To handle `regexp`, and `undefined` types, use the `EXTENDED_SCHEMA`. Note that
|
||||
functions are no longer supported for security reasons
|
||||
|
||||
```ts
|
||||
import {
|
||||
EXTENDED_SCHEMA,
|
||||
parse,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
|
||||
|
||||
const data = parse(
|
||||
`
|
||||
regexp:
|
||||
simple: !!js/regexp foobar
|
||||
modifiers: !!js/regexp /foobar/mi
|
||||
undefined: !!js/undefined ~
|
||||
# Disabled, see: https://github.com/denoland/deno_std/pull/1275
|
||||
# function: !!js/function >
|
||||
# function foobar() {
|
||||
# return 'hello world!';
|
||||
# }
|
||||
`,
|
||||
{ schema: EXTENDED_SCHEMA },
|
||||
);
|
||||
```
|
||||
|
||||
You can also use custom types by extending schemas.
|
||||
|
||||
```ts
|
||||
import {
|
||||
DEFAULT_SCHEMA,
|
||||
parse,
|
||||
Type,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
|
||||
|
||||
const yaml = "...";
|
||||
const MyYamlType = new Type("!myYamlType", {
|
||||
kind: "sequence",
|
||||
/* other type options here*/
|
||||
});
|
||||
const MY_SCHEMA = DEFAULT_SCHEMA.extend({ explicit: [MyYamlType] });
|
||||
|
||||
parse(yaml, { schema: MY_SCHEMA });
|
||||
```
|
||||
|
||||
### API
|
||||
|
||||
#### `parse(str: string, opts?: ParserOption): unknown`
|
||||
|
||||
Parses the YAML string with a single document.
|
||||
|
||||
#### `parseAll(str: string, iterator?: Function, opts?: ParserOption): unknown`
|
||||
|
||||
Parses the YAML string with multiple documents. If the iterator is given, it's
|
||||
applied to every document instead of returning the array of parsed objects.
|
||||
|
||||
#### `stringify(obj: object, opts?: DumpOption): string`
|
||||
|
||||
Serializes `object` as a YAML document.
|
||||
|
||||
### :warning: Limitations
|
||||
|
||||
- `binary` type is currently not stable.
|
||||
|
||||
### More example
|
||||
|
||||
See: https://github.com/nodeca/js-yaml/tree/master/examples
|
||||
|
||||
## JSON streaming
|
||||
|
||||
Streams JSON concatenated with line breaks or special characters. This module
|
||||
supports the following formats:
|
||||
|
||||
- [JSON lines](https://jsonlines.org/)
|
||||
- [NDJSON](http://ndjson.org/)
|
||||
- [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464)
|
||||
- [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON)
|
||||
- JSON concatenated with any delimiter
|
||||
|
||||
### Basic usage
|
||||
|
||||
If you want to parse JSON separated by a delimiter, use `TextLineStream` (or
|
||||
`TextDelimiterStream`) and `JsonParseStream`. `JsonParseStream` ignores chunks
|
||||
consisting of spaces, tab characters, or newline characters .
|
||||
|
||||
```ts
|
||||
// parse JSON lines or NDJSON
|
||||
import { TextLineStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
|
||||
const url =
|
||||
"https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.jsonl";
|
||||
const { body } = await fetch(url);
|
||||
|
||||
const readable = body!
|
||||
.pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
|
||||
.pipeThrough(new TextLineStream()) // transform into a stream where each chunk is divided by a newline
|
||||
.pipeThrough(new JsonParseStream()); // parse each chunk as JSON
|
||||
|
||||
for await (const data of readable) {
|
||||
console.log(data);
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
// parse JSON Text Sequences
|
||||
import { TextDelimiterStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
|
||||
const url =
|
||||
"https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.json-seq";
|
||||
const { body } = await fetch(url);
|
||||
|
||||
const delimiter = "\x1E";
|
||||
const readable = body!
|
||||
.pipeThrough(new TextDecoderStream())
|
||||
.pipeThrough(new TextDelimiterStream(delimiter)) // transform into a stream where each chunk is divided by a delimiter
|
||||
.pipeThrough(new JsonParseStream());
|
||||
|
||||
for await (const data of readable) {
|
||||
console.log(data);
|
||||
}
|
||||
```
|
||||
|
||||
If you want to parse
|
||||
[Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON),
|
||||
use `ConcatenatedJsonParseStream`.
|
||||
|
||||
```ts
|
||||
import { ConcatenatedJsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
|
||||
const url =
|
||||
"https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.concatenated-json";
|
||||
const { body } = await fetch(url);
|
||||
|
||||
const readable = body!
|
||||
.pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
|
||||
.pipeThrough(new ConcatenatedJsonParseStream()); // parse Concatenated JSON
|
||||
|
||||
for await (const data of readable) {
|
||||
console.log(data);
|
||||
}
|
||||
```
|
||||
|
||||
Use `JsonStringifyStream` to transform streaming data to
|
||||
[JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/),
|
||||
[NDJSON](http://ndjson.org/) or
|
||||
[Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
|
||||
|
||||
By default, `JsonStringifyStream` adds "\n" as a suffix after each chunk.
|
||||
|
||||
```ts
|
||||
import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
|
||||
const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
|
||||
|
||||
readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
|
||||
.pipeThrough(new JsonStringifyStream()) // convert to JSON lines (ndjson)
|
||||
.pipeThrough(new TextEncoderStream()) // convert a string to a Uint8Array
|
||||
.pipeTo(file.writable)
|
||||
.then(() => console.log("write success"));
|
||||
```
|
||||
|
||||
If you want to use an arbitrary delimiter, specify prefix and suffix as options.
|
||||
These are added before and after chunk after stringify. To convert to
|
||||
[JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464), set the
|
||||
prefix to the delimiter "\x1E" as options.
|
||||
|
||||
```ts
|
||||
import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
|
||||
const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
|
||||
|
||||
readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
|
||||
.pipeThrough(new JsonStringifyStream({ prefix: "\x1E", suffix: "\n" })) // convert to JSON Text Sequences
|
||||
.pipeThrough(new TextEncoderStream())
|
||||
.pipeTo(file.writable)
|
||||
.then(() => console.log("write success"));
|
||||
```
|
||||
|
||||
If you want to stream [JSON lines](https://jsonlines.org/) from the server:
|
||||
|
||||
```ts
|
||||
import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts";
|
||||
import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
|
||||
// A server that streams one line of JSON every second
|
||||
serve(() => {
|
||||
let intervalId: number | undefined;
|
||||
const readable = new ReadableStream({
|
||||
start(controller) {
|
||||
// enqueue data once per second
|
||||
intervalId = setInterval(() => {
|
||||
controller.enqueue({ now: new Date() });
|
||||
}, 1000);
|
||||
},
|
||||
cancel() {
|
||||
clearInterval(intervalId);
|
||||
},
|
||||
});
|
||||
|
||||
const body = readable
|
||||
.pipeThrough(new JsonStringifyStream()) // convert data to JSON lines
|
||||
.pipeThrough(new TextEncoderStream()); // convert a string to a Uint8Array
|
||||
|
||||
return new Response(body);
|
||||
});
|
||||
```
|
||||
|
||||
## JSONC
|
||||
|
||||
JSONC (JSON with Comments) parser for Deno.
|
||||
|
||||
### API
|
||||
|
||||
#### `parse(text: string, options: { allowTrailingComma?: boolean; })`
|
||||
|
||||
Parses the JSONC string. Setting allowTrailingComma to false rejects trailing
|
||||
commas in objects and arrays. If parsing fails, throw a SyntaxError.
|
||||
|
||||
### Basic usage
|
||||
|
||||
```ts
|
||||
import * as JSONC from "https://deno.land/std@$STD_VERSION/encoding/jsonc.ts";
|
||||
|
||||
console.log(JSONC.parse('{"foo": "bar", } // comment')); //=> { foo: "bar" }
|
||||
console.log(JSONC.parse('{"foo": "bar", } /* comment */')); //=> { foo: "bar" }
|
||||
console.log(JSONC.parse('{"foo": "bar" } // comment', {
|
||||
allowTrailingComma: false,
|
||||
})); //=> { foo: "bar" }
|
||||
```
|
||||
|
||||
## base32
|
||||
|
||||
[RFC4648 base32](https://tools.ietf.org/html/rfc4648#section-6) encoder/decoder
|
||||
for Deno.
|
||||
|
||||
### Basic usage
|
||||
|
||||
`encode` encodes a `Uint8Array` to RFC4648 base32 representation, and `decode`
|
||||
decodes the given RFC4648 base32 representation to a `Uint8Array`.
|
||||
|
||||
```ts
|
||||
import {
|
||||
decode,
|
||||
encode,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/base32.ts";
|
||||
|
||||
const b32Repr = "RC2E6GA=";
|
||||
|
||||
const binaryData = decode(b32Repr);
|
||||
console.log(binaryData);
|
||||
// => Uint8Array [ 136, 180, 79, 24 ]
|
||||
|
||||
console.log(encode(binaryData));
|
||||
// => RC2E6GA=
|
||||
```
|
||||
|
||||
## base64
|
||||
|
||||
[RFC4648 base64](https://tools.ietf.org/html/rfc4648#section-4) encoder/decoder
|
||||
for Deno.
|
||||
|
||||
### Basic usage
|
||||
|
||||
`encode` encodes a `Uint8Array` to RFC4648 base64 representation, and `decode`
|
||||
decodes the given RFC4648 base64 representation to a `Uint8Array`.
|
||||
|
||||
```ts
|
||||
import {
|
||||
decode,
|
||||
encode,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/base64.ts";
|
||||
|
||||
const b64Repr = "Zm9vYg==";
|
||||
|
||||
const binaryData = decode(b64Repr);
|
||||
console.log(binaryData);
|
||||
// => Uint8Array [ 102, 111, 111, 98 ]
|
||||
|
||||
console.log(encode(binaryData));
|
||||
// => Zm9vYg==
|
||||
```
|
||||
|
||||
## base64url
|
||||
|
||||
[RFC4648 base64url](https://datatracker.ietf.org/doc/html/rfc4648#section-5)
|
||||
encoder/decoder for Deno.
|
||||
|
||||
### Basic usage
|
||||
|
||||
`encode` encodes a `Uint8Array` to RFC4648 base64url representation, and
|
||||
`decode` decodes the given RFC4648 base64url representation to a `Uint8Array`.
|
||||
|
||||
```ts
|
||||
import {
|
||||
decode,
|
||||
encode,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/base64url.ts";
|
||||
|
||||
const binary = new TextEncoder().encode("foobar");
|
||||
const encoded = encode(binary);
|
||||
console.log(encoded);
|
||||
// => "Zm9vYmFy"
|
||||
|
||||
console.log(decode(encoded));
|
||||
// => Uint8Array(6) [ 102, 111, 111, 98, 97, 114 ]
|
||||
```
|
||||
|
||||
## ascii85
|
||||
|
||||
Ascii85/base85 encoder and decoder with support for multiple standards.
|
||||
|
||||
### Basic usage
|
||||
|
||||
`encode` encodes a `Uint8Array` to a ascii85 representation, and `decode`
|
||||
decodes the given ascii85 representation to a `Uint8Array`.
|
||||
|
||||
```ts
|
||||
import {
|
||||
decode,
|
||||
encode,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/ascii85.ts";
|
||||
|
||||
const a85Repr = "LpTqp";
|
||||
|
||||
const binaryData = decode(a85Repr);
|
||||
console.log(binaryData);
|
||||
// => Uint8Array [ 136, 180, 79, 24 ]
|
||||
|
||||
console.log(encode(binaryData));
|
||||
// => LpTqp
|
||||
```
|
||||
|
||||
### Specifying a standard and delimiter
|
||||
|
||||
By default all functions are using the most popular Adobe version of ascii85 and
|
||||
not adding any delimiter. However, there are three more standards supported -
|
||||
btoa (different delimiter and additional compression of 4 bytes equal to 32),
|
||||
[Z85](https://rfc.zeromq.org/spec/32/) and
|
||||
[RFC 1924](https://tools.ietf.org/html/rfc1924). It's possible to use a
|
||||
different encoding by specifying it in `options` object as a second parameter.
|
||||
|
||||
Similarly, it's possible to make `encode` add a delimiter (`<~` and `~>` for
|
||||
Adobe, `xbtoa Begin` and `xbtoa End` with newlines between the delimiters and
|
||||
encoded data for btoa. Checksums for btoa are not supported. Delimiters are not
|
||||
supported by other encodings.)
|
||||
|
||||
encoding examples:
|
||||
|
||||
```ts
|
||||
import {
|
||||
decode,
|
||||
encode,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/ascii85.ts";
|
||||
const binaryData = new Uint8Array([136, 180, 79, 24]);
|
||||
console.log(encode(binaryData));
|
||||
// => LpTqp
|
||||
console.log(encode(binaryData, { standard: "Adobe", delimiter: true }));
|
||||
// => <~LpTqp~>
|
||||
console.log(encode(binaryData, { standard: "btoa", delimiter: true }));
|
||||
/* => xbtoa Begin
|
||||
LpTqp
|
||||
xbtoa End */
|
||||
console.log(encode(binaryData, { standard: "RFC 1924" }));
|
||||
// => h_p`_
|
||||
console.log(encode(binaryData, { standard: "Z85" }));
|
||||
// => H{P}{
|
||||
```
|
||||
|
||||
## hex
|
||||
|
||||
hexadecimal encoder/decoder for Deno.
|
||||
|
||||
### Basic usage
|
||||
|
||||
`encode` encodes a `Uint8Array` to hexadecimal `Uint8Array` with 2 * length, and
|
||||
`decode` decodes the given hexadecimal `Uint8Array` to a `Uint8Array`.
|
||||
|
||||
```ts
|
||||
import {
|
||||
decode,
|
||||
encode,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/hex.ts";
|
||||
|
||||
const binary = new TextEncoder().encode("abc");
|
||||
const encoded = encode(binary);
|
||||
console.log(encoded);
|
||||
// => Uint8Array(6) [ 54, 49, 54, 50, 54, 51 ]
|
||||
|
||||
console.log(decode(encoded));
|
||||
// => Uint8Array(3) [ 97, 98, 99 ]
|
||||
```
|
||||
|
||||
## Front Matter
|
||||
|
||||
Extracts
|
||||
[front matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/)
|
||||
from strings.
|
||||
|
||||
Supported formats:
|
||||
|
||||
- [`YAML`](./front_matter/yaml.ts)
|
||||
- [`TOML`](./front_matter/toml.ts)
|
||||
- [`JSON`](./front_matter/json.ts)
|
||||
|
||||
### Basic usage
|
||||
|
||||
example.md
|
||||
|
||||
```
|
||||
---
|
||||
module: front_matter
|
||||
tags:
|
||||
- yaml
|
||||
- toml
|
||||
- json
|
||||
---
|
||||
|
||||
deno is awesome
|
||||
```
|
||||
|
||||
example.ts
|
||||
|
||||
```ts
|
||||
import {
|
||||
extract,
|
||||
test,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/front_matter/any.ts";
|
||||
|
||||
const str = await Deno.readTextFile("./example.md");
|
||||
|
||||
if (test(str)) {
|
||||
console.log(extract(str));
|
||||
} else {
|
||||
console.log("document doesn't contain front matter");
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
$ deno run ./example.ts
|
||||
{
|
||||
frontMatter: "module: front_matter\ntags:\n - yaml\n - toml\n - json",
|
||||
body: "deno is awesome",
|
||||
attrs: { module: "front_matter", tags: [ "yaml", "toml", "json" ] }
|
||||
}
|
||||
```
|
||||
|
||||
The above example recognizes any of the supported formats, extracts metadata and
|
||||
parses accordingly. Please note that in this case both the [YAML](#yaml) and
|
||||
[TOML](#toml) parsers will be imported as dependencies.
|
||||
|
||||
If you need only one specific format then you can import the file named
|
||||
respectively from [here](./front_matter).
|
||||
|
||||
### Advanced usage
|
||||
|
||||
```ts
|
||||
import {
|
||||
createExtractor,
|
||||
Format,
|
||||
Parser,
|
||||
test as _test,
|
||||
} from "https://deno.land/std@$STD_VERSION/encoding/front_matter/mod.ts";
|
||||
import { parse } from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
|
||||
|
||||
const extract = createExtractor({
|
||||
[Format.TOML]: parse as Parser,
|
||||
[Format.JSON]: JSON.parse as Parser,
|
||||
});
|
||||
|
||||
export function test(str: string): boolean {
|
||||
return _test(str, [Format.TOML, Format.JSON]);
|
||||
}
|
||||
```
|
||||
|
||||
In this setup `extract()` and `test()` will work with TOML and JSON and only.
|
||||
This way the YAML parser is not loaded if not needed. You can cherry-pick which
|
||||
combination of formats are you supporting based on your needs.
|
||||
|
||||
### Delimiters
|
||||
|
||||
#### YAML
|
||||
|
||||
```
|
||||
---
|
||||
these: are
|
||||
---
|
||||
```
|
||||
|
||||
```
|
||||
---yaml
|
||||
all: recognized
|
||||
---
|
||||
```
|
||||
|
||||
```
|
||||
= yaml =
|
||||
as: yaml
|
||||
= yaml =
|
||||
```
|
||||
|
||||
#### TOML
|
||||
|
||||
```
|
||||
---toml
|
||||
this = 'is'
|
||||
---
|
||||
```
|
||||
|
||||
```
|
||||
= toml =
|
||||
parsed = 'as'
|
||||
toml = 'data'
|
||||
= toml =
|
||||
```
|
||||
|
||||
#### JSON
|
||||
|
||||
```
|
||||
---json
|
||||
{
|
||||
"and": "this"
|
||||
}
|
||||
---
|
||||
```
|
||||
|
||||
```
|
||||
{
|
||||
"is": "JSON"
|
||||
}
|
||||
```
|
@ -21,6 +21,25 @@ export function parse(content: string, options?: ParseOptions): unknown {
|
||||
/**
|
||||
* Same as `parse()`, but understands multi-document sources.
|
||||
* Applies iterator to each document if specified, or returns array of documents.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { parseAll } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
|
||||
*
|
||||
* const data = parseAll(`
|
||||
* ---
|
||||
* id: 1
|
||||
* name: Alice
|
||||
* ---
|
||||
* id: 2
|
||||
* name: Bob
|
||||
* ---
|
||||
* id: 3
|
||||
* name: Eve
|
||||
* `);
|
||||
* console.log(data);
|
||||
* // => [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" }, { id: 3, name: "Eve" } ]
|
||||
* ```
|
||||
*/
|
||||
export function parseAll(
|
||||
content: string,
|
||||
|
@ -4,8 +4,34 @@ import { Schema } from "../schema.ts";
|
||||
import { regexp, undefinedType } from "../type/mod.ts";
|
||||
import { def } from "./default.ts";
|
||||
|
||||
// Extends JS-YAML default schema with additional JavaScript types
|
||||
// It is not described in the YAML specification.
|
||||
/***
|
||||
* Extends JS-YAML default schema with additional JavaScript types
|
||||
* It is not described in the YAML specification.
|
||||
* Functions are no longer supported for security reasons.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* EXTENDED_SCHEMA,
|
||||
* parse,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
|
||||
*
|
||||
* const data = parse(
|
||||
* `
|
||||
* regexp:
|
||||
* simple: !!js/regexp foobar
|
||||
* modifiers: !!js/regexp /foobar/mi
|
||||
* undefined: !!js/undefined ~
|
||||
* # Disabled, see: https://github.com/denoland/deno_std/pull/1275
|
||||
* # function: !!js/function >
|
||||
* # function foobar() {
|
||||
* # return 'hello world!';
|
||||
* # }
|
||||
* `,
|
||||
* { schema: EXTENDED_SCHEMA },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export const extended = new Schema({
|
||||
explicit: [regexp, undefinedType],
|
||||
include: [def],
|
||||
|
@ -6,18 +6,50 @@
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* ## Specifying a standard and delimiter
|
||||
*
|
||||
* By default, all functions are using the most popular Adobe version of ascii85
|
||||
* and not adding any delimiter. However, there are three more standards
|
||||
* supported - btoa (different delimiter and additional compression of 4 bytes
|
||||
* equal to 32), [Z85](https://rfc.zeromq.org/spec/32/) and
|
||||
* [RFC 1924](https://tools.ietf.org/html/rfc1924). It's possible to use a
|
||||
* different encoding by specifying it in `options` object as a second parameter.
|
||||
*
|
||||
* Similarly, it's possible to make `encode` add a delimiter (`<~` and `~>` for
|
||||
* Adobe, `xbtoa Begin` and `xbtoa End` with newlines between the delimiters and
|
||||
* encoded data for btoa. Checksums for btoa are not supported. Delimiters are not
|
||||
* supported by other encodings.)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* decode,
|
||||
* encode,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/ascii85.ts";
|
||||
*
|
||||
* const a85Repr = "LpTqp";
|
||||
*
|
||||
* const binaryData = decode(a85Repr);
|
||||
* console.log(binaryData);
|
||||
* // => Uint8Array [ 136, 180, 79, 24 ]
|
||||
*
|
||||
* console.log(encode(binaryData));
|
||||
* // => LpTqp
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
export type Ascii85Standard = "Adobe" | "btoa" | "RFC 1924" | "Z85";
|
||||
|
||||
/**
|
||||
* encoding/decoding options
|
||||
* @property standard - characterset and delimiter (if supported and used). Defaults to Adobe
|
||||
* @property delimiter - whether to use a delimiter (if supported) - "<~" and "~>" by default
|
||||
*/
|
||||
/** encoding/decoding options */
|
||||
export interface Ascii85Options {
|
||||
/** characterset and delimiter (if supported and used).
|
||||
*
|
||||
* @default {"Adobe"}
|
||||
*/
|
||||
standard?: Ascii85Standard;
|
||||
/** whether to use a delimiter (if supported) - "<~" and "~>" by default */
|
||||
delimiter?: boolean;
|
||||
}
|
||||
const rfc1924 =
|
||||
|
@ -9,6 +9,23 @@
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* decode,
|
||||
* encode,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/base32.ts";
|
||||
*
|
||||
* const b32Repr = "RC2E6GA=";
|
||||
*
|
||||
* const binaryData = decode(b32Repr);
|
||||
* console.log(binaryData);
|
||||
* // => Uint8Array [ 136, 180, 79, 24 ]
|
||||
*
|
||||
* console.log(encode(binaryData));
|
||||
* // => RC2E6GA=
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -6,6 +6,23 @@
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* decode,
|
||||
* encode,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/base64.ts";
|
||||
*
|
||||
* const b64Repr = "Zm9vYg==";
|
||||
*
|
||||
* const binaryData = decode(b64Repr);
|
||||
* console.log(binaryData);
|
||||
* // => Uint8Array [ 102, 111, 111, 98 ]
|
||||
*
|
||||
* console.log(encode(binaryData));
|
||||
* // => Zm9vYg==
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -6,6 +6,22 @@
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* decode,
|
||||
* encode,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/base64url.ts";
|
||||
*
|
||||
* const binary = new TextEncoder().encode("foobar");
|
||||
* const encoded = encode(binary);
|
||||
* console.log(encoded);
|
||||
* // => "Zm9vYmFy"
|
||||
*
|
||||
* console.log(decode(encoded));
|
||||
* // => Uint8Array(6) [ 102, 111, 111, 98, 97, 114 ]
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
176
encoding/csv.ts
176
encoding/csv.ts
@ -60,6 +60,70 @@ export type ColumnDetails = {
|
||||
prop: PropertyAccessor | PropertyAccessor[];
|
||||
};
|
||||
|
||||
/**
|
||||
* The most essential aspect of a column is accessing the property holding the
|
||||
* data for that column on each object in the data array. If that member is at
|
||||
* the top level, `Column` can simply be a property accessor, which is either a
|
||||
* `string` (if it's a plain object) or a `number` (if it's an array).
|
||||
*
|
||||
* ```ts
|
||||
* const columns = [
|
||||
* "name",
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* Each property accessor will be used as the header for the column:
|
||||
*
|
||||
* | name |
|
||||
* | :--: |
|
||||
* | Deno |
|
||||
*
|
||||
* - If the required data is not at the top level (it's nested in other
|
||||
* objects/arrays), then a simple property accessor won't work, so an array of
|
||||
* them will be required.
|
||||
*
|
||||
* ```ts
|
||||
* const columns = [
|
||||
* ["repo", "name"],
|
||||
* ["repo", "org"],
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* When using arrays of property accessors, the header names inherit the value
|
||||
* of the last accessor in each array:
|
||||
*
|
||||
* | name | org |
|
||||
* | :--: | :------: |
|
||||
* | deno | denoland |
|
||||
*
|
||||
* - If a different column header is desired, then a `ColumnDetails` object type
|
||||
* can be used for each column:
|
||||
*
|
||||
* - **`header?: string`** is the optional value to use for the column header
|
||||
* name
|
||||
*
|
||||
* - **`prop: PropertyAccessor | PropertyAccessor[]`** is the property accessor
|
||||
* (`string` or `number`) or array of property accessors used to access the
|
||||
* data on each object
|
||||
*
|
||||
* ```ts
|
||||
* const columns = [
|
||||
* "name",
|
||||
* {
|
||||
* prop: ["runsOn", 0],
|
||||
* header: "language 1",
|
||||
* },
|
||||
* {
|
||||
* prop: ["runsOn", 1],
|
||||
* header: "language 2",
|
||||
* },
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* | name | language 1 | language 2 |
|
||||
* | :--: | :--------: | :--------: |
|
||||
* | Deno | Rust | TypeScript |
|
||||
*/
|
||||
export type Column = ColumnDetails | PropertyAccessor | PropertyAccessor[];
|
||||
|
||||
type NormalizedColumn = Omit<ColumnDetails, "header" | "prop"> & {
|
||||
@ -138,24 +202,89 @@ function getValuesFromItem(
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param headers Whether or not to include the row of headers.
|
||||
* Default: `true`
|
||||
*
|
||||
* @param separator Delimiter used to separate values. Examples:
|
||||
* - `","` _comma_ (Default)
|
||||
* - `"\t"` _tab_
|
||||
* - `"|"` _pipe_
|
||||
* - etc.
|
||||
*/
|
||||
export type StringifyOptions = {
|
||||
/** Whether to include the row of headers or not.
|
||||
*
|
||||
* @default {true}
|
||||
*/
|
||||
headers?: boolean;
|
||||
/**
|
||||
* Delimiter used to separate values. Examples:
|
||||
* - `","` _comma_
|
||||
* - `"\t"` _tab_
|
||||
* - `"|"` _pipe_
|
||||
* - etc.
|
||||
*
|
||||
* @default {","}
|
||||
*/
|
||||
separator?: string;
|
||||
/**
|
||||
* a list of instructions for how to target and transform the data for each
|
||||
* column of output. This is also where you can provide an explicit header
|
||||
* name for the column.
|
||||
*/
|
||||
columns?: Column[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @param data The array of objects to encode
|
||||
* @param data The source data to stringify. It's an array of items which are
|
||||
* plain objects or arrays.
|
||||
*
|
||||
* `DataItem: Record<string, unknown> | unknown[]`
|
||||
*
|
||||
* ```ts
|
||||
* const data = [
|
||||
* {
|
||||
* name: "Deno",
|
||||
* repo: { org: "denoland", name: "deno" },
|
||||
* runsOn: ["Rust", "TypeScript"],
|
||||
* },
|
||||
* ];
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* Column,
|
||||
* stringify,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
|
||||
*
|
||||
* type Character = {
|
||||
* age: number;
|
||||
* name: {
|
||||
* first: string;
|
||||
* last: string;
|
||||
* };
|
||||
* };
|
||||
*
|
||||
* const data: Character[] = [
|
||||
* {
|
||||
* age: 70,
|
||||
* name: {
|
||||
* first: "Rick",
|
||||
* last: "Sanchez",
|
||||
* },
|
||||
* },
|
||||
* {
|
||||
* age: 14,
|
||||
* name: {
|
||||
* first: "Morty",
|
||||
* last: "Smith",
|
||||
* },
|
||||
* },
|
||||
* ];
|
||||
*
|
||||
* let columns: Column[] = [
|
||||
* ["name", "first"],
|
||||
* "age",
|
||||
* ];
|
||||
*
|
||||
* console.log(stringify(data, { columns }));
|
||||
* // first,age
|
||||
* // Rick,70
|
||||
* // Morty,14
|
||||
* ```
|
||||
*
|
||||
* @param options Output formatting options
|
||||
*/
|
||||
export function stringify(
|
||||
@ -194,20 +323,35 @@ export function stringify(
|
||||
|
||||
export interface ParseOptions extends ReadOptions {
|
||||
/**
|
||||
* If you provide `skipFirstRow: true` and `columns`, the first line will be skipped.
|
||||
* If you provide `skipFirstRow: true` but not `columns`, the first line will be skipped and used as header definitions.
|
||||
* If you provide `skipFirstRow: true` and `columns`, the first line will be
|
||||
* skipped.
|
||||
* If you provide `skipFirstRow: true` but not `columns`, the first line will
|
||||
* be skipped and used as header definitions.
|
||||
*/
|
||||
skipFirstRow?: boolean;
|
||||
|
||||
/**
|
||||
* If you provide `string[]` or `ColumnOptions[]`, those names will be used for header definition.
|
||||
*/
|
||||
/** List of names used for header definition. */
|
||||
columns?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Csv parse helper to manipulate data.
|
||||
* Provides an auto/custom mapper for columns.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { parse } from "https://deno.land/std@$STD_VERSION/encoding/csv.ts";
|
||||
* const string = "a,b,c\nd,e,f";
|
||||
*
|
||||
* console.log(
|
||||
* await parse(string, {
|
||||
* skipFirstRow: false,
|
||||
* }),
|
||||
* );
|
||||
* // output:
|
||||
* // [["a", "b", "c"], ["d", "e", "f"]]
|
||||
* ```
|
||||
*
|
||||
* @param input Input to parse.
|
||||
* @param opt options of the parser.
|
||||
* @returns If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns `string[][]`.
|
||||
|
@ -5,21 +5,33 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert } from "../../_util/asserts.ts";
|
||||
|
||||
/**
|
||||
* @property separator - Character which separates values. Default: ','
|
||||
* @property comment - Character to start a comment. Default: '#'
|
||||
* @property trimLeadingSpace - Flag to trim the leading space of the value.
|
||||
* Default: 'false'
|
||||
* @property lazyQuotes - Allow unquoted quote in a quoted field or non double
|
||||
* quoted quotes in quoted field. Default: 'false'
|
||||
* @property fieldsPerRecord - Enabling the check of fields for each row.
|
||||
* If == 0, first row is used as referral for the number of fields.
|
||||
*/
|
||||
export interface ReadOptions {
|
||||
/** Character which separates values.
|
||||
*
|
||||
* @default {","}
|
||||
*/
|
||||
separator?: string;
|
||||
/** Character to start a comment.
|
||||
*
|
||||
* @default {"#"}
|
||||
*/
|
||||
comment?: string;
|
||||
/** Flag to trim the leading space of the value.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
trimLeadingSpace?: boolean;
|
||||
/**
|
||||
* Allow unquoted quote in a quoted field or non-double-quoted quotes in
|
||||
* quoted field.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
lazyQuotes?: boolean;
|
||||
/**
|
||||
* Enabling the check of fields for each row. If == 0, first row is used as
|
||||
* referral for the number of fields.
|
||||
*/
|
||||
fieldsPerRecord?: number;
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,149 @@
|
||||
// Copyright (c) Jason Campbell. MIT license
|
||||
|
||||
/**
|
||||
* Extracts
|
||||
* [front matter](https://daily-dev-tips.com/posts/what-exactly-is-frontmatter/)
|
||||
* from strings.
|
||||
*
|
||||
* {@linkcode createExtractor}, {@linkcode recognize} and {@linkcode test} functions
|
||||
* to handle many forms of front matter.
|
||||
*
|
||||
* Adapted from
|
||||
* [jxson/front-matter](https://github.com/jxson/front-matter/blob/36f139ef797bd9e5196a9ede03ef481d7fbca18e/index.js).
|
||||
*
|
||||
* Supported formats:
|
||||
*
|
||||
* - [`YAML`](./front_matter/yaml.ts)
|
||||
* - [`TOML`](./front_matter/toml.ts)
|
||||
* - [`JSON`](./front_matter/json.ts)
|
||||
*
|
||||
* ### Basic usage
|
||||
*
|
||||
* example.md
|
||||
*
|
||||
* ```ignore
|
||||
* ---
|
||||
* module: front_matter
|
||||
* tags:
|
||||
* - yaml
|
||||
* - toml
|
||||
* - json
|
||||
* ---
|
||||
*
|
||||
* deno is awesome
|
||||
* ```
|
||||
*
|
||||
* example.ts
|
||||
*
|
||||
* ```ts
|
||||
* import {
|
||||
* extract,
|
||||
* test,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/front_matter/any.ts";
|
||||
*
|
||||
* const str = await Deno.readTextFile("./example.md");
|
||||
*
|
||||
* if (test(str)) {
|
||||
* console.log(extract(str));
|
||||
* } else {
|
||||
* console.log("document doesn't contain front matter");
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ```ignore
|
||||
* $ deno run ./example.ts
|
||||
* {
|
||||
* frontMatter: "module: front_matter\ntags:\n - yaml\n - toml\n - json",
|
||||
* body: "deno is awesome",
|
||||
* attrs: { module: "front_matter", tags: [ "yaml", "toml", "json" ] }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The above example recognizes any of the supported formats, extracts metadata and
|
||||
* parses accordingly. Please note that in this case both the [YAML](#yaml) and
|
||||
* [TOML](#toml) parsers will be imported as dependencies.
|
||||
*
|
||||
* If you need only one specific format then you can import the file named
|
||||
* respectively from [here](./front_matter).
|
||||
*
|
||||
* ### Advanced usage
|
||||
*
|
||||
* ```ts
|
||||
* import {
|
||||
* createExtractor,
|
||||
* Format,
|
||||
* Parser,
|
||||
* test as _test,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/front_matter/mod.ts";
|
||||
* import { parse } from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
|
||||
*
|
||||
* const extract = createExtractor({
|
||||
* [Format.TOML]: parse as Parser,
|
||||
* [Format.JSON]: JSON.parse as Parser,
|
||||
* });
|
||||
*
|
||||
* export function test(str: string): boolean {
|
||||
* return _test(str, [Format.TOML, Format.JSON]);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In this setup `extract()` and `test()` will work with TOML and JSON and only.
|
||||
* This way the YAML parser is not loaded if not needed. You can cherry-pick which
|
||||
* combination of formats are you supporting based on your needs.
|
||||
*
|
||||
* ### Delimiters
|
||||
*
|
||||
* #### YAML
|
||||
*
|
||||
* ```ignore
|
||||
* ---
|
||||
* these: are
|
||||
* ---
|
||||
* ```
|
||||
*
|
||||
* ```ignore
|
||||
* ---yaml
|
||||
* all: recognized
|
||||
* ---
|
||||
* ```
|
||||
*
|
||||
* ```ignore
|
||||
* = yaml =
|
||||
* as: yaml
|
||||
* = yaml =
|
||||
* ```
|
||||
*
|
||||
* #### TOML
|
||||
*
|
||||
* ```ignore
|
||||
* ---toml
|
||||
* this = 'is'
|
||||
* ---
|
||||
* ```
|
||||
*
|
||||
* ```ignore
|
||||
* = toml =
|
||||
* parsed = 'as'
|
||||
* toml = 'data'
|
||||
* = toml =
|
||||
* ```
|
||||
*
|
||||
* #### JSON
|
||||
*
|
||||
* ```ignore
|
||||
* ---json
|
||||
* {
|
||||
* "and": "this"
|
||||
* }
|
||||
* ---
|
||||
* ```
|
||||
*
|
||||
* ```ignore
|
||||
* {
|
||||
* "is": "JSON"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -8,6 +8,22 @@
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* decode,
|
||||
* encode,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/hex.ts";
|
||||
*
|
||||
* const binary = new TextEncoder().encode("abc");
|
||||
* const encoded = encode(binary);
|
||||
* console.log(encoded);
|
||||
* // => Uint8Array(6) [ 54, 49, 54, 50, 54, 51 ]
|
||||
*
|
||||
* console.log(decode(encoded));
|
||||
* // => Uint8Array(3) [ 97, 98, 99 ]
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -25,6 +25,8 @@ export interface ParseStreamOptions {
|
||||
* This can be used to parse [JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/) and [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464).
|
||||
* Chunks consisting of spaces, tab characters, or newline characters will be ignored.
|
||||
*
|
||||
* @example
|
||||
* parse JSON lines or NDJSON
|
||||
* ```ts
|
||||
* import { TextLineStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
* import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
@ -33,8 +35,29 @@ export interface ParseStreamOptions {
|
||||
* const { body } = await fetch(url);
|
||||
*
|
||||
* const readable = body!
|
||||
* .pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
|
||||
* .pipeThrough(new TextLineStream()) // transform into a stream where each chunk is divided by a newline
|
||||
* .pipeThrough(new JsonParseStream()); // parse each chunk as JSON
|
||||
*
|
||||
* for await (const data of readable) {
|
||||
* console.log(data);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* parse JSON Text Sequences
|
||||
* ```ts
|
||||
* import { TextDelimiterStream } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
* import { JsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
*
|
||||
* const url =
|
||||
* "https://deno.land/std@$STD_VERSION/encoding/testdata/json/test.json-seq";
|
||||
* const { body } = await fetch(url);
|
||||
*
|
||||
* const delimiter = "\x1E";
|
||||
* const readable = body!
|
||||
* .pipeThrough(new TextDecoderStream())
|
||||
* .pipeThrough(new TextLineStream()) // or `new TextDelimiterStream(delimiter)`
|
||||
* .pipeThrough(new TextDelimiterStream(delimiter)) // transform into a stream where each chunk is divided by a delimiter
|
||||
* .pipeThrough(new JsonParseStream());
|
||||
*
|
||||
* for await (const data of readable) {
|
||||
@ -71,6 +94,7 @@ function isBrankString(str: string) {
|
||||
/**
|
||||
* stream to parse [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { ConcatenatedJsonParseStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
*
|
||||
@ -78,8 +102,8 @@ function isBrankString(str: string) {
|
||||
* const { body } = await fetch(url);
|
||||
*
|
||||
* const readable = body!
|
||||
* .pipeThrough(new TextDecoderStream())
|
||||
* .pipeThrough(new ConcatenatedJsonParseStream());
|
||||
* .pipeThrough(new TextDecoderStream()) // convert Uint8Array to string
|
||||
* .pipeThrough(new ConcatenatedJsonParseStream()); // parse Concatenated JSON
|
||||
*
|
||||
* for await (const data of readable) {
|
||||
* console.log(data);
|
||||
|
@ -2,9 +2,15 @@
|
||||
|
||||
/** Optional object interface for `JsonStringifyStream`. */
|
||||
export interface StringifyStreamOptions {
|
||||
/** Prefix to be added after stringify. The default is "". */
|
||||
/** Prefix to be added after stringify.
|
||||
*
|
||||
* @default {""}
|
||||
*/
|
||||
readonly prefix?: string;
|
||||
/** Suffix to be added after stringify. The default is "\n". */
|
||||
/** Suffix to be added after stringify.
|
||||
*
|
||||
* @default {"\n"}
|
||||
*/
|
||||
readonly suffix?: string;
|
||||
/** Controls the buffer of the TransformStream used internally. Check https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/TransformStream. */
|
||||
readonly writableStrategy?: QueuingStrategy<unknown>;
|
||||
@ -18,6 +24,7 @@ export interface StringifyStreamOptions {
|
||||
* This can be used to stringify [JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/), [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464), and [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
|
||||
* You can optionally specify a prefix and suffix for each chunk. The default prefix is "" and the default suffix is "\n".
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
* import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
@ -25,20 +32,58 @@ export interface StringifyStreamOptions {
|
||||
* const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
|
||||
*
|
||||
* readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
|
||||
* .pipeThrough(new JsonStringifyStream())
|
||||
* .pipeThrough(new JsonStringifyStream()) // convert to JSON lines (ndjson)
|
||||
* .pipeThrough(new TextEncoderStream()) // convert a string to a Uint8Array
|
||||
* .pipeTo(file.writable)
|
||||
* .then(() => console.log("write success"));
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* To convert to [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464), set the
|
||||
* prefix to the delimiter "\x1E" as options.
|
||||
* ```ts
|
||||
* import { readableStreamFromIterable } from "https://deno.land/std@$STD_VERSION/streams/mod.ts";
|
||||
* import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
*
|
||||
* const file = await Deno.open("./tmp.jsonl", { create: true, write: true });
|
||||
*
|
||||
* readableStreamFromIterable([{ foo: "bar" }, { baz: 100 }])
|
||||
* .pipeThrough(new JsonStringifyStream({ prefix: "\x1E", suffix: "\n" })) // convert to JSON Text Sequences
|
||||
* .pipeThrough(new TextEncoderStream())
|
||||
* .pipeTo(file.writable)
|
||||
* .then(() => console.log("write success"));
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* If you want to stream [JSON lines](https://jsonlines.org/) from the server:
|
||||
* ```ts
|
||||
* import { serve } from "https://deno.land/std@$STD_VERSION/http/server.ts";
|
||||
* import { JsonStringifyStream } from "https://deno.land/std@$STD_VERSION/encoding/json/stream.ts";
|
||||
*
|
||||
* // A server that streams one line of JSON every second
|
||||
* serve(() => {
|
||||
* let intervalId: number | undefined;
|
||||
* const readable = new ReadableStream({
|
||||
* start(controller) {
|
||||
* // enqueue data once per second
|
||||
* intervalId = setInterval(() => {
|
||||
* controller.enqueue({ now: new Date() });
|
||||
* }, 1000);
|
||||
* },
|
||||
* cancel() {
|
||||
* clearInterval(intervalId);
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* const body = readable
|
||||
* .pipeThrough(new JsonStringifyStream()) // convert data to JSON lines
|
||||
* .pipeThrough(new TextEncoderStream()); // convert a string to a Uint8Array
|
||||
*
|
||||
* return new Response(body);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export class JsonStringifyStream extends TransformStream<unknown, string> {
|
||||
/**
|
||||
* @param options
|
||||
* @param options.prefix Prefix to be added after stringify. The default is "".
|
||||
* @param options.suffix Suffix to be added after stringify. The default is "\n".
|
||||
* @param options.writableStrategy Controls the buffer of the TransformStream used internally. Check https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/TransformStream.
|
||||
* @param options.readableStrategy Controls the buffer of the TransformStream used internally. Check https://developer.mozilla.org/en-US/docs/Web/API/TransformStream/TransformStream.
|
||||
*/
|
||||
constructor({
|
||||
prefix = "",
|
||||
suffix = "\n",
|
||||
|
@ -1,4 +1,28 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/***
|
||||
* Streams JSON concatenated with line breaks or special characters. This module
|
||||
* supports the following formats:
|
||||
* - [JSON lines](https://jsonlines.org/)
|
||||
* - [NDJSON](http://ndjson.org/)
|
||||
* - [JSON Text Sequences](https://datatracker.ietf.org/doc/html/rfc7464)
|
||||
* - [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON)
|
||||
* - JSON concatenated with any delimiter
|
||||
*
|
||||
* If you want to parse JSON separated by a delimiter, use {@linkcode TextLineStream}
|
||||
* (or {@linkcode TextDelimiterStream}) and {@linkcode JsonParseStream}.
|
||||
* {@linkcode JsonParseStream} ignores chunks consisting of spaces, tab
|
||||
* characters, or newline characters.
|
||||
*
|
||||
* If you want to parse
|
||||
* [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON),
|
||||
* use {@linkcode ConcatenatedJsonParseStream}.
|
||||
*
|
||||
* Use {@linkcode JsonStringifyStream} to transform streaming data to
|
||||
* [JSON lines](https://jsonlines.org/), [NDJSON](http://ndjson.org/),
|
||||
* [NDJSON](http://ndjson.org/) or
|
||||
* [Concatenated JSON](https://en.wikipedia.org/wiki/JSON_streaming#Concatenated_JSON).
|
||||
*/
|
||||
|
||||
export * from "./_parse.ts";
|
||||
export * from "./_stringify.ts";
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/** {@linkcode parse} function for parsing
|
||||
* [JSONC](https://code.visualstudio.com/docs/languages/json#_json-with-comments)
|
||||
* strings.
|
||||
* (JSON with Comments) strings.
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
@ -12,7 +12,10 @@
|
||||
import { assert } from "../_util/asserts.ts";
|
||||
|
||||
export interface ParseOptions {
|
||||
/** Allow trailing commas at the end of arrays and objects. (default: `true`) */
|
||||
/** Allow trailing commas at the end of arrays and objects.
|
||||
*
|
||||
* @default {true}
|
||||
*/
|
||||
allowTrailingComma?: boolean;
|
||||
}
|
||||
|
||||
@ -20,16 +23,19 @@ export interface ParseOptions {
|
||||
* Converts a JSON with Comments (JSONC) string into an object.
|
||||
* If a syntax error is found, throw a SyntaxError.
|
||||
*
|
||||
* @param text A valid JSONC string.
|
||||
* @param options
|
||||
* @param options.allowTrailingComma Allow trailing commas at the end of arrays and objects. (default: `true`)
|
||||
* @example
|
||||
*
|
||||
* ```ts
|
||||
* import * as JSONC from "https://deno.land/std@$STD_VERSION/encoding/jsonc.ts";
|
||||
*
|
||||
* JSONC.parse('{"foo": "bar", } // comment'); //=> { foo: "bar" }
|
||||
* JSONC.parse('{"foo": "bar" } // comment', { allowTrailingComma: false }); //=> { foo: "bar" }
|
||||
* console.log(JSONC.parse('{"foo": "bar", } // comment')); //=> { foo: "bar" }
|
||||
* console.log(JSONC.parse('{"foo": "bar", } /* comment *\/')); //=> { foo: "bar" }
|
||||
* console.log(JSONC.parse('{"foo": "bar" } // comment', {
|
||||
* allowTrailingComma: false,
|
||||
* })); //=> { foo: "bar" }
|
||||
* ```
|
||||
*
|
||||
* @param text A valid JSONC string.
|
||||
*/
|
||||
export function parse(
|
||||
text: string,
|
||||
|
132
encoding/toml.ts
132
encoding/toml.ts
@ -1,10 +1,138 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/** {@linkcode parse} and {@linkcode stringify} for handling
|
||||
* [TOML](https://toml.io/en/) encoded data.
|
||||
/**
|
||||
* {@linkcode parse} and {@linkcode stringify} for handling
|
||||
* [TOML](https://toml.io/en/latest) encoded data. Be sure to read the supported
|
||||
* types as not every spec is supported at the moment and the handling in
|
||||
* TypeScript side is a bit different.
|
||||
*
|
||||
* ## Supported types and handling
|
||||
*
|
||||
* - :heavy_check_mark: [Keys](https://toml.io/en/latest#keys)
|
||||
* - :exclamation: [String](https://toml.io/en/latest#string)
|
||||
* - :heavy_check_mark: [Multiline String](https://toml.io/en/latest#string)
|
||||
* - :heavy_check_mark: [Literal String](https://toml.io/en/latest#string)
|
||||
* - :exclamation: [Integer](https://toml.io/en/latest#integer)
|
||||
* - :heavy_check_mark: [Float](https://toml.io/en/latest#float)
|
||||
* - :heavy_check_mark: [Boolean](https://toml.io/en/latest#boolean)
|
||||
* - :heavy_check_mark:
|
||||
* [Offset Date-time](https://toml.io/en/latest#offset-date-time)
|
||||
* - :heavy_check_mark:
|
||||
* [Local Date-time](https://toml.io/en/latest#local-date-time)
|
||||
* - :heavy_check_mark: [Local Date](https://toml.io/en/latest#local-date)
|
||||
* - :exclamation: [Local Time](https://toml.io/en/latest#local-time)
|
||||
* - :heavy_check_mark: [Table](https://toml.io/en/latest#table)
|
||||
* - :heavy_check_mark: [Inline Table](https://toml.io/en/latest#inline-table)
|
||||
* - :exclamation: [Array of Tables](https://toml.io/en/latest#array-of-tables)
|
||||
*
|
||||
* :exclamation: _Supported with warnings see [Warning](#Warning)._
|
||||
*
|
||||
* ### :warning: Warning
|
||||
*
|
||||
* #### String
|
||||
*
|
||||
* - Regex : Due to the spec, there is no flag to detect regex properly in a TOML
|
||||
* declaration. So the regex is stored as string.
|
||||
*
|
||||
* #### Integer
|
||||
*
|
||||
* For **Binary** / **Octal** / **Hexadecimal** numbers, they are stored as string
|
||||
* to be not interpreted as Decimal.
|
||||
*
|
||||
* #### Local Time
|
||||
*
|
||||
* Because local time does not exist in JavaScript, the local time is stored as a
|
||||
* string.
|
||||
*
|
||||
* #### Inline Table
|
||||
*
|
||||
* Inline tables are supported. See below:
|
||||
*
|
||||
* ```toml
|
||||
* animal = { type = { name = "pug" } }
|
||||
* ## Output { animal: { type: { name: "pug" } } }
|
||||
* animal = { type.name = "pug" }
|
||||
* ## Output { animal: { type : { name : "pug" } }
|
||||
* animal.as.leaders = "tosin"
|
||||
* ## Output { animal: { as: { leaders: "tosin" } } }
|
||||
* "tosin.abasi" = "guitarist"
|
||||
* ## Output { tosin.abasi: "guitarist" }
|
||||
* ```
|
||||
*
|
||||
* #### Array of Tables
|
||||
*
|
||||
* At the moment only simple declarations like below are supported:
|
||||
*
|
||||
* ```toml
|
||||
* [[bin]]
|
||||
* name = "deno"
|
||||
* path = "cli/main.rs"
|
||||
*
|
||||
* [[bin]]
|
||||
* name = "deno_core"
|
||||
* path = "src/foo.rs"
|
||||
*
|
||||
* [[nib]]
|
||||
* name = "node"
|
||||
* path = "not_found"
|
||||
* ```
|
||||
*
|
||||
* will output:
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "bin": [
|
||||
* { "name": "deno", "path": "cli/main.rs" },
|
||||
* { "name": "deno_core", "path": "src/foo.rs" }
|
||||
* ],
|
||||
* "nib": [{ "name": "node", "path": "not_found" }]
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* parse,
|
||||
* stringify,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/toml.ts";
|
||||
* const obj = {
|
||||
* bin: [
|
||||
* { name: "deno", path: "cli/main.rs" },
|
||||
* { name: "deno_core", path: "src/foo.rs" },
|
||||
* ],
|
||||
* nib: [{ name: "node", path: "not_found" }],
|
||||
* };
|
||||
* const tomlString = stringify(obj);
|
||||
* console.log(tomlString);
|
||||
*
|
||||
* // =>
|
||||
* // [[bin]]
|
||||
* // name = "deno"
|
||||
* // path = "cli/main.rs"
|
||||
*
|
||||
* // [[bin]]
|
||||
* // name = "deno_core"
|
||||
* // path = "src/foo.rs"
|
||||
*
|
||||
* // [[nib]]
|
||||
* // name = "node"
|
||||
* // path = "not_found"
|
||||
*
|
||||
* const tomlObject = parse(tomlString);
|
||||
* console.log(tomlObject);
|
||||
*
|
||||
* // =>
|
||||
* // {
|
||||
* // bin: [
|
||||
* // { name: "deno", path: "cli/main.rs" },
|
||||
* // { name: "deno_core", path: "src/foo.rs" }
|
||||
* // ],
|
||||
* // nib: [ { name: "node", path: "not_found" } ]
|
||||
* // }
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -1,12 +1,48 @@
|
||||
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/** {@linkcode parse} and {@linkcode stringify} for handling
|
||||
/**
|
||||
* {@linkcode parse} and {@linkcode stringify} for handling
|
||||
* [YAML](https://yaml.org/) encoded data.
|
||||
*
|
||||
* Ported from
|
||||
* [js-yaml v3.13.1](https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da)
|
||||
*
|
||||
* If your YAML contains multiple documents in it, you can use {@linkcode parseAll} for
|
||||
* handling it.
|
||||
*
|
||||
* To handle `regexp`, and `undefined` types, use {@linkcode EXTENDED_SCHEMA}.
|
||||
* You can also use custom types by extending schemas.
|
||||
*
|
||||
* ## :warning: Limitations
|
||||
* - `binary` type is currently not stable.
|
||||
*
|
||||
* For further examples see https://github.com/nodeca/js-yaml/tree/master/examples.
|
||||
* @example
|
||||
* ```ts
|
||||
* import {
|
||||
* parse,
|
||||
* stringify,
|
||||
* } from "https://deno.land/std@$STD_VERSION/encoding/yaml.ts";
|
||||
*
|
||||
* const data = parse(`
|
||||
* foo: bar
|
||||
* baz:
|
||||
* - qux
|
||||
* - quux
|
||||
* `);
|
||||
* console.log(data);
|
||||
* // => { foo: "bar", baz: [ "qux", "quux" ] }
|
||||
*
|
||||
* const yaml = stringify({ foo: "bar", baz: ["qux", "quux"] });
|
||||
* console.log(yaml);
|
||||
* // =>
|
||||
* // foo: bar
|
||||
* // baz:
|
||||
* // - qux
|
||||
* // - quux
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
# flags
|
||||
|
||||
Command line arguments parser for Deno based on minimist.
|
||||
|
||||
# Example
|
||||
|
||||
```ts
|
||||
import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
|
||||
|
||||
console.dir(parse(Deno.args));
|
||||
```
|
||||
|
||||
```
|
||||
$ deno run https://deno.land/std/examples/flags.ts -a beep -b boop
|
||||
{ _: [], a: 'beep', b: 'boop' }
|
||||
```
|
||||
|
||||
```
|
||||
$ deno run https://deno.land/std/examples/flags.ts -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
|
||||
{ _: [ 'foo', 'bar', 'baz' ],
|
||||
x: 3,
|
||||
y: 4,
|
||||
n: 5,
|
||||
a: true,
|
||||
b: true,
|
||||
c: true,
|
||||
beep: 'boop' }
|
||||
```
|
||||
|
||||
# API
|
||||
|
||||
## const parsedArgs = parse(args, options = {});
|
||||
|
||||
`parsedArgs._` contains all the arguments that didn't have an option associated
|
||||
with them.
|
||||
|
||||
Numeric-looking arguments will be returned as numbers unless `options.string` or
|
||||
`options.boolean` is set for that argument name.
|
||||
|
||||
Any arguments after `'--'` will not be parsed and will end up in `parsedArgs._`.
|
||||
|
||||
options can be:
|
||||
|
||||
- `options.string` - a string or array of strings argument names to always treat
|
||||
as strings.
|
||||
- `options.boolean` - a boolean, string or array of strings to always treat as
|
||||
booleans. if `true` will treat all double hyphenated arguments without equal
|
||||
signs as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`). All
|
||||
`boolean` arguments will be set to `false` by default.
|
||||
- `options.collect` - a string or array of strings argument names to always
|
||||
treat as arrays. Collectable options can be used multiple times. All values
|
||||
will be collected into an array. If a non collectable option is used multiple
|
||||
times, the last value is used. All Collectable arguments will be set to `[]`
|
||||
by default.
|
||||
- `options.negatable` - a string or array of strings argument names which can be
|
||||
negated by prefixing them with `--no-`, like `--no-config`.
|
||||
- `options.alias` - an object mapping string names to strings or arrays of
|
||||
string argument names to use as aliases.
|
||||
- `options.default` - an object mapping string argument names to default values.
|
||||
- `options.stopEarly` - when true, populate `parsedArgs._` with everything after
|
||||
the first non-option.
|
||||
- `options['--']` - when true, populate `parsedArgs._` with everything before
|
||||
the `--` and `parsedArgs['--']` with everything after the `--`. Here's an
|
||||
example:
|
||||
```ts
|
||||
// $ deno run example.ts -- a arg1
|
||||
import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
|
||||
console.dir(parse(Deno.args, { "--": false }));
|
||||
// output: { _: [ "a", "arg1" ] }
|
||||
console.dir(parse(Deno.args, { "--": true }));
|
||||
// output: { _: [], --: [ "a", "arg1" ] }
|
||||
```
|
||||
- `options.unknown` - a function which is invoked with a command line parameter
|
||||
not defined in the `options` configuration object. If the function returns
|
||||
`false`, the unknown option is not added to `parsedArgs`.
|
||||
|
||||
By default, the flags module tries to determine the type of all arguments
|
||||
automatically and the return type of the `parse` method will have an index
|
||||
signature with `any` as value (`{ [x: string]: any }`).
|
||||
|
||||
If the `string`, `boolean` or `collect` option is set, the return value of the
|
||||
`parse` method will be fully typed and the index signature of the return type
|
||||
will change to `{ [x: string]: unknown }`.
|
87
flags/mod.ts
87
flags/mod.ts
@ -5,6 +5,30 @@
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
|
||||
*
|
||||
* console.dir(parse(Deno.args));
|
||||
* ```
|
||||
*
|
||||
* ```sh
|
||||
* $ deno run https://deno.land/std/examples/flags.ts -a beep -b boop
|
||||
* { _: [], a: 'beep', b: 'boop' }
|
||||
* ```
|
||||
*
|
||||
* ```sh
|
||||
* $ deno run https://deno.land/std/examples/flags.ts -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
|
||||
* { _: [ 'foo', 'bar', 'baz' ],
|
||||
* x: 3,
|
||||
* y: 4,
|
||||
* n: 5,
|
||||
* a: true,
|
||||
* b: true,
|
||||
* c: true,
|
||||
* beep: 'boop' }
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
import { assert } from "../_util/asserts.ts";
|
||||
@ -229,9 +253,13 @@ export interface ParseOptions<
|
||||
| undefined,
|
||||
DD extends boolean | undefined = boolean | undefined,
|
||||
> {
|
||||
/** When `true`, populate the result `_` with everything before the `--` and
|
||||
* the result `['--']` with everything after the `--`. Here's an example:
|
||||
/**
|
||||
* When `true`, populate the result `_` with everything before the `--` and
|
||||
* the result `['--']` with everything after the `--`.
|
||||
*
|
||||
* @default {false}
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // $ deno run example.ts -- a arg1
|
||||
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
|
||||
@ -240,43 +268,55 @@ export interface ParseOptions<
|
||||
* console.dir(parse(Deno.args, { "--": true }));
|
||||
* // output: { _: [], --: [ "a", "arg1" ] }
|
||||
* ```
|
||||
*
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
"--"?: DD;
|
||||
|
||||
/** An object mapping string names to strings or arrays of string argument
|
||||
* names to use as aliases. */
|
||||
/**
|
||||
* An object mapping string names to strings or arrays of string argument
|
||||
* names to use as aliases.
|
||||
*/
|
||||
alias?: A;
|
||||
|
||||
/** A boolean, string or array of strings to always treat as booleans. If
|
||||
/**
|
||||
* A boolean, string or array of strings to always treat as booleans. If
|
||||
* `true` will treat all double hyphenated arguments without equal signs as
|
||||
* `boolean` (e.g. affects `--foo`, not `-f` or `--foo=bar`) */
|
||||
* `boolean` (e.g. affects `--foo`, not `-f` or `--foo=bar`).
|
||||
* All `boolean` arguments will be set to `false` by default.
|
||||
*/
|
||||
boolean?: B | ReadonlyArray<Extract<B, string>>;
|
||||
|
||||
/** An object mapping string argument names to default values. */
|
||||
default?: D & Defaults<B, S>;
|
||||
|
||||
/** When `true`, populate the result `_` with everything after the first
|
||||
* non-option. */
|
||||
/**
|
||||
* When `true`, populate the result `_` with everything after the first
|
||||
* non-option.
|
||||
*/
|
||||
stopEarly?: boolean;
|
||||
|
||||
/** A string or array of strings argument names to always treat as strings. */
|
||||
string?: S | ReadonlyArray<Extract<S, string>>;
|
||||
|
||||
/** A string or array of strings argument names to always treat as arrays.
|
||||
/**
|
||||
* A string or array of strings argument names to always treat as arrays.
|
||||
* Collectable options can be used multiple times. All values will be
|
||||
* collected into one array. If a non-collectable option is used multiple
|
||||
* times, the last value is used. */
|
||||
* times, the last value is used.
|
||||
* All Collectable arguments will be set to `[]` by default.
|
||||
*/
|
||||
collect?: C | ReadonlyArray<Extract<C, string>>;
|
||||
|
||||
/** A string or array of strings argument names which can be negated
|
||||
* by prefixing them with `--no-`, like `--no-config`. */
|
||||
/**
|
||||
* A string or array of strings argument names which can be negated
|
||||
* by prefixing them with `--no-`, like `--no-config`.
|
||||
*/
|
||||
negatable?: N | ReadonlyArray<Extract<N, string>>;
|
||||
|
||||
/** A function which is invoked with a command line parameter not defined in
|
||||
/**
|
||||
* A function which is invoked with a command line parameter not defined in
|
||||
* the `options` configuration object. If the function returns `false`, the
|
||||
* unknown option is not added to `parsedArgs`. */
|
||||
* unknown option is not added to `parsedArgs`.
|
||||
*/
|
||||
unknown?: (arg: string, key?: string, value?: unknown) => unknown;
|
||||
}
|
||||
|
||||
@ -331,11 +371,26 @@ function hasKey(obj: NestedMapping, keys: string[]): boolean {
|
||||
* considered a key-value pair. Any arguments which could not be parsed are
|
||||
* available in the `_` property of the returned object.
|
||||
*
|
||||
* By default, the flags module tries to determine the type of all arguments
|
||||
* automatically and the return type of the `parse` method will have an index
|
||||
* signature with `any` as value (`{ [x: string]: any }`).
|
||||
*
|
||||
* If the `string`, `boolean` or `collect` option is set, the return value of
|
||||
* the `parse` method will be fully typed and the index signature of the return
|
||||
* type will change to `{ [x: string]: unknown }`.
|
||||
*
|
||||
* Any arguments after `'--'` will not be parsed and will end up in `parsedArgs._`.
|
||||
*
|
||||
* Numeric-looking arguments will be returned as numbers unless `options.string`
|
||||
* or `options.boolean` is set for that argument name.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
|
||||
* const parsedArgs = parse(Deno.args);
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { parse } from "https://deno.land/std@$STD_VERSION/flags/mod.ts";
|
||||
* const parsedArgs = parse(["--foo", "--bar=baz", "./quux.txt"]);
|
||||
|
252
fmt/README.md
252
fmt/README.md
@ -3,20 +3,6 @@
|
||||
This is very much a work-in-progress. I'm actively soliciting feedback. What
|
||||
immediately follows are points for discussion.
|
||||
|
||||
If you are looking for the documentation proper, skip to:
|
||||
|
||||
"printf: prints formatted output"
|
||||
|
||||
and
|
||||
|
||||
"Colors"
|
||||
|
||||
below.
|
||||
|
||||
## Discussion
|
||||
|
||||
This is very much a work-in-progress. I'm actively soliciting feedback.
|
||||
|
||||
- What useful features are available in other languages apart from Golang and C?
|
||||
|
||||
- behaviour of `%v` verb. In Golang, this is a shortcut verb to "print the
|
||||
@ -28,8 +14,9 @@ This is very much a work-in-progress. I'm actively soliciting feedback.
|
||||
`inspect` output is not defined, however. This may be problematic if using
|
||||
this code on other platforms (and expecting interoperability). To my
|
||||
knowledge, no suitable specification of object representation aside from JSON
|
||||
and `toString` exist. ( Aside: see "[Common object formats][3]" in the
|
||||
"Console Living Standard" which basically says "do whatever" )
|
||||
and `toString` exist. ( Aside: see
|
||||
"[Common object formats](https://console.spec.whatwg.org/#object-formats)" in
|
||||
the "Console Living Standard" which basically says "do whatever" )
|
||||
|
||||
- `%j` verb. This is an extension particular to this implementation. Currently
|
||||
not very sophisticated, it just runs `JSON.stringify` on the argument.
|
||||
@ -58,236 +45,3 @@ This is very much a work-in-progress. I'm actively soliciting feedback.
|
||||
- some flags that are potentially applicable ( POSIX long and unsigned modifiers
|
||||
are not likely useful) are missing, namely %q (print quoted), %U (unicode
|
||||
format)
|
||||
|
||||
# printf: prints formatted output
|
||||
|
||||
sprintf converts and formats a variable number of arguments as is specified by a
|
||||
`format string`. In it's basic form, a format string may just be a literal. In
|
||||
case arguments are meant to be formatted, a `directive` is contained in the
|
||||
format string, preceded by a '%' character:
|
||||
|
||||
%<verb>
|
||||
|
||||
E.g. the verb `s` indicates the directive should be replaced by the string
|
||||
representation of the argument in the corresponding position of the argument
|
||||
list. E.g.:
|
||||
|
||||
Hello %s!
|
||||
|
||||
applied to the arguments "World" yields "Hello World!".
|
||||
|
||||
The meaning of the format string is modelled after [POSIX][1] format strings as
|
||||
well as well as [Golang format strings][2]. Both contain elements specific to
|
||||
the respective programming language that don't apply to JavaScript, so they can
|
||||
not be fully supported. Furthermore we implement some functionality that is
|
||||
specific to JS.
|
||||
|
||||
## Verbs
|
||||
|
||||
The following verbs are supported:
|
||||
|
||||
| Verb | Meaning |
|
||||
| ----- | -------------------------------------------------------------- |
|
||||
| `%` | print a literal percent |
|
||||
| `t` | evaluate arg as boolean, print `true` or `false` |
|
||||
| `b` | eval as number, print binary |
|
||||
| `c` | eval as number, print character corresponding to the codePoint |
|
||||
| `o` | eval as number, print octal |
|
||||
| `x X` | print as hex (ff FF), treat string as list of bytes |
|
||||
| `e E` | print number in scientific/exponent format 1.123123e+01 |
|
||||
| `f F` | print number as float with decimal point and no exponent |
|
||||
| `g G` | use %e %E or %f %F depending on size of argument |
|
||||
| `s` | interpolate string |
|
||||
| `T` | type of arg, as returned by `typeof` |
|
||||
| `v` | value of argument in 'default' format (see below) |
|
||||
| `j` | argument as formatted by `JSON.stringify` |
|
||||
|
||||
## Width and Precision
|
||||
|
||||
Verbs may be modified by providing them with width and precision, either or both
|
||||
may be omitted:
|
||||
|
||||
%9f width 9, default precision
|
||||
%.9f default width, precision 9
|
||||
%8.9f width 8, precision 9
|
||||
%8.f width 9, precision 0
|
||||
|
||||
In general, 'width' describes the minimum length of the output, while
|
||||
'precision' limits the output.
|
||||
|
||||
| verb | precision |
|
||||
| --------- | --------------------------------------------------------------- |
|
||||
| `t` | n/a |
|
||||
| `b c o` | n/a |
|
||||
| `x X` | n/a for number, strings are truncated to p bytes(!) |
|
||||
| `e E f F` | number of places after decimal, default 6 |
|
||||
| `g G` | set maximum number of digits |
|
||||
| `s` | truncate input |
|
||||
| `T` | truncate |
|
||||
| `v` | truncate, or depth if used with # see "'default' format", below |
|
||||
| `j` | n/a |
|
||||
|
||||
Numerical values for width and precision can be substituted for the `*` char, in
|
||||
which case the values are obtained from the next args, e.g.:
|
||||
|
||||
sprintf("%*.*f", 9, 8, 456.0)
|
||||
|
||||
is equivalent to:
|
||||
|
||||
sprintf("%9.8f", 456.0)
|
||||
|
||||
## Flags
|
||||
|
||||
The effects of the verb may be further influenced by using flags to modify the
|
||||
directive:
|
||||
|
||||
| Flag | Verb | Meaning |
|
||||
| ----- | --------- | -------------------------------------------------------------------------- |
|
||||
| `+` | numeric | always print sign |
|
||||
| `-` | all | pad to the right (left justify) |
|
||||
| `#` | | alternate format |
|
||||
| `#` | `b o x X` | prefix with `0b 0 0x` |
|
||||
| `#` | `g G` | don't remove trailing zeros |
|
||||
| `#` | `v` | ues output of `inspect` instead of `toString` |
|
||||
| `' '` | | space character |
|
||||
| `' '` | `x X` | leave spaces between bytes when printing string |
|
||||
| `' '` | `d` | insert space for missing `+` sign character |
|
||||
| `0` | all | pad with zero, `-` takes precedence, sign is appended in front of padding |
|
||||
| `<` | all | format elements of the passed array according to the directive (extension) |
|
||||
|
||||
## 'default' format
|
||||
|
||||
The default format used by `%v` is the result of calling `toString()` on the
|
||||
relevant argument. If the `#` flags is used, the result of calling `inspect()`
|
||||
is interpolated. In this case, the precision, if set is passed to `inspect()` as
|
||||
the 'depth' config parameter.
|
||||
|
||||
## Positional arguments
|
||||
|
||||
Arguments do not need to be consumed in the order they are provided and may be
|
||||
consumed more than once. E.g.:
|
||||
|
||||
sprintf("%[2]s %[1]s", "World", "Hello")
|
||||
|
||||
returns "Hello World". The presence of a positional indicator resets the arg
|
||||
counter allowing args to be reused:
|
||||
|
||||
sprintf("dec[%d]=%d hex[%[1]d]=%x oct[%[1]d]=%#o %s", 1, 255, "Third")
|
||||
|
||||
returns `dec[1]=255 hex[1]=0xff oct[1]=0377 Third`
|
||||
|
||||
Width and precision my also use positionals:
|
||||
|
||||
"%[2]*.[1]*d", 1, 2
|
||||
|
||||
This follows the golang conventions and not POSIX.
|
||||
|
||||
## Errors
|
||||
|
||||
The following errors are handled:
|
||||
|
||||
Incorrect verb:
|
||||
|
||||
S("%h", "") %!(BAD VERB 'h')
|
||||
|
||||
Too few arguments:
|
||||
|
||||
S("%d") %!(MISSING 'd')"
|
||||
|
||||
# Colors
|
||||
|
||||
Adds functions used for displaying colored text.
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import {
|
||||
bgBlue,
|
||||
bgRgb24,
|
||||
bgRgb8,
|
||||
bold,
|
||||
italic,
|
||||
red,
|
||||
rgb24,
|
||||
rgb8,
|
||||
} from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
|
||||
|
||||
console.log(bgBlue(italic(red(bold("Hello, World!")))));
|
||||
|
||||
// also supports 8bit colors
|
||||
|
||||
console.log(rgb8("Hello, World!", 42));
|
||||
|
||||
console.log(bgRgb8("Hello, World!", 42));
|
||||
|
||||
// and 24bit rgb
|
||||
|
||||
console.log(rgb24("Hello, World!", {
|
||||
r: 41,
|
||||
g: 42,
|
||||
b: 43,
|
||||
}));
|
||||
|
||||
console.log(bgRgb24("Hello, World!", {
|
||||
r: 41,
|
||||
g: 42,
|
||||
b: 43,
|
||||
}));
|
||||
```
|
||||
|
||||
# Pretty Bytes
|
||||
|
||||
> Convert bytes to a human readable string: 1337 → 1.34 kB
|
||||
|
||||
A utility for displaying file sizes for humans.
|
||||
|
||||
Note: This module was ported from
|
||||
[pretty-bytes](https://github.com/sindresorhus/pretty-bytes).
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { format } from "https://deno.land/std@$STD_VERSION/fmt/bytes.ts";
|
||||
|
||||
format(1337);
|
||||
//=> '1.34 kB'
|
||||
|
||||
format(100);
|
||||
//=> '100 B'
|
||||
|
||||
// Display with units of bits
|
||||
format(1337, { bits: true });
|
||||
//=> '1.34 kbit'
|
||||
|
||||
// Display file size differences
|
||||
format(42, { signed: true });
|
||||
//=> '+42 B'
|
||||
|
||||
// Localized output using German locale
|
||||
format(1337, { locale: "de" });
|
||||
//=> '1,34 kB'
|
||||
```
|
||||
|
||||
# Pretty Duration
|
||||
|
||||
Format milliseconds to time duration.
|
||||
|
||||
```ts
|
||||
import { format } from "https://deno.land/std@$STD_VERSION/fmt/duration.ts";
|
||||
|
||||
// "00:00:01:39:674:000:000"
|
||||
format(99674, { style: "digital" });
|
||||
|
||||
// "0d 0h 1m 39s 674ms 0µs 0ns"
|
||||
format(99674);
|
||||
|
||||
// "1m 39s 674ms"
|
||||
format(99674, { ignoreZero: true });
|
||||
|
||||
// "1 minutes, 39 seconds, 674 milliseconds"
|
||||
format(99674, { style: "full", ignoreZero: true });
|
||||
```
|
||||
|
||||
[1]: https://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
|
||||
[2]: https://golang.org/pkg/fmt/
|
||||
[3]: https://console.spec.whatwg.org/#object-formats
|
||||
|
36
fmt/bytes.ts
36
fmt/bytes.ts
@ -5,9 +5,33 @@
|
||||
/** Pretty print bytes.
|
||||
*
|
||||
* Based on [pretty-bytes](https://github.com/sindresorhus/pretty-bytes).
|
||||
* A utility for displaying file sizes for humans.
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { format } from "https://deno.land/std@$STD_VERSION/fmt/bytes.ts";
|
||||
*
|
||||
* format(1337);
|
||||
* //=> '1.34 kB'
|
||||
*
|
||||
* format(100);
|
||||
* //=> '100 B'
|
||||
*
|
||||
* // Display with units of bits
|
||||
* format(1337, { bits: true });
|
||||
* //=> '1.34 kbit'
|
||||
*
|
||||
* // Display file size differences
|
||||
* format(42, { signed: true });
|
||||
* //=> '+42 B'
|
||||
*
|
||||
* // Localized output using German locale
|
||||
* format(1337, { locale: "de" });
|
||||
* //=> '1,34 kB'
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
@ -20,9 +44,15 @@ type LocaleOptions = {
|
||||
* @deprecated (will be removed after 0.170.0) use `FormatOptions` instead
|
||||
*/
|
||||
export interface PrettyBytesOptions {
|
||||
/** Uses bits representation. Default is false. */
|
||||
/** Uses bits representation.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
bits?: boolean;
|
||||
/** Uses binary bytes (e.g. kibibyte). Default is false. */
|
||||
/** Uses binary bytes (e.g. kibibyte).
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
binary?: boolean;
|
||||
/** Include plus sign for positive numbers. */
|
||||
signed?: boolean;
|
||||
@ -59,7 +89,7 @@ export function prettyBytes(num: number, options: FormatOptions = {}) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert bytes to a human readable string: 1337 → 1.34 kB
|
||||
* Convert bytes to a human-readable string: 1337 → 1.34 kB
|
||||
*
|
||||
* @param num The number to format
|
||||
* @param options The options
|
||||
|
@ -7,14 +7,45 @@
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* ```ts
|
||||
* import { bgBlue, red, bold } from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
|
||||
* console.log(bgBlue(red(bold("Hello world!"))));
|
||||
* ```
|
||||
*
|
||||
* This module supports `NO_COLOR` environmental variable disabling any coloring
|
||||
* if `NO_COLOR` is set.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import {
|
||||
* bgBlue,
|
||||
* bgRgb24,
|
||||
* bgRgb8,
|
||||
* bold,
|
||||
* italic,
|
||||
* red,
|
||||
* rgb24,
|
||||
* rgb8,
|
||||
* } from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
|
||||
*
|
||||
* console.log(bgBlue(italic(red(bold("Hello, World!")))));
|
||||
*
|
||||
* // also supports 8bit colors
|
||||
*
|
||||
* console.log(rgb8("Hello, World!", 42));
|
||||
*
|
||||
* console.log(bgRgb8("Hello, World!", 42));
|
||||
*
|
||||
* // and 24bit rgb
|
||||
*
|
||||
* console.log(rgb24("Hello, World!", {
|
||||
* r: 41,
|
||||
* g: 42,
|
||||
* b: 43,
|
||||
* }));
|
||||
*
|
||||
* console.log(bgRgb24("Hello, World!", {
|
||||
* r: 41,
|
||||
* g: 42,
|
||||
* b: 43,
|
||||
* }));
|
||||
* ```
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
@ -1,5 +1,25 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// A module to get formatted digital duration from milliseconds.
|
||||
|
||||
/**
|
||||
* Format milliseconds to time duration.
|
||||
*
|
||||
* ```ts
|
||||
* import { format } from "https://deno.land/std@$STD_VERSION/fmt/duration.ts";
|
||||
*
|
||||
* // "00:00:01:39:674:000:000"
|
||||
* format(99674, { style: "digital" });
|
||||
*
|
||||
* // "0d 0h 1m 39s 674ms 0µs 0ns"
|
||||
* format(99674);
|
||||
*
|
||||
* // "1m 39s 674ms"
|
||||
* format(99674, { ignoreZero: true });
|
||||
*
|
||||
* // "1 minutes, 39 seconds, 674 milliseconds"
|
||||
* format(99674, { style: "full", ignoreZero: true });
|
||||
* ```
|
||||
* @module
|
||||
*/
|
||||
|
||||
const addZero = (num: number, digits: number) =>
|
||||
String(num).padStart(digits, "0");
|
||||
|
136
fmt/printf.ts
136
fmt/printf.ts
@ -7,6 +7,142 @@
|
||||
* This implementation is inspired by POSIX and Golang but does not port
|
||||
* implementation code.
|
||||
*
|
||||
* sprintf converts and formats a variable number of arguments as is specified
|
||||
* by a `format string`. In it's basic form, a format string may just be a
|
||||
* literal. In case arguments are meant to be formatted, a `directive` is
|
||||
* contained in the format string, preceded by a '%' character:
|
||||
*
|
||||
* %<verb>
|
||||
*
|
||||
* E.g. the verb `s` indicates the directive should be replaced by the string
|
||||
* representation of the argument in the corresponding position of the argument
|
||||
* list. E.g.:
|
||||
*
|
||||
* Hello %s!
|
||||
*
|
||||
* applied to the arguments "World" yields "Hello World!".
|
||||
*
|
||||
* The meaning of the format string is modelled after [POSIX][1] format strings
|
||||
* as well as well as [Golang format strings][2]. Both contain elements specific
|
||||
* to the respective programming language that don't apply to JavaScript, so
|
||||
* they can not be fully supported. Furthermore we implement some functionality
|
||||
* that is specific to JS.
|
||||
*
|
||||
* ## Verbs
|
||||
*
|
||||
* The following verbs are supported:
|
||||
*
|
||||
* | Verb | Meaning |
|
||||
* | ----- | -------------------------------------------------------------- |
|
||||
* | `%` | print a literal percent |
|
||||
* | `t` | evaluate arg as boolean, print `true` or `false` |
|
||||
* | `b` | eval as number, print binary |
|
||||
* | `c` | eval as number, print character corresponding to the codePoint |
|
||||
* | `o` | eval as number, print octal |
|
||||
* | `x X` | print as hex (ff FF), treat string as list of bytes |
|
||||
* | `e E` | print number in scientific/exponent format 1.123123e+01 |
|
||||
* | `f F` | print number as float with decimal point and no exponent |
|
||||
* | `g G` | use %e %E or %f %F depending on size of argument |
|
||||
* | `s` | interpolate string |
|
||||
* | `T` | type of arg, as returned by `typeof` |
|
||||
* | `v` | value of argument in 'default' format (see below) |
|
||||
* | `j` | argument as formatted by `JSON.stringify` |
|
||||
*
|
||||
* ## Width and Precision
|
||||
*
|
||||
* Verbs may be modified by providing them with width and precision, either or
|
||||
* both may be omitted:
|
||||
*
|
||||
* %9f width 9, default precision
|
||||
* %.9f default width, precision 9
|
||||
* %8.9f width 8, precision 9
|
||||
* %8.f width 9, precision 0
|
||||
*
|
||||
* In general, 'width' describes the minimum length of the output, while
|
||||
* 'precision' limits the output.
|
||||
*
|
||||
* | verb | precision |
|
||||
* | --------- | --------------------------------------------------------------- |
|
||||
* | `t` | n/a |
|
||||
* | `b c o` | n/a |
|
||||
* | `x X` | n/a for number, strings are truncated to p bytes(!) |
|
||||
* | `e E f F` | number of places after decimal, default 6 |
|
||||
* | `g G` | set maximum number of digits |
|
||||
* | `s` | truncate input |
|
||||
* | `T` | truncate |
|
||||
* | `v` | truncate, or depth if used with # see "'default' format", below |
|
||||
* | `j` | n/a |
|
||||
*
|
||||
* Numerical values for width and precision can be substituted for the `*` char,
|
||||
* in which case the values are obtained from the next args, e.g.:
|
||||
*
|
||||
* sprintf("%*.*f", 9, 8, 456.0)
|
||||
*
|
||||
* is equivalent to:
|
||||
*
|
||||
* sprintf("%9.8f", 456.0)
|
||||
*
|
||||
* ## Flags
|
||||
*
|
||||
* The effects of the verb may be further influenced by using flags to modify
|
||||
* the directive:
|
||||
*
|
||||
* | Flag | Verb | Meaning |
|
||||
* | ----- | --------- | -------------------------------------------------------------------------- |
|
||||
* | `+` | numeric | always print sign |
|
||||
* | `-` | all | pad to the right (left justify) |
|
||||
* | `#` | | alternate format |
|
||||
* | `#` | `b o x X` | prefix with `0b 0 0x` |
|
||||
* | `#` | `g G` | don't remove trailing zeros |
|
||||
* | `#` | `v` | ues output of `inspect` instead of `toString` |
|
||||
* | `' '` | | space character |
|
||||
* | `' '` | `x X` | leave spaces between bytes when printing string |
|
||||
* | `' '` | `d` | insert space for missing `+` sign character |
|
||||
* | `0` | all | pad with zero, `-` takes precedence, sign is appended in front of padding |
|
||||
* | `<` | all | format elements of the passed array according to the directive (extension) |
|
||||
*
|
||||
* ## 'default' format
|
||||
*
|
||||
* The default format used by `%v` is the result of calling `toString()` on the
|
||||
* relevant argument. If the `#` flags is used, the result of calling `inspect()`
|
||||
* is interpolated. In this case, the precision, if set is passed to `inspect()`
|
||||
* as the 'depth' config parameter.
|
||||
*
|
||||
* ## Positional arguments
|
||||
*
|
||||
* Arguments do not need to be consumed in the order they are provided and may
|
||||
* be consumed more than once. E.g.:
|
||||
*
|
||||
* sprintf("%[2]s %[1]s", "World", "Hello")
|
||||
*
|
||||
* returns "Hello World". The presence of a positional indicator resets the arg
|
||||
* counter allowing args to be reused:
|
||||
*
|
||||
* sprintf("dec[%d]=%d hex[%[1]d]=%x oct[%[1]d]=%#o %s", 1, 255, "Third")
|
||||
*
|
||||
* returns `dec[1]=255 hex[1]=0xff oct[1]=0377 Third`
|
||||
*
|
||||
* Width and precision my also use positionals:
|
||||
*
|
||||
* "%[2]*.[1]*d", 1, 2
|
||||
*
|
||||
* This follows the golang conventions and not POSIX.
|
||||
*
|
||||
* ## Errors
|
||||
*
|
||||
* The following errors are handled:
|
||||
*
|
||||
* Incorrect verb:
|
||||
*
|
||||
* S("%h", "") %!(BAD VERB 'h')
|
||||
*
|
||||
* Too few arguments:
|
||||
*
|
||||
* S("%d") %!(MISSING 'd')"
|
||||
*
|
||||
* [1]: https://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
|
||||
* [2]: https://golang.org/pkg/fmt/
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
228
fs/README.md
228
fs/README.md
@ -1,228 +0,0 @@
|
||||
# fs
|
||||
|
||||
fs module is made to provide helpers to manipulate the filesystem.
|
||||
|
||||
## Usage
|
||||
|
||||
Most of the following modules are exposed in `mod.ts`. This feature is currently
|
||||
<b>unstable</b>. To enable it use `deno run --unstable`.
|
||||
|
||||
### emptyDir
|
||||
|
||||
Ensures that a directory is empty. Deletes directory contents if the directory
|
||||
is not empty. If the directory does not exist, it is created. The directory
|
||||
itself is not deleted.
|
||||
|
||||
```ts
|
||||
import {
|
||||
emptyDir,
|
||||
emptyDirSync,
|
||||
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
emptyDir("./foo"); // returns a promise
|
||||
emptyDirSync("./foo"); // void
|
||||
```
|
||||
|
||||
### ensureDir
|
||||
|
||||
Ensures that the directory exists. If the directory structure does not exist, it
|
||||
is created. Like `mkdir -p`.
|
||||
|
||||
```ts
|
||||
import {
|
||||
ensureDir,
|
||||
ensureDirSync,
|
||||
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
ensureDir("./bar"); // returns a promise
|
||||
ensureDirSync("./ensureDirSync"); // void
|
||||
```
|
||||
|
||||
### ensureFile
|
||||
|
||||
Ensures that the file exists. If the file that is requested to be created is in
|
||||
directories that do not exist, these directories are created. If the file
|
||||
already exists, it is **NOT MODIFIED**.
|
||||
|
||||
```ts
|
||||
import {
|
||||
ensureFile,
|
||||
ensureFileSync,
|
||||
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
ensureFile("./folder/targetFile.dat"); // returns promise
|
||||
ensureFileSync("./folder/targetFile.dat"); // void
|
||||
```
|
||||
|
||||
### ensureSymlink
|
||||
|
||||
Ensures that the link exists. If the directory structure does not exist, it is
|
||||
created.
|
||||
|
||||
```ts
|
||||
import {
|
||||
ensureSymlink,
|
||||
ensureSymlinkSync,
|
||||
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
ensureSymlink("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // returns promise
|
||||
ensureSymlinkSync("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // void
|
||||
```
|
||||
|
||||
### EOL
|
||||
|
||||
Detects and format the passed string for the targeted End Of Line character.
|
||||
|
||||
```ts
|
||||
import {
|
||||
detect,
|
||||
EOL,
|
||||
format,
|
||||
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
const CRLFinput = "deno\r\nis not\r\nnode";
|
||||
const Mixedinput = "deno\nis not\r\nnode";
|
||||
const LFinput = "deno\nis not\nnode";
|
||||
const NoNLinput = "deno is not node";
|
||||
|
||||
detect(LFinput); // output EOL.LF
|
||||
detect(CRLFinput); // output EOL.CRLF
|
||||
detect(Mixedinput); // output EOL.CRLF
|
||||
detect(NoNLinput); // output null
|
||||
|
||||
format(CRLFinput, EOL.LF); // output "deno\nis not\nnode"
|
||||
```
|
||||
|
||||
### exists
|
||||
|
||||
Test whether or not the given path exists by checking with the file system.
|
||||
|
||||
```ts
|
||||
import {
|
||||
exists,
|
||||
existsSync,
|
||||
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
exists("./foo.txt"); // resolves a boolean
|
||||
existsSync("./foo.txt"); // returns a boolean
|
||||
```
|
||||
|
||||
**Note: do not use this function if performing a check before another operation
|
||||
on that file. Doing so causes a race condition. Instead, perform the actual file
|
||||
operation directly.**
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
import {
|
||||
exists,
|
||||
existsSync,
|
||||
} from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
if (await exists("./foo.txt")) {
|
||||
await Deno.remove("./foo.txt");
|
||||
}
|
||||
|
||||
// OR
|
||||
|
||||
if (existsSync("./foo.txt")) {
|
||||
Deno.removeSync("./foo.txt");
|
||||
}
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
// Notice no use of exists or existsSync
|
||||
try {
|
||||
await Deno.remove("./foo.txt");
|
||||
} catch (error) {
|
||||
if (!(error instanceof Deno.errors.NotFound)) {
|
||||
throw error;
|
||||
}
|
||||
// Do nothing...
|
||||
}
|
||||
|
||||
// OR
|
||||
|
||||
try {
|
||||
Deno.removeSync("./foo.txt");
|
||||
} catch (error) {
|
||||
if (!(error instanceof Deno.errors.NotFound)) {
|
||||
throw error;
|
||||
}
|
||||
// Do nothing...
|
||||
}
|
||||
```
|
||||
|
||||
### move
|
||||
|
||||
Moves a file or directory. Overwrites it if option provided.
|
||||
|
||||
```ts
|
||||
import { move, moveSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
move("./foo", "./bar"); // returns a promise
|
||||
moveSync("./foo", "./bar"); // void
|
||||
moveSync("./foo", "./existingFolder", { overwrite: true });
|
||||
// Will overwrite existingFolder
|
||||
```
|
||||
|
||||
### copy
|
||||
|
||||
copy a file or directory. Overwrites it if option provided.
|
||||
|
||||
```ts
|
||||
import { copy, copySync } from "https://deno.land/std@$STD_VERSION/fs/copy.ts";
|
||||
|
||||
copy("./foo", "./bar"); // returns a promise
|
||||
copySync("./foo", "./bar"); // void
|
||||
copySync("./foo", "./existingFolder", { overwrite: true });
|
||||
// Will overwrite existingFolder
|
||||
```
|
||||
|
||||
### walk
|
||||
|
||||
Iterate all files in a directory recursively.
|
||||
|
||||
```ts
|
||||
import { walk, walkSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
for (const entry of walkSync(".")) {
|
||||
console.log(entry.path);
|
||||
}
|
||||
|
||||
// Async
|
||||
async function printFilesNames() {
|
||||
for await (const entry of walk(".")) {
|
||||
console.log(entry.path);
|
||||
}
|
||||
}
|
||||
|
||||
printFilesNames().then(() => console.log("Done!"));
|
||||
```
|
||||
|
||||
### expandGlob
|
||||
|
||||
Expand the glob string from the specified `root` directory and yield each result
|
||||
as a `WalkEntry` object.
|
||||
|
||||
```ts
|
||||
import { expandGlob } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
for await (const file of expandGlob("**/*.ts")) {
|
||||
console.log(file);
|
||||
}
|
||||
```
|
||||
|
||||
### expandGlobSync
|
||||
|
||||
Synchronous version of `expandGlob()`.
|
||||
|
||||
```ts
|
||||
import { expandGlobSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
|
||||
for (const file of expandGlobSync("**/*.ts")) {
|
||||
console.log(file);
|
||||
}
|
||||
```
|
23
fs/copy.ts
23
fs/copy.ts
@ -9,22 +9,22 @@ import { isWindows } from "../_util/os.ts";
|
||||
|
||||
export interface CopyOptions {
|
||||
/**
|
||||
* overwrite existing file or directory. Default is `false`
|
||||
* overwrite existing file or directory.
|
||||
* @default {false}
|
||||
*/
|
||||
overwrite?: boolean;
|
||||
/**
|
||||
* When `true`, will set last modification and access times to the ones of the
|
||||
* original source files.
|
||||
* When `false`, timestamp behavior is OS-dependent.
|
||||
* Default is `false`.
|
||||
*
|
||||
* @default {false}
|
||||
*/
|
||||
preserveTimestamps?: boolean;
|
||||
}
|
||||
|
||||
interface InternalCopyOptions extends CopyOptions {
|
||||
/**
|
||||
* default is `false`
|
||||
*/
|
||||
/** @default {false} */
|
||||
isFolder?: boolean;
|
||||
}
|
||||
|
||||
@ -243,6 +243,13 @@ function copyDirSync(
|
||||
/**
|
||||
* Copy a file or directory. The directory can have contents. Like `cp -r`.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/fs/copy.ts";
|
||||
* copy("./foo", "./bar"); // returns a promise
|
||||
* ```
|
||||
*
|
||||
* @param src the file/directory path.
|
||||
* Note that if `src` is a directory it will copy everything inside
|
||||
* of this directory, not the entire directory itself
|
||||
@ -282,6 +289,12 @@ export async function copy(
|
||||
/**
|
||||
* Copy a file or directory. The directory can have contents. Like `cp -r`.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { copySync } from "https://deno.land/std@$STD_VERSION/fs/copy.ts";
|
||||
* copySync("./foo", "./bar"); // void
|
||||
* ```
|
||||
* @param src the file/directory path.
|
||||
* Note that if `src` is a directory it will copy everything inside
|
||||
* of this directory, not the entire directory itself
|
||||
|
@ -8,6 +8,13 @@ import { toPathString } from "./_util.ts";
|
||||
* If the directory does not exist, it is created.
|
||||
* The directory itself is not deleted.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { emptyDir } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* emptyDir("./foo"); // returns a promise
|
||||
* ```
|
||||
*/
|
||||
export async function emptyDir(dir: string | URL) {
|
||||
try {
|
||||
@ -39,6 +46,13 @@ export async function emptyDir(dir: string | URL) {
|
||||
* If the directory does not exist, it is created.
|
||||
* The directory itself is not deleted.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { emptyDirSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* emptyDirSync("./foo"); // void
|
||||
* ```
|
||||
*/
|
||||
export function emptyDirSync(dir: string | URL) {
|
||||
try {
|
||||
|
@ -5,6 +5,13 @@ import { getFileInfoType } from "./_util.ts";
|
||||
* Ensures that the directory exists.
|
||||
* If the directory structure does not exist, it is created. Like mkdir -p.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { ensureDir } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* ensureDir("./bar"); // returns a promise
|
||||
* ```
|
||||
*/
|
||||
export async function ensureDir(dir: string | URL) {
|
||||
try {
|
||||
@ -30,6 +37,13 @@ export async function ensureDir(dir: string | URL) {
|
||||
* Ensures that the directory exists.
|
||||
* If the directory structure does not exist, it is created. Like mkdir -p.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { ensureDirSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* ensureDirSync("./ensureDirSync"); // void
|
||||
* ```
|
||||
*/
|
||||
export function ensureDirSync(dir: string | URL) {
|
||||
try {
|
||||
|
@ -10,6 +10,13 @@ import { getFileInfoType, toPathString } from "./_util.ts";
|
||||
* these directories are created. If the file already exists,
|
||||
* it is NOTMODIFIED.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { ensureFile } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* ensureFile("./folder/targetFile.dat"); // returns promise
|
||||
* ```
|
||||
*/
|
||||
export async function ensureFile(filePath: string | URL) {
|
||||
try {
|
||||
@ -41,6 +48,13 @@ export async function ensureFile(filePath: string | URL) {
|
||||
* these directories are created. If the file already exists,
|
||||
* it is NOT MODIFIED.
|
||||
* Requires the `--allow-read` and `--allow-write` flag.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { ensureFileSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* ensureFileSync("./folder/targetFile.dat"); // void
|
||||
* ```
|
||||
*/
|
||||
export function ensureFileSync(filePath: string | URL) {
|
||||
try {
|
||||
|
@ -7,6 +7,13 @@ import { toPathString } from "./_util.ts";
|
||||
* Ensures that the hard link exists.
|
||||
* If the directory structure does not exist, it is created.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { ensureSymlink } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* ensureSymlink("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // returns promise
|
||||
* ```
|
||||
*
|
||||
* @param src the source file path. Directory hard links are not allowed.
|
||||
* @param dest the destination link path
|
||||
*/
|
||||
@ -21,6 +28,13 @@ export async function ensureLink(src: string | URL, dest: string | URL) {
|
||||
* Ensures that the hard link exists.
|
||||
* If the directory structure does not exist, it is created.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { ensureSymlinkSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* ensureSymlinkSync("./folder/targetFile.dat", "./folder/targetFile.link.dat"); // void
|
||||
* ```
|
||||
*
|
||||
* @param src the source file path. Directory hard links are not allowed.
|
||||
* @param dest the destination link path
|
||||
*/
|
||||
|
30
fs/eol.ts
30
fs/eol.ts
@ -13,7 +13,22 @@ const regDetect = /(?:\r?\n)/g;
|
||||
|
||||
/**
|
||||
* Detect the EOL character for string input.
|
||||
* returns null if no newline
|
||||
* returns null if no newline.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { detect, EOL } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* const CRLFinput = "deno\r\nis not\r\nnode";
|
||||
* const Mixedinput = "deno\nis not\r\nnode";
|
||||
* const LFinput = "deno\nis not\nnode";
|
||||
* const NoNLinput = "deno is not node";
|
||||
*
|
||||
* detect(LFinput); // output EOL.LF
|
||||
* detect(CRLFinput); // output EOL.CRLF
|
||||
* detect(Mixedinput); // output EOL.CRLF
|
||||
* detect(NoNLinput); // output null
|
||||
* ```
|
||||
*/
|
||||
export function detect(content: string): EOL | null {
|
||||
const d = content.match(regDetect);
|
||||
@ -25,7 +40,18 @@ export function detect(content: string): EOL | null {
|
||||
return hasCRLF ? EOL.CRLF : EOL.LF;
|
||||
}
|
||||
|
||||
/** Format the file to the targeted EOL */
|
||||
/**
|
||||
* Format the file to the targeted EOL.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { EOL, format } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* const CRLFinput = "deno\r\nis not\r\nnode";
|
||||
*
|
||||
* format(CRLFinput, EOL.LF); // output "deno\nis not\nnode"
|
||||
* ```
|
||||
*/
|
||||
export function format(content: string, eol: EOL): string {
|
||||
return content.replace(regDetect, eol);
|
||||
}
|
||||
|
@ -58,18 +58,19 @@ function comparePath(a: WalkEntry, b: WalkEntry): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Expand the glob string from the specified `root` directory and yield each
|
||||
/**
|
||||
* Expand the glob string from the specified `root` directory and yield each
|
||||
* result as a `WalkEntry` object.
|
||||
*
|
||||
* See [`globToRegExp()`](../path/glob.ts#globToRegExp) for details on supported
|
||||
* syntax.
|
||||
*
|
||||
* Example:
|
||||
* @example
|
||||
* ```ts
|
||||
* import { expandGlob } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
|
||||
* for await (const file of expandGlob("**\/*.ts")) {
|
||||
* console.log(file);
|
||||
* }
|
||||
* import { expandGlob } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
|
||||
* for await (const file of expandGlob("**\/*.ts")) {
|
||||
* console.log(file);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export async function* expandGlob(
|
||||
@ -180,15 +181,15 @@ export async function* expandGlob(
|
||||
yield* currentMatches;
|
||||
}
|
||||
|
||||
/** Synchronous version of `expandGlob()`.
|
||||
*
|
||||
* Example:
|
||||
/**
|
||||
* Synchronous version of `expandGlob()`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { expandGlobSync } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
|
||||
* for (const file of expandGlobSync("**\/*.ts")) {
|
||||
* console.log(file);
|
||||
* }
|
||||
* import { expandGlobSync } from "https://deno.land/std@$STD_VERSION/fs/expand_glob.ts";
|
||||
* for (const file of expandGlobSync("**\/*.ts")) {
|
||||
* console.log(file);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function* expandGlobSync(
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
/** Helpers for working with the filesystem.
|
||||
/**
|
||||
* Helpers for working with the filesystem.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
21
fs/move.ts
21
fs/move.ts
@ -7,7 +7,16 @@ interface MoveOptions {
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
||||
/** Moves a file or directory */
|
||||
/**
|
||||
* Moves a file or directory.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { move } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* move("./foo", "./bar"); // returns a promise
|
||||
* ```
|
||||
*/
|
||||
export async function move(
|
||||
src: string | URL,
|
||||
dest: string | URL,
|
||||
@ -43,7 +52,15 @@ export async function move(
|
||||
return;
|
||||
}
|
||||
|
||||
/** Moves a file or directory synchronously */
|
||||
/**
|
||||
* Moves a file or directory synchronously.
|
||||
* @example
|
||||
* ```ts
|
||||
* import { moveSync } from "https://deno.land/std@$STD_VERSION/fs/mod.ts";
|
||||
*
|
||||
* moveSync("./foo", "./bar"); // void
|
||||
* ```
|
||||
*/
|
||||
export function moveSync(
|
||||
src: string | URL,
|
||||
dest: string | URL,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user