Skip to content

Commit b70110f

Browse files
authored
Feat/add cli command (#19)
* feat: add sw to the package and compilation with cli to copy code * feat: add cli command * chore: add new cli name * chore: add package.json keywords
1 parent b39b723 commit b70110f

5 files changed

Lines changed: 136 additions & 65 deletions

File tree

examples/my-twd-app/public/mock-sw.js

Lines changed: 1 addition & 63 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
"main": "./dist/twd.umd.js",
66
"module": "./dist/twd.es.js",
77
"types": "./dist/index.d.ts",
8+
"bin": {
9+
"twd-js": "./dist/cli.js"
10+
},
11+
"repository": {
12+
"type": "git",
13+
"url": "git@github.com:BRIKEV/twd.git"
14+
},
815
"exports": {
916
".": {
1017
"types": "./dist/index.d.ts",
@@ -16,7 +23,7 @@
1623
"dist"
1724
],
1825
"scripts": {
19-
"build": "vite build",
26+
"build": "vite build && vite build -c vite.sw.config.js && cp src/cli/installsw.js dist/cli.js",
2027
"test": "vitest",
2128
"test:ci": "vitest --run --coverage",
2229
"conventional-changelog": "conventional-changelog -i CHANGELOG.md",
@@ -37,5 +44,19 @@
3744
"vite": "^7.1.4",
3845
"vite-plugin-dts": "^4.5.4",
3946
"vitest": "^3.2.4"
40-
}
47+
},
48+
"keywords": [
49+
"testing",
50+
"twd-js",
51+
"twd",
52+
"tdd",
53+
"bdd",
54+
"test",
55+
"development",
56+
"react",
57+
"javascript",
58+
"typescript",
59+
"vite",
60+
"vitest"
61+
]
4162
}

src/cli/installsw.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env node
2+
import fs from "fs";
3+
import path from "path";
4+
import { fileURLToPath } from "url";
5+
6+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
7+
8+
const [, , command, targetDir, ...flags] = process.argv;
9+
10+
if (command !== "init") {
11+
console.error("Usage: npx twd-mock init <public-dir> [--save]");
12+
process.exit(1);
13+
}
14+
15+
if (!targetDir) {
16+
console.error("❌ You must provide a target public dir");
17+
process.exit(1);
18+
}
19+
20+
const save = flags.includes("--save");
21+
const src = path.join(__dirname, "../dist/mock-sw.js");
22+
const dest = path.resolve(process.cwd(), targetDir, "mock-sw.js");
23+
24+
fs.mkdirSync(path.dirname(dest), { recursive: true });
25+
fs.copyFileSync(src, dest);
26+
27+
console.log(`✅ mock-sw.js copied to ${dest}`);
28+
if (save) {
29+
console.log("💡 Remember to register it in your app:");
30+
console.log(`
31+
if ("serviceWorker" in navigator) {
32+
navigator.serviceWorker.register("/mock-sw.js?v=1");
33+
}
34+
`);
35+
}

src/cli/mock-sw.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// mock-sw.js
2+
3+
// Storage for rules inside the SW
4+
let rules = [];
5+
6+
/**
7+
* Match a request against rules
8+
*/
9+
const findRule = (method, url) => {
10+
return rules.find(
11+
(r) =>
12+
r.method === method &&
13+
(typeof r.url === "string" ? r.url === url : new RegExp(r.url).test(url))
14+
);
15+
};
16+
17+
// Intercept fetches
18+
self.addEventListener("fetch", (event) => {
19+
const { method } = event.request;
20+
const url = event.request.url;
21+
22+
const rule = findRule(method, url);
23+
24+
if (rule) {
25+
console.log("Mock hit:", rule.alias, method, url);
26+
27+
event.respondWith(
28+
(async () => {
29+
// Capture body if needed
30+
let body = null;
31+
try {
32+
body = await event.request.clone().text();
33+
} catch {}
34+
35+
// Mark executed and notify page
36+
self.clients.matchAll().then((clients) => {
37+
clients.forEach((client) =>
38+
client.postMessage({
39+
type: "EXECUTED",
40+
alias: rule.alias,
41+
request: body,
42+
})
43+
);
44+
});
45+
46+
return new Response(JSON.stringify(rule.response), {
47+
status: rule.status || 200,
48+
headers: rule.headers || { "Content-Type": "application/json" },
49+
});
50+
})()
51+
);
52+
}
53+
});
54+
55+
// Listen for messages from the app
56+
self.addEventListener("message", (event) => {
57+
const { type, rule } = event.data || {};
58+
if (type === "ADD_RULE") {
59+
rules = rules.filter((r) => r.alias !== rule.alias);
60+
rules.push(rule);
61+
console.log("Rule added:", rule);
62+
}
63+
});

vite.sw.config.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineConfig } from "vite";
2+
3+
export default defineConfig({
4+
build: {
5+
outDir: "dist",
6+
emptyOutDir: false,
7+
rollupOptions: {
8+
input: "src/cli/mock-sw.js",
9+
output: {
10+
entryFileNames: "mock-sw.js",
11+
},
12+
},
13+
},
14+
});

0 commit comments

Comments
 (0)