sawit-utils 0.1.0

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.
@@ -0,0 +1,36 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Node.js Package
5
+
6
+ on:
7
+ release:
8
+ types: [created]
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: 24
19
+ - run: npm install
20
+ - run: npm ci
21
+ - run: npm test
22
+
23
+ publish-npm:
24
+ needs: build
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-node@v4
29
+ with:
30
+ node-version: 24
31
+ registry-url: https://registry.npmjs.org/
32
+ - run: npm install
33
+ - run: npm ci
34
+ - run: npm publish
35
+ env:
36
+ NODE_AUTH_TOKEN: ${{secrets.npm_token}}
@@ -0,0 +1,24 @@
1
+ name: Publish to JSR
2
+ on:
3
+ workflow_dispatch:
4
+
5
+ jobs:
6
+ publish:
7
+ runs-on: ubuntu-latest
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+ steps:
12
+ - name: Checkout
13
+ uses: actions/checkout@v6.0.2
14
+
15
+ - name: Setup Node
16
+ uses: actions/setup-node@v4
17
+ with:
18
+ node-version: '24'
19
+
20
+ - name: Install Package
21
+ run: npm install
22
+
23
+ - name: Publish package
24
+ run: npx jsr publish
package/.si.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "plugin": "org.smartide.plugin.nodejs",
3
+ "run": "npm test",
4
+ "gui": false,
5
+ "intelligence": {
6
+ ".json": {
7
+ "enabled": true,
8
+ "run": "vscode-json-language-server --stdio"
9
+ },
10
+ ".js": {
11
+ "enabled": false,
12
+ "run": "typescript-language-server --stdio"
13
+ }
14
+ }
15
+ }
package/index.js ADDED
@@ -0,0 +1,110 @@
1
+ import moment from "moment-timezone";
2
+
3
+ export function convertMsToDuration(ms) {
4
+ if (!ms || ms <= 0) return "0 seconds";
5
+
6
+ const duration = moment.duration(ms);
7
+ const hasLargerUnits = duration.asSeconds() >= 1;
8
+
9
+ const parts = [];
10
+
11
+ if (duration.years() > 0) parts.push(`${duration.years()} years`);
12
+ if (duration.months() > 0) parts.push(`${duration.months()} months`);
13
+ if (duration.weeks() > 0) parts.push(`${duration.weeks()} weeks`);
14
+ if (duration.days() > 0) parts.push(`${duration.days()} days`);
15
+ if (duration.hours() > 0) parts.push(`${duration.hours()} hours`);
16
+ if (duration.minutes() > 0) parts.push(`${duration.minutes()} minutes`);
17
+ if (duration.seconds() > 0) parts.push(`${duration.seconds()} seconds`);
18
+
19
+ if (!hasLargerUnits && duration.milliseconds() > 0)
20
+ parts.push(`${duration.milliseconds()} milliseconds`);
21
+
22
+ return parts.join(" ") || "0 detik";
23
+ }
24
+
25
+ export function formatSize(byteCount, withPerSecond = false) {
26
+ if (!byteCount) return `0 yBytes${withPerSecond ? "/s" : ""}`;
27
+
28
+ let index = 8;
29
+ let size = byteCount;
30
+ const bytes = [
31
+ "yBytes",
32
+ "zBytes",
33
+ "aBytes",
34
+ "fBytes",
35
+ "pBytes",
36
+ "nBytes",
37
+ "µBytes",
38
+ "mBytes",
39
+ "Bytes",
40
+ "KiB",
41
+ "MiB",
42
+ "GiB",
43
+ "TiB",
44
+ "PiB",
45
+ "EiB",
46
+ "ZiB",
47
+ "YiB",
48
+ ];
49
+
50
+ while (size < 1 && index > 0) {
51
+ size *= 1024;
52
+ index--;
53
+ }
54
+
55
+ while (size >= 1024 && index < bytes.length - 1) {
56
+ size /= 1024;
57
+ index++;
58
+ }
59
+
60
+ return `${size.toFixed(2)} ${bytes[index]}${withPerSecond ? "/s" : ""}`;
61
+ }
62
+
63
+ export function generateUID(id) {
64
+ if (!id) return null;
65
+
66
+ let hash = 0;
67
+ for (let i = 0; i < id.length; i++) {
68
+ const charCode = id.charCodeAt(i);
69
+ hash = (hash * 31 + charCode) % 1000000007;
70
+ }
71
+
72
+ const uniquePart = id.split("").reverse().join("").charCodeAt(0).toString(16);
73
+ let uid = `${Math.abs(hash).toString(16).toLowerCase()}-${uniquePart}`;
74
+ return uid;
75
+ }
76
+
77
+ export function getRandomElement(array) {
78
+ if (!array || !array.length || array.length === 0) return null;
79
+ return array[Math.floor(Math.random() * array.length)];
80
+ }
81
+
82
+ export function isUrl(url) {
83
+ if (!url) return false;
84
+ return /(https?:\/\/[^\s]+)/g.test(url);
85
+ }
86
+
87
+ export function delay(ms) {
88
+ if (!ms) return null;
89
+ return new Promise((res) => setTimeout(res, ms));
90
+ }
91
+
92
+ export const formatUptime = (startTime) => {
93
+ const uptime = Date.now() - startTime;
94
+ const seconds = Math.floor((uptime / 1000) % 60);
95
+ const minutes = Math.floor((uptime / (1000 * 60)) % 60);
96
+ const hours = Math.floor((uptime / (1000 * 60 * 60)) % 24);
97
+ const days = Math.floor(uptime / (1000 * 60 * 60 * 24));
98
+ return `${days}d ${hours}h ${minutes}m ${seconds}s`;
99
+ };
100
+
101
+ export const escapeHTML = (text) => {
102
+ if (!text) return "";
103
+ return text
104
+ .toString()
105
+ .replace(/&/g, "&amp;")
106
+ .replace(/</g, "&lt;")
107
+ .replace(/>/g, "&gt;")
108
+ .replace(/"/g, "&quot;")
109
+ .replace(/'/g, "&#039;");
110
+ };
package/jsr.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "@indra87g/sawit-utils",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "exports": "./index.js"
6
+ }
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "sawit-utils",
3
+ "description": "A palm-based utility for single-ball programmers who think palms are trees.",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "start": "node index.js",
8
+ "test": "vitest"
9
+ },
10
+ "dependencies": {
11
+ "moment": "^2.30.1",
12
+ "moment-timezone": "^0.6.0"
13
+ },
14
+ "devDependencies": {
15
+ "vitest": "^4.0.18"
16
+ }
17
+ }
@@ -0,0 +1,10 @@
1
+ import { expect, test, toBe } from "vitest";
2
+ import { convertMsToDuration, formatSize } from "../index.js";
3
+
4
+ test("convert 10000ms to equal 10s", () => {
5
+ expect(convertMsToDuration(10000)).toBe("10 seconds");
6
+ });
7
+
8
+ test("format 100000000bytes to equal 95.37 MiB", () => {
9
+ expect(formatSize(100000000)).toBe("95.37 MiB");
10
+ });