@kyvrixon/utils 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,27 +1,28 @@
1
1
  {
2
- "name": "@kyvrixon/utils",
3
- "main": "./dist/index.js",
4
- "version": "0.0.2",
5
- "type": "module",
6
- "private": false,
7
- "files": [
8
- "dist"
9
- ],
10
- "packageManager": "bun@1.3.6",
11
- "types": "./dist/types/index.d.ts",
12
- "devDependencies": {
13
- "@types/bun": "1.3.6"
14
- },
15
- "peerDependencies": {
16
- "typescript": "^5.9.3"
17
- },
18
- "dependencies": {
19
- "chalk": "^5.6.2"
20
- },
21
- "exports": {
22
- ".": {
23
- "types": "./dist/types/index.d.ts",
24
- "import": "./dist/index.js"
25
- }
26
- }
2
+ "name": "@kyvrixon/utils",
3
+ "main": "./src/index.ts",
4
+ "version": "0.0.4",
5
+ "type": "module",
6
+ "private": false,
7
+ "license": "MIT",
8
+ "files": [
9
+ "src"
10
+ ],
11
+ "packageManager": "bun@1.3.6",
12
+ "types": "./src/index.ts",
13
+ "devDependencies": {
14
+ "@types/bun": "1.3.6"
15
+ },
16
+ "peerDependencies": {
17
+ "typescript": "^5.9.3"
18
+ },
19
+ "dependencies": {
20
+ "chalk": "^5.6.2"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "types": "./src/index.ts",
25
+ "import": "./src/index.ts"
26
+ }
27
+ }
27
28
  }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./lib/logger";
2
+ export * from "./lib/formatSeconds";
@@ -0,0 +1,135 @@
1
+ type TimeUnitTypes = "y" | "mo" | "w" | "d" | "h" | "m" | "s" | "ms";
2
+
3
+ const UNITS: Record<
4
+ TimeUnitTypes,
5
+ { label: string; short: string; ms: number }
6
+ > = {
7
+ y: { label: "year", short: "y", ms: 0 },
8
+ mo: { label: "month", short: "mo", ms: 0 },
9
+ w: { label: "week", short: "w", ms: 7 * 24 * 3600 * 1000 },
10
+ d: { label: "day", short: "d", ms: 24 * 3600 * 1000 },
11
+ h: { label: "hour", short: "h", ms: 3600 * 1000 },
12
+ m: { label: "minute", short: "m", ms: 60 * 1000 },
13
+ s: { label: "second", short: "s", ms: 1000 },
14
+ ms: { label: "millisecond", short: "ms", ms: 1 },
15
+ };
16
+
17
+ const ALL_UNITS_ORDER: Array<TimeUnitTypes> = [
18
+ "y",
19
+ "mo",
20
+ "w",
21
+ "d",
22
+ "h",
23
+ "m",
24
+ "s",
25
+ "ms",
26
+ ];
27
+
28
+ export const formatSeconds = (
29
+ seconds: number,
30
+ options: {
31
+ includeZeroUnits?: boolean;
32
+ onlyUnits?: Array<TimeUnitTypes>;
33
+ format?: "long" | "short";
34
+ customFormatter?: (
35
+ unit: TimeUnitTypes,
36
+ value: number,
37
+ label: string,
38
+ ) => string;
39
+ } = {},
40
+ ): string => {
41
+ const includeZeroUnits = options.includeZeroUnits ?? false;
42
+ const onlyUnits = options.onlyUnits ?? [];
43
+ const format = options.format ?? "long";
44
+ const customFormatter = options.customFormatter;
45
+
46
+ const totalMs = Math.max(0, Number(seconds) * 1000);
47
+ const unitsToDisplay = ALL_UNITS_ORDER.filter((u) =>
48
+ onlyUnits.length ? onlyUnits.includes(u) : true,
49
+ );
50
+
51
+ if (totalMs === 0) {
52
+ const zeroParts: Array<string> = [];
53
+ for (const u of unitsToDisplay) {
54
+ if (format === "short") {
55
+ zeroParts.push(`0${UNITS[u].short}`);
56
+ } else {
57
+ zeroParts.push(`0 ${UNITS[u].label}`);
58
+ }
59
+ }
60
+ return zeroParts.join(format === "short" ? " " : ", ");
61
+ }
62
+
63
+ const now = new Date();
64
+ const end = new Date(now.getTime() + totalMs);
65
+
66
+ let years = 0;
67
+ if (unitsToDisplay.includes("y") || unitsToDisplay.includes("mo")) {
68
+ years = end.getFullYear() - now.getFullYear();
69
+ }
70
+
71
+ let months = 0;
72
+ if (unitsToDisplay.includes("mo")) {
73
+ months = end.getMonth() - now.getMonth();
74
+ if (years < 0) months += 12;
75
+ }
76
+
77
+ const remainingMs =
78
+ end.getTime() -
79
+ new Date(
80
+ now.getFullYear() + years,
81
+ now.getMonth() + months,
82
+ now.getDate(),
83
+ now.getHours(),
84
+ now.getMinutes(),
85
+ now.getSeconds(),
86
+ now.getMilliseconds(),
87
+ ).getTime();
88
+
89
+ const diff: Record<TimeUnitTypes, number> = {
90
+ y: years,
91
+ mo: months,
92
+ w: Math.floor(remainingMs / UNITS.w.ms),
93
+ d: Math.floor((remainingMs % UNITS.w.ms) / UNITS.d.ms),
94
+ h: Math.floor((remainingMs % UNITS.d.ms) / UNITS.h.ms),
95
+ m: Math.floor((remainingMs % UNITS.h.ms) / UNITS.m.ms),
96
+ s: Math.floor((remainingMs % UNITS.m.ms) / UNITS.s.ms),
97
+ ms: remainingMs % 1000,
98
+ };
99
+
100
+ const showZeros = includeZeroUnits || onlyUnits.length > 0;
101
+
102
+ const parts: Array<string> = [];
103
+ for (const unit of unitsToDisplay) {
104
+ const value = diff[unit] ?? 0;
105
+ if (value || showZeros) {
106
+ let label = "";
107
+ if (format === "short") {
108
+ label = UNITS[unit].short;
109
+ } else {
110
+ if (value === 1) {
111
+ label = UNITS[unit].label;
112
+ } else {
113
+ label = `${UNITS[unit].label}s`;
114
+ }
115
+ }
116
+
117
+ if (customFormatter) {
118
+ parts.push(customFormatter(unit, value, label));
119
+ } else {
120
+ if (format === "short") {
121
+ parts.push(`${value}${label}`);
122
+ } else {
123
+ parts.push(`${value} ${label}`);
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ if (format === "long" && parts.length > 1) {
130
+ const last = parts.pop();
131
+ return `${parts.join(", ")} and ${last}`;
132
+ }
133
+
134
+ return parts.join(format === "short" ? " " : ",");
135
+ };
@@ -0,0 +1,124 @@
1
+ import { env } from "bun";
2
+ import chalk from "chalk";
3
+
4
+ type LogLevel = "notif" | "alert" | "error" | "debug";
5
+ const { cyan, yellow, red, magenta, dim, gray, bold } = chalk;
6
+ const formatter = new Intl.DateTimeFormat("en-AU", {
7
+ weekday: "short",
8
+ hour: "2-digit",
9
+ minute: "2-digit",
10
+ second: "2-digit",
11
+ hour12: false,
12
+ });
13
+
14
+ /**
15
+ * To enable debuging make the env variable `__DEBUG_MODE` equal to "1"
16
+ */
17
+ export class Logger {
18
+ private readonly colors: Record<LogLevel, typeof chalk> = {
19
+ notif: cyan,
20
+ alert: yellow,
21
+ error: red,
22
+ debug: magenta,
23
+ };
24
+
25
+ private readonly logMethods: Record<
26
+ LogLevel,
27
+ "log" | "warn" | "error" | "debug"
28
+ > = {
29
+ notif: "log",
30
+ alert: "warn",
31
+ error: "error",
32
+ debug: "debug",
33
+ };
34
+
35
+ private getTimestamp(): string {
36
+ const now = new Date();
37
+ const ms = now.getMilliseconds().toString().padStart(3, "0");
38
+ const base = formatter.format(now).replace(",", " @");
39
+ return `${base}.${ms}`;
40
+ }
41
+
42
+ private formatMessage(level: LogLevel, message: string | Error): string {
43
+ const timestamp = gray(`[${this.getTimestamp()}]`);
44
+ const levelLabel = bold(this.colors[level](level.toUpperCase().padEnd(5)));
45
+
46
+ const content =
47
+ message instanceof Error
48
+ ? `${red(message.message)}\n${dim(this.sanitizeStack(message.stack || ""))}`
49
+ : message;
50
+
51
+ return `${timestamp} ${levelLabel} ${dim("»")} ${content}`;
52
+ }
53
+
54
+ private sanitizeStack(stack: string): string {
55
+ return stack
56
+ .split("\n")
57
+ .filter((line) => !line.includes("(native") && line.includes(":"))
58
+ .map((line, index) => {
59
+ if (index === 0) return false;
60
+ return (
61
+ line
62
+ .trim()
63
+ // .replace(/\\/g, "/")
64
+ // .replace(
65
+ // /(.*):(\d+):(\d+)/,
66
+ // (_, f, l, c) => `${dim(f)} ${bold(`(L${l} C${c})`)}`,
67
+ // )
68
+ .replace(/at\s+/, " └─ ")
69
+ );
70
+ })
71
+ .filter(Boolean)
72
+ .join("\n");
73
+ }
74
+
75
+ private log(level: LogLevel, message: unknown, forceError?: boolean): void {
76
+ if (forceError) return void console.error(message);
77
+ void console[this.logMethods[level]](
78
+ this.formatMessage(level, message as string | Error),
79
+ );
80
+ }
81
+
82
+ /**
83
+ * Pring a regular (info) message
84
+ *
85
+ * @param m Message to display
86
+ */
87
+ public notif(m: unknown) {
88
+ this.log("notif", m);
89
+ }
90
+
91
+ /**
92
+ * Print an alert (warning)
93
+ *
94
+ * @param m Message to display
95
+ */
96
+ public alert(m: unknown) {
97
+ this.log("alert", m);
98
+ }
99
+
100
+ /**
101
+ * Print an error
102
+ *
103
+ * @param m Message to display
104
+ * @param e Error (optional)
105
+ * @param f Force error - directly calls `console.error()`
106
+ */
107
+ public error(m: unknown, e?: Error, f?: boolean) {
108
+ this.log("error", e ?? m, f);
109
+ }
110
+
111
+ /**
112
+ * Print a debug message
113
+ *
114
+ * @param m Message to display
115
+ */
116
+ public debug(m: unknown) {
117
+ if ("__DEBUG_MODE" in env && env.__DEBUG_MODE === "1") this.log("debug", m);
118
+ }
119
+
120
+ public divider(text: string): void {
121
+ const line = dim("─".repeat(Math.max(0, (50 - text.length - 2) / 2)));
122
+ console.log(`\n${line} ${bold(text.trim())} ${line}`);
123
+ }
124
+ }
package/dist/index.js DELETED
@@ -1 +0,0 @@
1
- export * from "./lib/Logger";
@@ -1,104 +0,0 @@
1
- import { env } from "bun";
2
- import chalk from "chalk";
3
- const { cyan, yellow, red, magenta, dim, gray, bold } = chalk;
4
- const formatter = new Intl.DateTimeFormat("en-AU", {
5
- weekday: "short",
6
- hour: "2-digit",
7
- minute: "2-digit",
8
- second: "2-digit",
9
- hour12: false,
10
- });
11
- /**
12
- * To enable debuging make the env variable `__DEBUG_MODE` equal to "1"
13
- */
14
- export class Logger {
15
- colors = {
16
- notif: cyan,
17
- alert: yellow,
18
- error: red,
19
- debug: magenta,
20
- };
21
- logMethods = {
22
- notif: "log",
23
- alert: "warn",
24
- error: "error",
25
- debug: "debug",
26
- };
27
- getTimestamp() {
28
- const now = new Date();
29
- const ms = now.getMilliseconds().toString().padStart(3, "0");
30
- const base = formatter.format(now).replace(",", " @");
31
- return `${base}:${ms}`;
32
- }
33
- formatMessage(level, message) {
34
- const timestamp = gray(`[${this.getTimestamp()}]`);
35
- const levelLabel = bold(this.colors[level](level.toUpperCase().padEnd(5)));
36
- const content = message instanceof Error
37
- ? `${red(message.message)}\n${dim(this.sanitizeStack(message.stack || ""))}`
38
- : message;
39
- return `${timestamp} ${levelLabel} ${dim("»")} ${content}`;
40
- }
41
- sanitizeStack(stack) {
42
- return stack
43
- .split("\n")
44
- .filter((line) => !line.includes("(native") && line.includes(":"))
45
- .map((line, index) => {
46
- if (index === 0)
47
- return false;
48
- return (line
49
- .trim()
50
- // .replace(/\\/g, "/")
51
- // .replace(
52
- // /(.*):(\d+):(\d+)/,
53
- // (_, f, l, c) => `${dim(f)} ${bold(`(L${l} C${c})`)}`,
54
- // )
55
- .replace(/at\s+/, " └─ "));
56
- })
57
- .filter(Boolean)
58
- .join("\n");
59
- }
60
- log(level, message, forceError) {
61
- if (forceError)
62
- return void console.error(message);
63
- void console[this.logMethods[level]](this.formatMessage(level, message));
64
- }
65
- /**
66
- * Pring a regular (info) message
67
- *
68
- * @param m Message to display
69
- */
70
- notif(m) {
71
- this.log("notif", m);
72
- }
73
- /**
74
- * Print an alert (warning)
75
- *
76
- * @param m Message to display
77
- */
78
- alert(m) {
79
- this.log("alert", m);
80
- }
81
- /**
82
- * Print an error
83
- *
84
- * @param m Message to display
85
- * @param e Error (optional)
86
- * @param f Force error - directly calls `console.error()`
87
- */
88
- error(m, e, f) {
89
- this.log("error", e ?? m, f);
90
- }
91
- /**
92
- * Print a debug message
93
- *
94
- * @param m Message to display
95
- */
96
- debug(m) {
97
- if ("__DEBUG_MODE" in env && env.__DEBUG_MODE === "1")
98
- this.log("debug", m);
99
- }
100
- divider(text) {
101
- const line = dim("─".repeat(Math.max(0, (50 - text.length - 2) / 2)));
102
- console.log(`\n${line} ${bold(text.trim())} ${line}`);
103
- }
104
- }
@@ -1,2 +0,0 @@
1
- export * from "./lib/Logger";
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
@@ -1,39 +0,0 @@
1
- /**
2
- * To enable debuging make the env variable `__DEBUG_MODE` equal to "1"
3
- */
4
- export declare class Logger {
5
- private readonly colors;
6
- private readonly logMethods;
7
- private getTimestamp;
8
- private formatMessage;
9
- private sanitizeStack;
10
- private log;
11
- /**
12
- * Pring a regular (info) message
13
- *
14
- * @param m Message to display
15
- */
16
- notif(m: unknown): void;
17
- /**
18
- * Print an alert (warning)
19
- *
20
- * @param m Message to display
21
- */
22
- alert(m: unknown): void;
23
- /**
24
- * Print an error
25
- *
26
- * @param m Message to display
27
- * @param e Error (optional)
28
- * @param f Force error - directly calls `console.error()`
29
- */
30
- error(m: unknown, e?: Error, f?: boolean): void;
31
- /**
32
- * Print a debug message
33
- *
34
- * @param m Message to display
35
- */
36
- debug(m: unknown): void;
37
- divider(text: string): void;
38
- }
39
- //# sourceMappingURL=Logger.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../../lib/Logger.ts"],"names":[],"mappings":"AAaA;;GAEG;AACH,qBAAa,MAAM;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAKrB;IAEF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAQzB;IAEF,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,GAAG;IAOX;;;;OAIG;IACI,KAAK,CAAC,CAAC,EAAE,OAAO;IAIvB;;;;OAIG;IACI,KAAK,CAAC,CAAC,EAAE,OAAO;IAIvB;;;;;;OAMG;IACI,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO;IAI/C;;;;OAIG;IACI,KAAK,CAAC,CAAC,EAAE,OAAO;IAIhB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAIlC"}