Skip to content

Commit b50ee94

Browse files
committed
init
0 parents  commit b50ee94

File tree

12 files changed

+501
-0
lines changed

12 files changed

+501
-0
lines changed

.github/workflows/commit-test.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Test
2+
on: push
3+
jobs:
4+
test:
5+
name: Test
6+
runs-on: ubuntu-latest
7+
steps:
8+
- name: checkout
9+
uses: actions/checkout@v4
10+
- name: setup Node.js
11+
uses: actions/setup-node@v4
12+
- name: install deps
13+
run: npm i
14+
- name: run test
15+
run: npx vitest run

.github/workflows/release.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Test
2+
on:
3+
release:
4+
types: [created]
5+
jobs:
6+
test:
7+
name: Test
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: checkout
11+
uses: actions/checkout@v4
12+
- name: setup Node.js
13+
uses: actions/setup-node@v4
14+
- name: install deps
15+
run: npm i
16+
- name: run test
17+
run: npx vitest run
18+
deploy:
19+
needs: test
20+
name: Deploy on npm
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout repo
24+
uses: actions/checkout@v4
25+
- name: Install Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: 22
29+
registry-url: https://registry.npmjs.org
30+
- name: Publish to npm
31+
run: npm publish
32+
env:
33+
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

.npmignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.gitignore
2+
.github
3+
tests

README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
![ublitzjs](https://github.com/ublitzjs/core/blob/main/logo.png)
2+
3+
# @ublitzjs/dev-comments package for removing unused code using build step
4+
5+
This package (currently) removes all code between <code>/\*\_START_DEV\_\*/</code> comment and <code>/\*\_END_DEV\_\*/</code>.
6+
7+
## minifyFile
8+
9+
For example, there is a file with console.log
10+
_some.js_
11+
12+
```javascript
13+
let a = 10;
14+
console.log("BEFORE", a);
15+
a = await doSomething(a);
16+
console.log("AFTER", a);
17+
sendSomewhere(a);
18+
```
19+
20+
But you want to debug this code AND don't care about that when the project goes to production<br>
21+
Just do this (esm or cjs - no difference)
22+
23+
_some.js_
24+
25+
```javascript
26+
let a = 10;
27+
/*_START_DEV_*/ console.log("BEFORE", a); /*_END_DEV_*/
28+
a = await prepare(a);
29+
/*_START_DEV_*/ console.log("AFTER", a); /*_END_DEV_*/
30+
sendSomewhere(a);
31+
```
32+
33+
and in separate file define "build" script
34+
35+
_build.js_
36+
37+
```javascript
38+
import { minifyFile } from "@ublitzjs/dev-comments";
39+
import path from "node:path";
40+
await minifyFile(
41+
/*absolute paths*/
42+
path.resolve(import.meta.dirname, "./some.js"),
43+
path.resolve(import.meta.dirname, "./some.output.js")
44+
);
45+
```
46+
47+
It will generate the file as follows
48+
49+
```javascript
50+
let a = 10;
51+
52+
a = await doSomething(a);
53+
54+
sendSomewhere(a);
55+
```
56+
57+
## minifyFolder
58+
59+
this function goes through all given file paths (which are off thee same format as keys of return type of "@ublitzjs/static".analyzeFolder function)
60+
61+
```javascript
62+
import { minifyFolder } from "@ublitzjs/dev-comments";
63+
64+
minifyFolder(
65+
/*input directory path relative ot absolute path*/ "from",
66+
/*ouput dir path*/ "to",
67+
/*files */ ["b.js"]
68+
);
69+
```
70+
71+
and example using analyzeFolder from "static" package
72+
73+
```javascript
74+
import { minifyFolder } from "@ublitzjs/dev-comments";
75+
import { analyzeFolder } from "@ublitzjs/static";
76+
77+
await minifyFolder(
78+
"from",
79+
"to",
80+
Object.keys(await analyzeFolder("from", { deleteMimesList: true }))
81+
);
82+
```

cjs/index.cjs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
var { Worker } = require("node:worker_threads");
2+
var path = require("node:path");
3+
var fs = require("fs/promises");
4+
var os = require("node:os");
5+
var cpus = os.cpus().length;
6+
7+
async function minifyFolder(inputDir, outputDir, filesToMinify) {
8+
await fs.mkdir(outputDir, { recursive: true });
9+
for (let i = 1; i <= cpus && filesToMinify.length; i++)
10+
RegisterWorkersToFiles(inputDir, outputDir, filesToMinify);
11+
}
12+
async function RegisterWorkersToFiles(inputDir, outputDir, filesToMinify) {
13+
do {
14+
const fileName = filesToMinify.shift();
15+
if (!fileName) return;
16+
const inputPath = path.join(inputDir, fileName);
17+
const outputPath = path.join(outputDir, fileName);
18+
await minifyFile(inputPath, outputPath);
19+
} while (filesToMinify.length);
20+
}
21+
22+
async function minifyFile(input, output) {
23+
const worker = new Worker(path.resolve(__dirname, "worker.cjs"), {
24+
workerData: {
25+
input,
26+
output,
27+
},
28+
});
29+
return new Promise((resolve, reject) => {
30+
worker.on("message", (msg) => {
31+
resolve(msg);
32+
});
33+
34+
worker.on("error", (err) => {
35+
reject(err);
36+
});
37+
worker.on("exit", (code) => {
38+
if (code !== 0) {
39+
reject(code);
40+
}
41+
});
42+
});
43+
}
44+
module.exports = {
45+
minifyFile,
46+
minifyFolder,
47+
};

cjs/worker.cjs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import fs from "node:fs";
2+
import { workerData, parentPort } from "node:worker_threads";
3+
import path from "node:path";
4+
5+
const { input, output } = workerData;
6+
7+
const START_TAG = "/*_START_DEV_*/";
8+
const END_TAG = "/*_END_DEV_*/";
9+
(async () => {
10+
await fs.promises.mkdir(path.dirname(output), { recursive: true });
11+
12+
const rs = fs.createReadStream(input, {
13+
encoding: "utf8",
14+
highWaterMark: 20,
15+
});
16+
const ws = fs.createWriteStream(output, { encoding: "utf8" });
17+
18+
let buffer = ""; // holds leftover across chunks
19+
let state = "KEEPING"; // or "DELETING"
20+
21+
rs.on("data", (chunk) => {
22+
buffer += chunk;
23+
let idx;
24+
25+
while (true) {
26+
if (state === "KEEPING") {
27+
idx = buffer.indexOf(START_TAG);
28+
// No START tag – flush all except trailing possible START_TAG prefix
29+
if (idx === -1) {
30+
const safeEnd = buffer.length - START_TAG.length + 1;
31+
if (safeEnd > 0) {
32+
ws.write(buffer.slice(0, safeEnd));
33+
buffer = buffer.slice(safeEnd);
34+
}
35+
break;
36+
} else {
37+
// Found START tag
38+
ws.write(buffer.slice(0, idx));
39+
buffer = buffer.slice(idx + START_TAG.length);
40+
state = "DELETING";
41+
}
42+
} else {
43+
idx = buffer.indexOf(END_TAG);
44+
if (idx === -1) {
45+
// Not found yet – trim buffer to last possible END_TAG start
46+
buffer = buffer.slice(-END_TAG.length + 1);
47+
break;
48+
} else {
49+
buffer = buffer.slice(idx + END_TAG.length);
50+
state = "KEEPING";
51+
}
52+
}
53+
}
54+
});
55+
56+
rs.on("end", () => {
57+
if (state === "KEEPING" && buffer.length > 0) {
58+
ws.write(buffer);
59+
}
60+
ws.end(() => parentPort.postMessage(`${input}${output}`));
61+
});
62+
63+
rs.on("error", (err) => parentPort.postMessage(`Read error: ${err}`));
64+
ws.on("error", (err) => parentPort.postMessage(`Write error: ${err}`));
65+
})();

index.d.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* This function takes all files (in 3rd parameter) and effectively utilizes worker threads to get all of your code prepared as soon as possible.
3+
* @param inputDir directory, which is 'compiled'
4+
* @param outputDir directory, to whichfiles are 'compiled'
5+
* @param filesToMinify array of filepaths, relative ot inputDir. will be created in same nested dirs and same names as is in inputDir.
6+
*/
7+
export function minifyFolder(
8+
inputDir: string,
9+
outputDir: string,
10+
filesToMinify: string[]
11+
): Promise<any>;
12+
/**
13+
* remove code in a single file
14+
* @param input ABSOLUTE path to input file
15+
* @param output ABSOLUTE path to output file
16+
*/
17+
export function minifyFile(
18+
input: string,
19+
output: string
20+
): Promise<Error | string>;

mjs/index.mjs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Worker } from "node:worker_threads";
2+
import path from "node:path";
3+
import fs from "node:fs/promises";
4+
import os from "node:os";
5+
var cpus = os.cpus().length;
6+
7+
async function minifyFolder(inputDir, outputDir, filesToMinify) {
8+
await fs.mkdir(outputDir, { recursive: true });
9+
for (let i = 1; i <= cpus && filesToMinify.length; i++)
10+
RegisterWorkersToFiles(inputDir, outputDir, filesToMinify);
11+
}
12+
async function RegisterWorkersToFiles(inputDir, outputDir, filesToMinify) {
13+
do {
14+
const fileName = filesToMinify.shift();
15+
if (!fileName) return;
16+
const inputPath = path.join(inputDir, fileName);
17+
const outputPath = path.join(outputDir, fileName);
18+
await minifyFile(inputPath, outputPath);
19+
} while (filesToMinify.length);
20+
}
21+
22+
async function minifyFile(input, output) {
23+
const worker = new Worker(new URL("./worker.mjs", import.meta.url), {
24+
workerData: {
25+
input,
26+
output,
27+
},
28+
});
29+
return new Promise((resolve, reject) => {
30+
worker.on("message", (msg) => {
31+
resolve(msg);
32+
});
33+
34+
worker.on("error", (err) => {
35+
reject(err);
36+
});
37+
worker.on("exit", (code) => {
38+
if (code !== 0) {
39+
reject(code);
40+
}
41+
});
42+
});
43+
}
44+
export { minifyFile, minifyFolder };

mjs/worker.mjs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import fs from "node:fs";
2+
import { workerData, parentPort } from "node:worker_threads";
3+
import path from "node:path";
4+
5+
const { input, output } = workerData;
6+
7+
const START_TAG = "/*_START_DEV_*/";
8+
const END_TAG = "/*_END_DEV_*/";
9+
10+
await fs.promises.mkdir(path.dirname(output), { recursive: true });
11+
12+
const rs = fs.createReadStream(input, { encoding: "utf8", highWaterMark: 20 });
13+
const ws = fs.createWriteStream(output, { encoding: "utf8" });
14+
15+
let buffer = ""; // holds leftover across chunks
16+
let state = "KEEPING"; // or "DELETING"
17+
18+
rs.on("data", (chunk) => {
19+
buffer += chunk;
20+
let idx;
21+
22+
while (true) {
23+
if (state === "KEEPING") {
24+
idx = buffer.indexOf(START_TAG);
25+
if (idx === -1) {
26+
// No START tag – flush all except trailing possible START_TAG prefix
27+
const safeEnd = buffer.length - START_TAG.length + 1;
28+
if (safeEnd > 0) {
29+
ws.write(buffer.slice(0, safeEnd));
30+
buffer = buffer.slice(safeEnd);
31+
}
32+
break;
33+
} else {
34+
// Found START tag
35+
ws.write(buffer.slice(0, idx));
36+
buffer = buffer.slice(idx + START_TAG.length);
37+
state = "DELETING";
38+
}
39+
} else {
40+
idx = buffer.indexOf(END_TAG);
41+
if (idx === -1) {
42+
// Not found yet – trim buffer to last possible END_TAG start
43+
buffer = buffer.slice(-END_TAG.length + 1);
44+
break;
45+
} else {
46+
buffer = buffer.slice(idx + END_TAG.length);
47+
state = "KEEPING";
48+
}
49+
}
50+
}
51+
});
52+
53+
rs.on("end", () => {
54+
if (state === "KEEPING" && buffer.length > 0) {
55+
ws.write(buffer);
56+
}
57+
ws.end(() => parentPort.postMessage(`${input}${output}`));
58+
});
59+
60+
rs.on("error", (err) => parentPort.postMessage(`Read error: ${err}`));
61+
ws.on("error", (err) => parentPort.postMessage(`Write error: ${err}`));

0 commit comments

Comments
 (0)