@mustafa60x/gitpack 0.0.1 → 1.0.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/README.md CHANGED
@@ -1,2 +1,76 @@
1
- # gitpack
2
- Smart project packer that respects `.gitignore`
1
+ # Gitpack
2
+
3
+ > Smart project packer that respects `.gitignore` or falls back to a sensible default exclusion list. Creates timestamped archives named after your package.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Smart Naming**:
8
+ - Uses `name` and `version` from `package.json` if available (e.g., `app-v1.3.0-2026-02-09_153045.zip`)
9
+ - Fallback to directory name + timestamp if `package.json` is missing.
10
+ - ✅ **Git Aware**:
11
+ - Uses `git ls-files` to include only tracked and non-ignored files.
12
+ - ✅ **Multiple Formats**: Support for `.zip` and `.tar.gz`.
13
+ - ✅ **Custom Output**: Control where your archive goes and what it includes.
14
+
15
+ ## Installation
16
+
17
+ You can run it directly with `npx`:
18
+
19
+ ```bash
20
+ npx @mustafa60x/gitpack
21
+ ```
22
+
23
+ Or install it globally:
24
+
25
+ ```bash
26
+ npm install -g @mustafa60x/gitpack
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```bash
32
+ gitpack [options]
33
+ ```
34
+
35
+ ### Options
36
+
37
+ | Flag | Description | Default |
38
+ |------|-------------|---------|
39
+ | `--format <type>` | Archive format (`zip` or `tar`). | `zip` |
40
+ | `--out <path>` | Specify output directory. | `../` (Parent directory) |
41
+ | `--include-env` | Include `.env` files (only in fallback mode). | `false` |
42
+ | `--no-git` | Force fallback mode (ignore `.git` data). | `false` |
43
+
44
+ ### Examples
45
+
46
+ **Standard Zip (Parent Directory)**
47
+ ```bash
48
+ gitpack
49
+ ```
50
+
51
+ **Custom Output to a 'backups' folder**
52
+ ```bash
53
+ gitpack --out ./backups
54
+ ```
55
+
56
+ **Generate a .tar.gz file**
57
+ ```bash
58
+ gitpack --format tar
59
+ ```
60
+
61
+ **Force fallback mode and include .env files**
62
+ ```bash
63
+ gitpack --no-git --include-env
64
+ ```
65
+
66
+ ## Output Table
67
+
68
+ | Scenario | `package.json` | Example Result |
69
+ |----------|---------------|-----------------|
70
+ | **Standard Zip** | `name: "app"`, `v1.3.0` | `app-v1.3.0-2026-02-09_032045.zip` |
71
+ | **Tar Mode** | `name: "app"` | `app-2026-02-09_032045.tar.gz` |
72
+ | **No Package** | (missing) | `folder_name-2026-02-09_032045.zip` |
73
+
74
+ ## License
75
+
76
+ MIT © [mustafa60x](https://github.com/mustafa60x)
package/bin/gitpack.js CHANGED
@@ -1,3 +1,157 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- console.log("Hello World");
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { execSync } from "child_process";
6
+ import archiver from "archiver";
7
+
8
+ // ----------------------
9
+ // ARG PARSE
10
+ // ----------------------
11
+
12
+ const args = process.argv.slice(2);
13
+
14
+ let format = "zip";
15
+ let outDir = path.dirname(process.cwd());
16
+ let includeEnv = false;
17
+ let noGit = false;
18
+
19
+ for (let i = 0; i < args.length; i++) {
20
+ if (args[i] === "--format" && args[i + 1]) {
21
+ format = args[i + 1];
22
+ i++;
23
+ } else if (args[i] === "--out" && args[i + 1]) {
24
+ outDir = path.resolve(args[i + 1]);
25
+ i++;
26
+ } else if (args[i] === "--include-env") {
27
+ includeEnv = true;
28
+ } else if (args[i] === "--no-git") {
29
+ noGit = true;
30
+ }
31
+ }
32
+
33
+ // ----------------------
34
+ // PROJECT INFO
35
+ // ----------------------
36
+
37
+ const now = new Date();
38
+ const pad = (n) => String(n).padStart(2, "0");
39
+ const dateStr = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
40
+ const timeStr = `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
41
+ const timestamp = `${dateStr}_${timeStr}`;
42
+
43
+ const cwd = process.cwd();
44
+ let projectName = path.basename(cwd);
45
+ let version = "";
46
+
47
+ const pkgPath = path.join(cwd, "package.json");
48
+
49
+ if (fs.existsSync(pkgPath)) {
50
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
51
+ if (pkg.name) projectName = pkg.name;
52
+ if (pkg.version) version = `-v${pkg.version.replace(/^v/, "")}`;
53
+ }
54
+
55
+ if (!fs.existsSync(outDir)) {
56
+ fs.mkdirSync(outDir, { recursive: true });
57
+ }
58
+
59
+ const extension = format === "tar" ? "tar.gz" : "zip";
60
+ const safeProjectName = projectName.replace(/^@/, "").replace(/\//g, "-");
61
+ const outputName = `${safeProjectName}${version}-${timestamp}.${extension}`;
62
+ const outputPath = path.join(outDir, outputName);
63
+
64
+ // ----------------------
65
+ // ARCHIVER SETUP
66
+ // ----------------------
67
+
68
+ const output = fs.createWriteStream(outputPath);
69
+
70
+ const archive =
71
+ format === "tar"
72
+ ? archiver("tar", { gzip: true, gzipOptions: { level: 9 } })
73
+ : archiver("zip", { zlib: { level: 9 } });
74
+
75
+ archive.pipe(output);
76
+
77
+ // ----------------------
78
+ // FILE STRATEGY
79
+ // ----------------------
80
+
81
+ const gitAvailable = fs.existsSync(path.join(cwd, ".git")) && !noGit;
82
+
83
+ // Calculate relative path of output to CWD for exclusion
84
+ const relativeOutputPath = path.relative(cwd, outputPath);
85
+ const isOutputInside = !relativeOutputPath.startsWith("..") && !path.isAbsolute(relativeOutputPath);
86
+
87
+ if (gitAvailable) {
88
+ let gitCommand = "git ls-files --cached --others --exclude-standard";
89
+
90
+ // If output is inside, exclude it from git listing
91
+ if (isOutputInside) {
92
+ gitCommand += ` -- ":(exclude)${relativeOutputPath}"`;
93
+ }
94
+
95
+ const files = execSync(gitCommand)
96
+ .toString()
97
+ .split("\n")
98
+ .filter(Boolean);
99
+
100
+ files.forEach((file) => {
101
+ archive.file(path.join(cwd, file), { name: file });
102
+ });
103
+ } else {
104
+ const ignoreList = [
105
+ "node_modules/**",
106
+ ".git/**",
107
+ ".nuxt/**",
108
+ "dist/**",
109
+ "build/**",
110
+ ".next/**",
111
+ "coverage/**"
112
+ ];
113
+
114
+ if (isOutputInside) {
115
+ ignoreList.push(relativeOutputPath);
116
+ // Also ignore the folder if specific outDir was used
117
+ const relativeOutDir = path.relative(cwd, outDir);
118
+ if (!relativeOutDir.startsWith("..") && relativeOutDir !== "") {
119
+ ignoreList.push(`${relativeOutDir}/**`);
120
+ }
121
+ }
122
+
123
+ if (!includeEnv) {
124
+ ignoreList.push(".env", ".env.*");
125
+ }
126
+
127
+ archive.glob("**/*", {
128
+ cwd,
129
+ ignore: ignoreList
130
+ });
131
+ }
132
+
133
+ // ----------------------
134
+
135
+ function formatBytes(bytes) {
136
+ if (bytes === 0) return "0 Bytes";
137
+ const k = 1024;
138
+ const sizes = ["Bytes", "KB", "MB", "GB"];
139
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
140
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
141
+ }
142
+
143
+ archive.finalize();
144
+
145
+ output.on("close", () => {
146
+ const stats = fs.statSync(outputPath);
147
+ const size = formatBytes(stats.size);
148
+
149
+ console.log("\n──────────────────────────────────────────");
150
+ console.log(` 🎁 Project: ${projectName}`);
151
+ if (version) console.log(` 🏷️ Version: ${version.slice(1)}`);
152
+ console.log(` 📦 Format: ${format === "tar" ? "tar.gz" : "zip"}`);
153
+ console.log(` 📏 Size: ${size}`);
154
+ console.log(` 🚀 Path: ${outputPath}`);
155
+ console.log("──────────────────────────────────────────");
156
+ console.log(` ✔ Archive successfully created!\n`);
157
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mustafa60x/gitpack",
3
- "version": "0.0.1",
3
+ "version": "1.0.1",
4
4
  "overrides": {
5
5
  "glob": "^11.0.0"
6
6
  },
@@ -8,6 +8,12 @@
8
8
  "bin": {
9
9
  "gitpack": "bin/gitpack.js"
10
10
  },
11
+ "scripts": {
12
+ "release": "./scripts/publish.sh",
13
+ "release:patch": "./scripts/publish.sh patch",
14
+ "release:minor": "./scripts/publish.sh minor",
15
+ "release:major": "./scripts/publish.sh major"
16
+ },
11
17
  "type": "module",
12
18
  "repository": {
13
19
  "type": "git",
@@ -30,4 +36,4 @@
30
36
  "dependencies": {
31
37
  "archiver": "^7.0.1"
32
38
  }
33
- }
39
+ }
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+
3
+ # Colors
4
+ GREEN='\033[0;32m'
5
+ BLUE='\033[0;34m'
6
+ YELLOW='\033[1;33m'
7
+ NC='\033[0m' # No Color
8
+
9
+ echo -e "${BLUE}🚀 Starting Gitpack Release...${NC}"
10
+
11
+ # Stop on error
12
+ set -e
13
+
14
+ # Version type (patch, minor, major) default: patch
15
+ TYPE=${1:-patch}
16
+
17
+ # 1. Check current git status
18
+ if [ -n "$(git status --porcelain)" ]; then
19
+ echo -e "${YELLOW}⚠️ Uncommitted changes found. Please clean or commit your changes first.${NC}"
20
+ exit 1
21
+ fi
22
+
23
+ # 2. Run tests (if any)
24
+ # npm test
25
+
26
+ # 3. Update version
27
+ echo -e "${BLUE}🔢 Updating version ($TYPE)...${NC}"
28
+ NEW_VERSION=$(npm version $TYPE --no-git-tag-version)
29
+
30
+ # 4. Commit changes and create tag
31
+ git add package.json package-lock.json
32
+ git commit -m "chore: release $NEW_VERSION"
33
+ git tag -a $NEW_VERSION -m "Release $NEW_VERSION"
34
+
35
+ # 5. Push to Git
36
+ echo -e "${BLUE}📤 Pushing to Git...${NC}"
37
+ CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
38
+ git push origin "$CURRENT_BRANCH" --follow-tags
39
+
40
+ # 6. Publish to NPM
41
+ echo -e "${BLUE}📦 Publishing to NPM...${NC}"
42
+ npm publish --access public
43
+
44
+ echo -e "${GREEN}🎉 Successfully published version $NEW_VERSION!${NC}"