├── .editorconfig
├── .github
├── FUNDING.yml
└── workflows
│ ├── checks.yml
│ └── depsbot.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── assets
├── example.cast
└── example.svg
├── colors.ts
├── debug.ts
├── deps.ts
├── examples
└── hello.ts
├── format.ts
└── mod.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | indent_style = space
7 | indent_size = 2
8 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | open_collective: denosaurs
2 | github: denosaurs
3 |
--------------------------------------------------------------------------------
/.github/workflows/checks.yml:
--------------------------------------------------------------------------------
1 | name: check
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | lint:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Checkout sources
10 | uses: actions/checkout@v2
11 |
12 | - name: Setup latest deno version
13 | uses: denolib/setup-deno@v2
14 | with:
15 | deno-version: v1.x
16 |
17 | - name: Run deno fmt
18 | run: deno fmt --check
19 |
20 | - name: Run deno lint
21 | run: deno lint --unstable
22 |
23 | test:
24 | runs-on: ubuntu-latest
25 | steps:
26 | - name: Checkout sources
27 | uses: actions/checkout@v2
28 |
29 | - name: Setup latest deno version
30 | uses: denolib/setup-deno@v2
31 | with:
32 | deno-version: v1.x
33 |
34 | - name: Run deno test
35 | run: deno test --allow-none
36 |
--------------------------------------------------------------------------------
/.github/workflows/depsbot.yml:
--------------------------------------------------------------------------------
1 | name: depsbot
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 | schedule:
9 | - cron: "0 0 */2 * *"
10 |
11 | jobs:
12 | run:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout Repository
16 | uses: actions/checkout@v2
17 |
18 | - name: Run depsbot
19 | uses: denosaurs/depsbot@master
20 | with:
21 | github_token: ${{ secrets.GITHUB_TOKEN }}
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS files
2 | .DS_Store
3 | .cache
4 |
5 | # IDE
6 | .vscode
7 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog],
6 | and this project adheres to [Semantic Versioning].
7 |
8 | ## [0.2.0] - 2020-09-15
9 |
10 | ### Bug Fixes
11 |
12 | - deno 1.4.0 support ([`a111891`])
13 |
14 | ## [0.1.1] - 2020-09-13
15 |
16 | ### Features
17 |
18 | - deno.land/x release ([`4c11d60`])
19 |
20 | ## [0.1.0] - 2020-09-13
21 |
22 | ### Features
23 |
24 | - debug ([`1acbdd5`])
25 |
26 | ### Bug Fixes
27 |
28 | - remove withoutEnv default allow-all ([`32622f2`])
29 |
30 | [keep a changelog]: https://keepachangelog.com/en/1.0.0/
31 | [semantic versioning]: https://semver.org/spec/v2.0.0.html
32 | [0.2.0]: https://github.com/denosaurs/debug/compare/0.1.1...0.2.0
33 | [`a111891`]: https://github.com/denosaurs/debug/commit/a1118913fecda01aeb46b97a4659761271d27077
34 | [0.1.1]: https://github.com/denosaurs/debug/compare/0.1.0...0.1.1
35 | [`4c11d60`]: https://github.com/denosaurs/debug/commit/4c11d60d3be77f188376b1dcd57cff1254c41b7e
36 | [0.1.0]: https://github.com/denosaurs/debug/compare/0.1.0
37 | [`1acbdd5`]: https://github.com/denosaurs/debug/commit/1acbdd5206aef12d4b3922a76a2123a2a0be6b17
38 | [`32622f2`]: https://github.com/denosaurs/debug/commit/32622f2104e34f409081f6f9aead3a78879103eb
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-present the denosaurs team
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # debug
2 |
3 | [](https://github.com/denosaurs/debug/releases)
4 | [](https://github.com/denosaurs/debug/actions)
5 | [](https://github.com/denosaurs/depsbot)
6 | [](https://github.com/denosaurs/debug/blob/master/LICENSE)
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ```typescript
15 | import { debug } from "https://deno.land/x/debug/mod.ts";
16 |
17 | const log = debug("app");
18 | const name = "My Awesome App"
19 |
20 | const app = new Application();
21 |
22 | app.use((ctx) => {
23 | log("%s %s", ctx.request.method, ctx.request.url.pathname);
24 | ctx.response.body = "Hello World!";
25 | });
26 |
27 | log("Starting %s...", name);
28 | await app.listen({ port: 8000 });
29 | ```
30 |
31 | ```
32 | $ DEBUG=worker deno run --allow-env script.ts
33 | ```
34 |
35 | ## Namespace Colors
36 |
37 | Every debug instance has a color generated for it based on its namespace name.
38 | This helps when visually parsing the debug output to identify which debug instance
39 | a debug line belongs to.
40 |
41 | ## Millisecond diff
42 |
43 | When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
44 |
45 | ## Wildcards
46 |
47 | The `*` character may be used as a wildcard. Suppose for example your library has
48 | debuggers named "connect:bodyParser", "connect:compress", "connect:session",
49 | instead of listing all three with
50 | `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do
51 | `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
52 |
53 | You can also exclude specific debuggers by prefixing them with a "-" character.
54 | For example, `DEBUG=*,-connect:*` would include all debuggers except those
55 | starting with "connect:".
56 |
57 | ## Formatters
58 |
59 | Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.
60 | Below are the officially supported formatters:
61 |
62 | | Formatter | Representation |
63 | |-----------|----------------|
64 | | `%O` | Pretty-print an Object on multiple lines. |
65 | | `%o` | Pretty-print an Object all on a single line. |
66 | | `%s` | String. |
67 | | `%d` | Number (both integer and float). |
68 | | `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
69 | | `%%` | Single percent sign ('%'). This does not consume an argument. |
70 |
71 | ## Maintainers
72 |
73 | - Filippo Rossi ([@qu4k](https://github.com/qu4k))
74 |
75 | ## Other
76 |
77 | ### Related
78 |
79 | - [debug](https://github.com/visionmedia/debug) - A tiny JavaScript debugging utility modelled after Node.js core's debugging technique.
80 |
81 | ### Contribution
82 |
83 | Pull request, issues and feedback are very welcome. Code style is formatted with `deno fmt` and commit messages are done following Conventional Commits spec.
84 |
85 | ### Licence
86 |
87 | Copyright 2020-present, the denosaurs team. All rights reserved. MIT license.
88 |
--------------------------------------------------------------------------------
/assets/example.cast:
--------------------------------------------------------------------------------
1 | {"version": 2, "width": 105, "height": 41, "timestamp": 1599955843, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}}
2 | [0, "o", "$ DEBUG=app deno run --allow-env script.ts\r\n"]
3 | [0.273927, "o", "\u001b[34mapp\u001b[39m Starting My Awesome App... \u001b[34m+0ms\u001b[39m\r\n"]
4 | [0.755154, "o", "\u001b[34mapp\u001b[39m GET /hello \u001b[34m+583ms\u001b[39m\r\n"]
5 | [1.266938, "o", "\u001b[34mapp\u001b[39m GET /world \u001b[34m+511ms\u001b[39m\r\n"]
6 | [1.78001, "o", "\u001b[34mapp\u001b[39m GET /debug \u001b[34m+514ms\u001b[39m\r\n"]
7 | [2.293136, "o", "\u001b[34mapp\u001b[39m GET /is \u001b[34m+513ms\u001b[39m\r\n"]
8 | [2.804962, "o", "\u001b[34mapp\u001b[39m GET /awesome \u001b[34m+511ms\u001b[39m\r\n"]
9 | [5.644236, "o", "^C"]
10 |
--------------------------------------------------------------------------------
/assets/example.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/colors.ts:
--------------------------------------------------------------------------------
1 | import { colors } from "./deps.ts";
2 |
3 | export type ColorFunction = (message: string) => string;
4 | export const colorFunctions: ColorFunction[] = [
5 | colors.red,
6 | colors.green,
7 | colors.yellow,
8 | colors.blue,
9 | colors.magenta,
10 | colors.cyan,
11 | ];
12 |
13 | function hashCode(s: string): number {
14 | let h = 0;
15 | let l = s.length;
16 | let i = 0;
17 | if (l > 0) while (i < l) h = ((h << 5) - h + s.charCodeAt(i++)) | 0;
18 | return h;
19 | }
20 |
21 | export function generateColor(message: string): ColorFunction {
22 | const hash = Math.abs(hashCode(message));
23 | return colorFunctions[hash % colorFunctions.length];
24 | }
25 |
--------------------------------------------------------------------------------
/debug.ts:
--------------------------------------------------------------------------------
1 | import { generateColor, ColorFunction } from "./colors.ts";
2 | import { encode } from "./deps.ts";
3 | import { format } from "./format.ts";
4 |
5 | export interface Debug {
6 | (fmt: string, ...args: unknown[]): void;
7 | self: Debugger;
8 | }
9 |
10 | export class Debugger {
11 | manager: DebugManager;
12 | ns: string;
13 | color: ColorFunction;
14 | last: number;
15 | enabled: boolean;
16 |
17 | constructor(manager: DebugManager, namespace: string) {
18 | this.manager = manager;
19 | this.ns = namespace;
20 | this.color = generateColor(namespace);
21 | this.last = 0;
22 | this.enabled = manager.enabled.some((r) => r.test(namespace));
23 | }
24 |
25 | log(fmt: string, ...args: unknown[]): void {
26 | if (!this.enabled) return;
27 | const diff = Date.now() - (this.last || Date.now());
28 | fmt = format(fmt, ...args);
29 | const msg = `${this.color(this.ns)} ${fmt} ${this.color(`+${diff}ms`)}\n`;
30 | Deno.stderr.writeSync(encode(msg));
31 | this.last = Date.now();
32 | }
33 | }
34 |
35 | class DebugManager {
36 | debuggers: Map;
37 | enabled: RegExp[];
38 |
39 | constructor(enabled?: RegExp[]) {
40 | this.debuggers = new Map();
41 | this.enabled = enabled ?? [];
42 | }
43 | }
44 |
45 | function extract(opts?: string): RegExp[] {
46 | if (!opts || opts.length === 0) return [];
47 | opts = opts.replace(/\s/g, "").replace(/\*/g, ".+");
48 | return opts.split(",").map((rule) => new RegExp(`^${rule}$`));
49 | }
50 |
51 | let manager: DebugManager;
52 |
53 | export function withoutEnv(enabled?: RegExp[] | string) {
54 | if (!enabled) enabled = [];
55 | if (typeof enabled === "string") enabled = extract(enabled);
56 | manager = new DebugManager(enabled);
57 | }
58 |
59 | export function debug(namespace: string): Debug {
60 | if (!manager) manager = new DebugManager(extract(Deno.env.get("DEBUG")));
61 |
62 | const dbg = new Debugger(manager, namespace);
63 | manager.debuggers.set(namespace, dbg);
64 | const de: Debug = Object.assign(dbg.log.bind(dbg), {
65 | self: dbg,
66 | });
67 | return de;
68 | }
69 |
--------------------------------------------------------------------------------
/deps.ts:
--------------------------------------------------------------------------------
1 | export { createHash } from "https://deno.land/std@0.69.0/hash/mod.ts";
2 | export { encode } from "https://deno.land/std@0.69.0/encoding/utf8.ts";
3 | export * as colors from "https://deno.land/std@0.69.0/fmt/colors.ts";
4 |
--------------------------------------------------------------------------------
/examples/hello.ts:
--------------------------------------------------------------------------------
1 | import { debug } from "../mod.ts";
2 |
3 | const log = debug("app");
4 | const name = "My Awesome App";
5 |
6 | log("Starting %s...", name);
7 |
--------------------------------------------------------------------------------
/format.ts:
--------------------------------------------------------------------------------
1 | export function format(f: string, ...args: unknown[]) {
2 | let i = 0;
3 | let len = args.length;
4 | let str = String(f).replace(/%[sdjoO%]/g, (x: string): string => {
5 | if (x === "%%") return "%";
6 | if (i >= len) return x;
7 | switch (x) {
8 | case "%s":
9 | return String(args[i++]);
10 | case "%d":
11 | return Number(args[i++]).toString();
12 | case "%o":
13 | return Deno.inspect(args[i++]).split("\n").map((_) => _.trim()).join(
14 | " ",
15 | );
16 | case "%O":
17 | return Deno.inspect(args[i++]);
18 | case "%j":
19 | try {
20 | return JSON.stringify(args[i++]);
21 | } catch {
22 | return "[Circular]";
23 | }
24 | default:
25 | return x;
26 | }
27 | });
28 | for (const x of args.splice(i)) {
29 | if (x === null || !(typeof x === "object" && x !== null)) {
30 | str += " " + x;
31 | } else {
32 | str += " " + Deno.inspect(x);
33 | }
34 | }
35 | return str;
36 | }
37 |
--------------------------------------------------------------------------------
/mod.ts:
--------------------------------------------------------------------------------
1 | export * from "./debug.ts";
2 |
--------------------------------------------------------------------------------