Skip to content

Commit 3525a1a

Browse files
committed
formalize: writers, and exports
1 parent 57f7ce5 commit 3525a1a

File tree

15 files changed

+131
-64
lines changed

15 files changed

+131
-64
lines changed

README.md

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

2-
# 🧪 @e280/sten
3-
- logging utilities
2+
![](https://i.imgur.com/TTZbq3k.jpeg)
3+
4+
# 🖋️ @e280/sten
5+
- logging utility
46
- zero dependencies
57
- *an https://e280.org/ project*
68

@@ -11,24 +13,42 @@
1113
```sh
1214
npm install @e280/sten
1315
```
14-
- make a logger and do some logging
16+
- make your logger
1517
```ts
1618
import {Logger} from "@e280/sten"
1719

18-
const logger = new Logger()
19-
.target(Logger.node)
20-
.palette(Logger.colorful)
21-
.transform(Logger.timestamp)
20+
export const logger = new Logger()
21+
.setWriter(Logger.writers.auto())
22+
.setColors(Logger.colors.auto())
23+
.addShaper(Logger.shapers.timestamp())
2224
```
2325
- log a happy message
2426
```ts
25-
logger.log("hello world!")
27+
await logger.log("hello world!")
2628
```
2729
- log an angry message
2830
```ts
29-
logger.error("something bad happened")
31+
await logger.error("something bad happened")
3032
```
3133

34+
### writers
35+
the logger ultimately emits to stdout or stderr via a logger — the available writers are:
36+
- `auto`*(default)* automatically chooses `deno`, `node`, or `console`
37+
- `console` — outputs to console.log and console.error
38+
- `node` — outputs to process.stdout and process.stderr
39+
- `deno` — outputs to Deno.stdout and Deno.stderr
40+
- `void` — outputs nothing
41+
42+
### colors
43+
determines what happens when colors are used — available colors are:
44+
- `auto`*(default)* use color if it looks like we're in a color-supporting environment
45+
- `colorful` — full ansi color support
46+
- `colorless` — no color support (all color fns are duds)
47+
48+
### shapers
49+
a shaper is a fn that transforms the content before it is logged — you can attach any number of shapers, they are executed in order — by default, no shapers are used — the available shapers are:
50+
- `timestamp` — attaches a timestamp prefix to every message
51+
3252
<br/>
3353

3454
## 💖 made with open source love

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
"s"
1212
],
1313
"scripts": {
14-
"build": "tsc",
14+
"build": "run-s _clean _tsc",
15+
"_tsc": "tsc",
16+
"_clean": "rm -rf x",
1517
"build-watch": "tsc -w",
16-
"test": "node x/example.test.js --verbose",
17-
"test-watch": "node --watch x/example.test.js --verbose",
18+
"test": "node x/tests.test.js",
19+
"test-watch": "node --watch x/tests.test.js",
1820
"start": "run-p build-watch test-watch",
1921
"count": "find s -path '*/_archive' -prune -o -name '*.ts' -exec wc -l {} +"
2022
},

s/colors/auto.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
import {colorless} from "./colorless.js"
3+
import {colorful, Colors} from "./colorful.js"
4+
import {isColorSupported} from "../utils/supports.js"
5+
6+
export const autoColors = (): Colors => {
7+
return isColorSupported()
8+
? colorful
9+
: colorless
10+
}
11+

s/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
11

2+
export {Logger} from "./logger.js"
3+
export {Writer} from "./writers/writer.js"
4+
export {Colors} from "./colors/colorful.js"
5+
export {Shaper, ShaperContext, ShaperFns} from "./shapers/shaper.js"
6+

s/logger.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,58 @@
11

2-
import {Target} from "./targets/target.js"
2+
import {Writer} from "./writers/writer.js"
33
import {Shaper} from "./shapers/shaper.js"
4-
import {denoTarget} from "./targets/deno.js"
5-
import {nodeTarget} from "./targets/node.js"
4+
import {autoColors} from "./colors/auto.js"
5+
import {denoWriter} from "./writers/deno.js"
6+
import {nodeWriter} from "./writers/node.js"
7+
import {voidWriter} from "./writers/void.js"
8+
import {autoWriter} from "./writers/auto.js"
69
import {colorless} from "./colors/colorless.js"
7-
import {consoleTarget} from "./targets/console.js"
8-
import {isColorSupported} from "./utils/supports.js"
10+
import {consoleWriter} from "./writers/console.js"
911
import {colorful, Colors} from "./colors/colorful.js"
1012
import {timestampShaper} from "./shapers/timestamp.js"
1113

1214
export class Logger {
13-
static targets = {
14-
deno: denoTarget,
15-
node: nodeTarget,
16-
console: consoleTarget,
15+
static writers = {
16+
auto: autoWriter,
17+
void: voidWriter,
18+
deno: denoWriter,
19+
node: nodeWriter,
20+
console: consoleWriter,
1721
}
1822

1923
static colors = {
24+
auto: autoColors,
2025
colorful: () => colorful,
2126
colorless: () => colorless,
22-
auto: () => isColorSupported()
23-
? colorful
24-
: colorless,
2527
}
2628

2729
static shapers = {
2830
timestamp: timestampShaper,
2931
}
3032

3133
colors: Colors = Logger.colors.auto()
32-
target = consoleTarget()
34+
writer: Writer = Logger.writers.auto()
3335
shapers: Shaper[] = []
3436

3537
async log(...items: any[]) {
3638
for (const transform of this.shapers)
3739
items = transform(this).stdout(items)
38-
await this.target.stdout(items)
40+
await this.writer.stdout(items)
3941
}
4042

4143
async error(...items: any[]) {
4244
for (const transform of this.shapers)
4345
items = transform(this).stderr(items)
44-
await this.target.stderr(items)
46+
await this.writer.stderr(items)
4547
}
4648

4749
setColors(colors: Colors) {
4850
this.colors = colors
4951
return this
5052
}
5153

52-
setTarget(target: Target) {
53-
this.target = target
54+
setWriter(writer: Writer) {
55+
this.writer = writer
5456
return this
5557
}
5658

s/shapers/shaper.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ export type ShaperContext = {
55
colors: Colors
66
}
77

8-
export type Shaper = (context: ShaperContext) => ShapeFns
8+
export type Shaper = (context: ShaperContext) => ShaperFns
99

10-
export type ShapeFns = {
10+
export type ShaperFns = {
1111
stdout: (items: any[]) => any[]
1212
stderr: (items: any[]) => any[]
1313
}

s/tests.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
import {Logger} from "./logger.js"
3-
import {MockTarget} from "./targets/mock.js"
3+
import {MockWriter} from "./writers/mock.js"
44
import {Science, test, expect} from "@e280/science"
55

66
await Science.run({
@@ -9,21 +9,21 @@ await Science.run({
99
void new Logger()
1010
}),
1111
"logger with mock": test(async() => {
12-
const mock = new MockTarget()
13-
void new Logger().setTarget(mock)
12+
const mock = new MockWriter()
13+
void new Logger().setWriter(mock)
1414
}),
1515
"logger stdout": test(async() => {
16-
const mock = new MockTarget()
17-
const logger = new Logger().setTarget(mock)
16+
const mock = new MockWriter()
17+
const logger = new Logger().setWriter(mock)
1818
expect(mock.stdout.spy.calls.length).is(0)
1919
await logger.log("hello world!")
2020
expect(mock.stdout.spy.calls.length).is(1)
2121
expect(mock.getSpyStdout(0)).is("hello world!")
2222
expect(mock.stderr.spy.calls.length).is(0)
2323
}),
2424
"logger stderr": test(async() => {
25-
const mock = new MockTarget()
26-
const logger = new Logger().setTarget(mock)
25+
const mock = new MockWriter()
26+
const logger = new Logger().setWriter(mock)
2727
expect(mock.stderr.spy.calls.length).is(0)
2828
await logger.error("hello world!")
2929
expect(mock.stderr.spy.calls.length).is(1)
@@ -34,9 +34,9 @@ await Science.run({
3434

3535
"shapers": Science.suite({
3636
"custom prefix": test(async() => {
37-
const mock = new MockTarget()
37+
const mock = new MockWriter()
3838
const logger = new Logger()
39-
.setTarget(mock)
39+
.setWriter(mock)
4040
.addShaper(() => ({
4141
stdout: items => ["stdout:", ...items],
4242
stderr: items => ["stderr:", ...items],

s/targets/mock.ts renamed to s/utils/spy.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11

2-
import {Target} from "./target.js"
3-
42
export function spy<Fn extends (...args: any[]) => any>(fn: Fn) {
53
const calls: {args: Parameters<Fn>, ret: ReturnType<Fn>}[] = []
64

@@ -30,18 +28,3 @@ export function spy<Fn extends (...args: any[]) => any>(fn: Fn) {
3028
return spyFn
3129
}
3230

33-
export class MockTarget implements Target {
34-
stdout = spy((_items: any[]) => {})
35-
stderr = spy((_items: any[]) => {})
36-
37-
getSpyStdout(index: number) {
38-
const [items] = this.stdout.spy.args.at(index)!
39-
return items.join(" ")
40-
}
41-
42-
getSpyStderr(index: number) {
43-
const [items] = this.stderr.spy.args.at(index)!
44-
return items.join(" ")
45-
}
46-
}
47-

s/writers/auto.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
import {Writer} from "./writer.js"
3+
import {denoWriter} from "./deno.js"
4+
import {nodeWriter} from "./node.js"
5+
import {consoleWriter} from "./console.js"
6+
import {isDeno, isNode} from "../utils/supports.js"
7+
8+
export const autoWriter = (): Writer => {
9+
if (isDeno()) return denoWriter()
10+
else if (isNode()) return nodeWriter()
11+
else return consoleWriter()
12+
}
13+

s/targets/console.ts renamed to s/writers/console.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

2-
import {Target} from "./target.js"
2+
import {Writer} from "./writer.js"
33

4-
export const consoleTarget = (): Target => ({
4+
export const consoleWriter = (): Writer => ({
55
stdout: async(items: any[]) => console.log(...items),
66
stderr: async(items: any[]) => console.error(...items),
77
})

0 commit comments

Comments
 (0)