@varavel/veta 0.0.0-dev

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/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # @varavel/veta
2
+
3
+ This package installs the Veta CLI from GitHub Releases and exposes it as the `veta` command.
4
+
5
+ ```sh
6
+ npm install --global @varavel/veta
7
+ veta --help
8
+ ```
package/bin.js ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require("node:child_process");
4
+ const { getBinaryPath } = require("./index.js");
5
+ const { install } = require("./install.js");
6
+
7
+ /**
8
+ * Runs the installed Veta binary, installing it first when necessary.
9
+ * @returns {Promise<void>}
10
+ */
11
+ async function main() {
12
+ let binaryPath;
13
+ try {
14
+ binaryPath = getBinaryPath();
15
+ } catch (_) {
16
+ await install();
17
+ binaryPath = getBinaryPath();
18
+ }
19
+
20
+ const child = spawn(binaryPath, process.argv.slice(2), {
21
+ stdio: ["inherit", "inherit", "inherit"],
22
+ });
23
+
24
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
25
+ process.on(signal, () => {
26
+ if (child.pid) child.kill(signal);
27
+ });
28
+ }
29
+
30
+ child.on("exit", (code) => {
31
+ process.exit(code || 0);
32
+ });
33
+
34
+ child.on("error", (error) => {
35
+ console.error(error.message);
36
+ process.exit(1);
37
+ });
38
+ }
39
+
40
+ main().catch((error) => {
41
+ console.error(error.message);
42
+ process.exit(1);
43
+ });
package/checksums.json ADDED
@@ -0,0 +1,2 @@
1
+ {
2
+ }
package/index.js ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ /**
7
+ * Returns the installed Veta binary path.
8
+ * @returns {string} Absolute path to the Veta binary.
9
+ */
10
+ function getBinaryPath() {
11
+ const binaryName = process.platform === "win32" ? "veta.exe" : "veta";
12
+ const binaryPath = path.join(__dirname, "bin", binaryName);
13
+
14
+ if (!fs.existsSync(binaryPath)) {
15
+ throw new Error(
16
+ `Veta binary not found at ${binaryPath}. `
17
+ + "Installation may have failed. Try reinstalling: npm install --global @varavel/veta",
18
+ );
19
+ }
20
+
21
+ return binaryPath;
22
+ }
23
+
24
+ /**
25
+ * Returns the installed npm package version.
26
+ * @returns {string} Package version without a v prefix.
27
+ */
28
+ function getVersion() {
29
+ const packageJson = require("./package.json");
30
+ return packageJson.version.replace(/^v/, "");
31
+ }
32
+
33
+ module.exports = {
34
+ getBinaryPath,
35
+ getVersion,
36
+ };
37
+
38
+ if (require.main === module) {
39
+ console.log(getBinaryPath());
40
+ }
package/install.js ADDED
@@ -0,0 +1,255 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execFileSync } = require("node:child_process");
4
+ const crypto = require("node:crypto");
5
+ const fs = require("node:fs");
6
+ const https = require("node:https");
7
+ const path = require("node:path");
8
+ const checksums = require("./checksums.json");
9
+
10
+ const PLATFORM_MAP = {
11
+ darwin: "darwin",
12
+ linux: "linux",
13
+ win32: "windows",
14
+ };
15
+
16
+ const ARCH_MAP = {
17
+ x64: "amd64",
18
+ arm64: "arm64",
19
+ };
20
+
21
+ /**
22
+ * Returns the platform name used by Veta release assets.
23
+ * @returns {string} Release platform name.
24
+ */
25
+ function getPlatform() {
26
+ const platform = PLATFORM_MAP[process.platform];
27
+ if (!platform) {
28
+ throw new Error(`Unsupported platform: ${process.platform}. Veta supports darwin, linux, and win32.`);
29
+ }
30
+ return platform;
31
+ }
32
+
33
+ /**
34
+ * Returns the architecture name used by Veta release assets.
35
+ * @returns {string} Release architecture name.
36
+ */
37
+ function getArch() {
38
+ const arch = ARCH_MAP[process.arch];
39
+ if (!arch) {
40
+ throw new Error(`Unsupported architecture: ${process.arch}. Veta supports x64 and arm64.`);
41
+ }
42
+ if (process.platform === "win32" && arch === "arm64") {
43
+ throw new Error("Unsupported platform: Veta does not currently publish Windows arm64 binaries.");
44
+ }
45
+ return arch;
46
+ }
47
+
48
+ /**
49
+ * Returns the package version without a v prefix.
50
+ * @returns {string} Package version.
51
+ */
52
+ function getVersion() {
53
+ const packageJson = require("./package.json");
54
+ return packageJson.version.replace(/^v/, "");
55
+ }
56
+
57
+ /**
58
+ * Returns the platform-specific Veta binary name.
59
+ * @returns {string} Binary filename.
60
+ */
61
+ function getBinaryName() {
62
+ return process.platform === "win32" ? "veta.exe" : "veta";
63
+ }
64
+
65
+ /**
66
+ * Returns the release archive filename for this platform.
67
+ * @returns {string} Release archive filename.
68
+ */
69
+ function getReleaseFilename() {
70
+ const platform = getPlatform();
71
+ const arch = getArch();
72
+ const extension = platform === "windows" ? "zip" : "tar.gz";
73
+ return `veta_${platform}_${arch}.${extension}`;
74
+ }
75
+
76
+ /**
77
+ * Returns the GitHub release download URL for this platform.
78
+ * @returns {string} Download URL.
79
+ */
80
+ function getDownloadURL() {
81
+ const version = getVersion();
82
+ return `https://github.com/varavelio/veta/releases/download/v${version}/${getReleaseFilename()}`;
83
+ }
84
+
85
+ /**
86
+ * Verifies an archive buffer against the checksum embedded in this npm package.
87
+ * @param {Buffer} archiveBuffer Downloaded archive bytes.
88
+ * @param {string} filename Expected filename in checksums.txt.
89
+ * @returns {void}
90
+ */
91
+ function verifyChecksum(archiveBuffer, filename) {
92
+ const expectedHash = checksums[filename];
93
+ if (!expectedHash) {
94
+ throw new Error(`Checksum for ${filename} was not embedded in this npm package.`);
95
+ }
96
+
97
+ const actualHash = crypto.createHash("sha256").update(archiveBuffer).digest("hex");
98
+ if (expectedHash !== actualHash) {
99
+ throw new Error(
100
+ `Checksum verification failed for ${filename}.\nExpected: ${expectedHash}\nActual: ${actualHash}`,
101
+ );
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Ensures and returns the package-local binary directory.
107
+ * @returns {string} Binary directory path.
108
+ */
109
+ function ensureBinDir() {
110
+ const binDir = path.join(__dirname, "bin");
111
+ fs.mkdirSync(binDir, { recursive: true });
112
+ return binDir;
113
+ }
114
+
115
+ /**
116
+ * Extracts a tar.gz archive into the package binary directory.
117
+ * @param {Buffer} buffer Archive bytes.
118
+ * @param {string} binDir Destination directory.
119
+ * @param {string} binaryName Expected binary filename.
120
+ * @returns {void}
121
+ */
122
+ function extractTarGz(buffer, binDir, binaryName) {
123
+ const tempName = Date.now().toString();
124
+ const tempArchive = path.join(binDir, `${tempName}.tar.gz`);
125
+ const tempDir = path.join(binDir, `${tempName}-extract`);
126
+
127
+ try {
128
+ fs.writeFileSync(tempArchive, buffer);
129
+ fs.mkdirSync(tempDir, { recursive: true });
130
+ execFileSync("tar", ["-xzf", tempArchive, "-C", tempDir], { stdio: "pipe" });
131
+ installExtractedBinary(tempDir, binDir, binaryName);
132
+ } finally {
133
+ fs.rmSync(tempArchive, { force: true });
134
+ fs.rmSync(tempDir, { recursive: true, force: true });
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Extracts a zip archive into the package binary directory.
140
+ * @param {Buffer} buffer Archive bytes.
141
+ * @param {string} binDir Destination directory.
142
+ * @param {string} binaryName Expected binary filename.
143
+ * @returns {void}
144
+ */
145
+ function extractZip(buffer, binDir, binaryName) {
146
+ const tempName = Date.now().toString();
147
+ const tempArchive = path.join(binDir, `${tempName}.zip`);
148
+ const tempDir = path.join(binDir, `${tempName}-extract`);
149
+
150
+ try {
151
+ fs.writeFileSync(tempArchive, buffer);
152
+ fs.mkdirSync(tempDir, { recursive: true });
153
+ if (process.platform === "win32") {
154
+ execFileSync(
155
+ "powershell",
156
+ [
157
+ "-NoProfile",
158
+ "-Command",
159
+ "Expand-Archive -LiteralPath $args[0] -DestinationPath $args[1] -Force",
160
+ tempArchive,
161
+ tempDir,
162
+ ],
163
+ { stdio: "pipe" },
164
+ );
165
+ } else {
166
+ execFileSync("unzip", ["-q", tempArchive, "-d", tempDir], { stdio: "pipe" });
167
+ }
168
+ installExtractedBinary(tempDir, binDir, binaryName);
169
+ } finally {
170
+ fs.rmSync(tempArchive, { force: true });
171
+ fs.rmSync(tempDir, { recursive: true, force: true });
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Copies the extracted binary into the package binary directory.
177
+ * @param {string} tempDir Extraction directory.
178
+ * @param {string} binDir Destination binary directory.
179
+ * @param {string} binaryName Expected binary filename.
180
+ * @returns {void}
181
+ */
182
+ function installExtractedBinary(tempDir, binDir, binaryName) {
183
+ const source = path.join(tempDir, binaryName);
184
+ if (!fs.existsSync(source)) {
185
+ throw new Error(`Binary ${binaryName} not found in release archive`);
186
+ }
187
+
188
+ const destination = path.join(binDir, binaryName);
189
+ fs.copyFileSync(source, destination);
190
+ if (process.platform !== "win32") {
191
+ fs.chmodSync(destination, 0o755);
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Downloads a URL as a Buffer, following redirects.
197
+ * @param {string} url URL to download.
198
+ * @returns {Promise<Buffer>} Downloaded bytes.
199
+ */
200
+ function download(url) {
201
+ return new Promise((resolve, reject) => {
202
+ https
203
+ .get(url, (response) => {
204
+ if ([301, 302, 307, 308].includes(response.statusCode)) {
205
+ download(response.headers.location).then(resolve).catch(reject);
206
+ return;
207
+ }
208
+ if (response.statusCode !== 200) {
209
+ reject(new Error(`Failed to download ${url}: HTTP ${response.statusCode}`));
210
+ return;
211
+ }
212
+
213
+ const chunks = [];
214
+ response.on("data", (chunk) => chunks.push(chunk));
215
+ response.on("end", () => resolve(Buffer.concat(chunks)));
216
+ response.on("error", reject);
217
+ })
218
+ .on("error", reject);
219
+ });
220
+ }
221
+
222
+ /**
223
+ * Downloads and installs the Veta binary for this platform.
224
+ * @returns {Promise<void>}
225
+ */
226
+ async function install() {
227
+ const platform = getPlatform();
228
+ const binaryName = getBinaryName();
229
+ const filename = getReleaseFilename();
230
+ const binDir = ensureBinDir();
231
+
232
+ try {
233
+ console.log(`Veta: Downloading ${filename}...`);
234
+ const archiveBuffer = await download(getDownloadURL());
235
+
236
+ console.log("Veta: Verifying checksum...");
237
+ verifyChecksum(archiveBuffer, filename);
238
+
239
+ console.log("Veta: Extracting...");
240
+ if (platform === "windows") {
241
+ extractZip(archiveBuffer, binDir, binaryName);
242
+ } else {
243
+ extractTarGz(archiveBuffer, binDir, binaryName);
244
+ }
245
+
246
+ console.log("Veta: Installation complete. Run 'veta --version' to verify.");
247
+ } catch (error) {
248
+ console.error("Veta: Installation failed");
249
+ console.error(`Veta: ${error.message}`);
250
+ process.exit(1);
251
+ }
252
+ }
253
+
254
+ if (require.main === module) install();
255
+ module.exports = { install };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@varavel/veta",
3
+ "version": "0.0.0-dev",
4
+ "description": "Veta static site generator",
5
+ "author": "Varavel",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/varavelio/veta",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/varavelio/veta.git",
11
+ "directory": "integrations/installers/npm"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/varavelio/veta/issues"
15
+ },
16
+ "type": "commonjs",
17
+ "main": "index.js",
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "bin": {
22
+ "veta": "bin.js"
23
+ },
24
+ "files": [
25
+ "bin.js",
26
+ "checksums.json",
27
+ "install.js",
28
+ "index.js",
29
+ "package.json",
30
+ "README.md"
31
+ ],
32
+ "scripts": {
33
+ "postinstall": "node install.js"
34
+ },
35
+ "keywords": [
36
+ "static-site-generator",
37
+ "ssg",
38
+ "markdown",
39
+ "tailwindcss",
40
+ "varavel"
41
+ ],
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ },
45
+ "os": [
46
+ "darwin",
47
+ "linux",
48
+ "win32"
49
+ ],
50
+ "cpu": [
51
+ "x64",
52
+ "arm64"
53
+ ]
54
+ }