@amirabaris/webhook-kit 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +659 -2
- package/bin/webhook-kit.mjs +136 -0
- package/dist/index.cjs +1774 -0
- package/dist/index.d.cts +923 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +923 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.d.ts +923 -0
- package/dist/index.js +1774 -0
- package/dist/index.mjs +1738 -0
- package/dist/index.mjs.map +1 -0
- package/docs/agent-rules.md +151 -0
- package/package.json +83 -3
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* webhook-kit CLI
|
|
5
|
+
* Zero-dependency developer and agent tooling.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from "node:fs";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import process from "node:process";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
const START_MARKER = "<!-- webhook-kit-agent-rules:start -->";
|
|
17
|
+
const END_MARKER = "<!-- webhook-kit-agent-rules:end -->";
|
|
18
|
+
|
|
19
|
+
const AGENT_FILE_CANDIDATES = [
|
|
20
|
+
"AGENTS.md",
|
|
21
|
+
"CLAUDE.md",
|
|
22
|
+
".cursorrules",
|
|
23
|
+
".github/copilot-instructions.md",
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const AGENT_RULES_CONTENT = `${START_MARKER}
|
|
27
|
+
### Webhook Signature Verification Rules (webhook-kit)
|
|
28
|
+
- **NEVER parse JSON before verifying signatures**: In frameworks like Next.js, Hono, or Express, parsing JSON reorders keys and strips whitespace, invalidating cryptographic HMAC checks. Always pass the raw \`Request\` or raw text string.
|
|
29
|
+
- **Constant-Time Verification**: Never compare signatures with \`===\` or \`!==\`. Always use \`timingSafeEqual\` or \`verifyWebhookSignature\` from \`@amirabaris/webhook-kit\`.
|
|
30
|
+
- **Zero Node-Only Crypto**: Web standard environments (Cloudflare Workers, Next.js Edge, Bun, Deno) do not support \`node:crypto\`. Rely on \`@amirabaris/webhook-kit\` which uses \`crypto.subtle\`.
|
|
31
|
+
- **Conventional Commits**: Follow \`type(scope): message\` (e.g. \`feat(stripe): add tolerance check\`).
|
|
32
|
+
${END_MARKER}`;
|
|
33
|
+
|
|
34
|
+
function printHelp() {
|
|
35
|
+
console.log(`
|
|
36
|
+
webhook-kit CLI
|
|
37
|
+
|
|
38
|
+
Usage:
|
|
39
|
+
npx @amirabaris/webhook-kit <command> [options]
|
|
40
|
+
npx webhook-kit <command> [options]
|
|
41
|
+
|
|
42
|
+
Commands:
|
|
43
|
+
init-agent Inject or update webhook-kit rules into AGENTS.md or CLAUDE.md
|
|
44
|
+
version, -v Print current version
|
|
45
|
+
help, -h Show this help message
|
|
46
|
+
|
|
47
|
+
Options for init-agent:
|
|
48
|
+
--target <file> Target file (default: autodetects AGENTS.md or CLAUDE.md)
|
|
49
|
+
`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getPackageVersion() {
|
|
53
|
+
try {
|
|
54
|
+
const pkgPath = path.resolve(__dirname, "../package.json");
|
|
55
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
56
|
+
return pkg.version || "0.1.0";
|
|
57
|
+
} catch {
|
|
58
|
+
return "0.1.0";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function resolveTargetAgentFile(args) {
|
|
63
|
+
const targetIndex = args.indexOf("--target");
|
|
64
|
+
if (targetIndex !== -1 && args[targetIndex + 1]) {
|
|
65
|
+
return args[targetIndex + 1];
|
|
66
|
+
}
|
|
67
|
+
const existing = AGENT_FILE_CANDIDATES.find((candidate) =>
|
|
68
|
+
fs.existsSync(path.resolve(process.cwd(), candidate)),
|
|
69
|
+
);
|
|
70
|
+
return existing ?? "AGENTS.md";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function buildUpdatedAgentContent(existingContent, targetFile) {
|
|
74
|
+
const hasMarkers =
|
|
75
|
+
existingContent.includes(START_MARKER) &&
|
|
76
|
+
existingContent.includes(END_MARKER);
|
|
77
|
+
|
|
78
|
+
if (hasMarkers) {
|
|
79
|
+
const regex = new RegExp(`${START_MARKER}[\\s\\S]*?${END_MARKER}`, "g");
|
|
80
|
+
console.log(`Updated existing webhook-kit rules in ${targetFile}`);
|
|
81
|
+
return existingContent.replace(regex, AGENT_RULES_CONTENT);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const separator =
|
|
85
|
+
existingContent.length > 0 && !existingContent.endsWith("\n\n")
|
|
86
|
+
? "\n\n"
|
|
87
|
+
: "";
|
|
88
|
+
console.log(`Injected webhook-kit rules into ${targetFile}`);
|
|
89
|
+
return `${existingContent}${separator}${AGENT_RULES_CONTENT}\n`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function handleInitAgent(args) {
|
|
93
|
+
const targetFile = resolveTargetAgentFile(args);
|
|
94
|
+
const resolvedPath = path.resolve(process.cwd(), targetFile);
|
|
95
|
+
const existingContent = fs.existsSync(resolvedPath)
|
|
96
|
+
? fs.readFileSync(resolvedPath, "utf8")
|
|
97
|
+
: "";
|
|
98
|
+
|
|
99
|
+
const updatedContent = buildUpdatedAgentContent(existingContent, targetFile);
|
|
100
|
+
const parentDir = path.dirname(resolvedPath);
|
|
101
|
+
if (!fs.existsSync(parentDir)) {
|
|
102
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fs.writeFileSync(resolvedPath, updatedContent, "utf8");
|
|
106
|
+
console.log(`Rules synchronized successfully at ${resolvedPath}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const HELP_FLAGS = new Set(["help", "--help", "-h"]);
|
|
110
|
+
const VERSION_FLAGS = new Set(["version", "--version", "-v"]);
|
|
111
|
+
|
|
112
|
+
function main() {
|
|
113
|
+
const args = process.argv.slice(2);
|
|
114
|
+
const command = args[0];
|
|
115
|
+
|
|
116
|
+
if (!command || HELP_FLAGS.has(command)) {
|
|
117
|
+
printHelp();
|
|
118
|
+
process.exit(0);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (VERSION_FLAGS.has(command)) {
|
|
122
|
+
console.log(`webhook-kit v${getPackageVersion()}`);
|
|
123
|
+
process.exit(0);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (command === "init-agent") {
|
|
127
|
+
handleInitAgent(args.slice(1));
|
|
128
|
+
process.exit(0);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
console.error(`Unknown command: ${command}`);
|
|
132
|
+
printHelp();
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
main();
|