local-ticket-board 0.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 +18 -0
- package/bin/create-ticket-board.js +142 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# local-ticket-board
|
|
2
|
+
|
|
3
|
+
Scaffold the **Git Kanban - Local Ticket Board** into any repo via `npx`.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx local-ticket-board@latest kanban
|
|
9
|
+
cd kanban
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Options
|
|
14
|
+
|
|
15
|
+
- `--template <git-url>`: Use a different git repo as the template.
|
|
16
|
+
- `--no-install`: Skip `npm install`.
|
|
17
|
+
|
|
18
|
+
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
const DEFAULT_TEMPLATE = "https://github.com/Justbeingjustin/ticket-board.git";
|
|
7
|
+
|
|
8
|
+
function printHelp() {
|
|
9
|
+
console.log(`
|
|
10
|
+
local-ticket-board
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
npx local-ticket-board@latest [directory] [--template <git-url>] [--no-install]
|
|
14
|
+
|
|
15
|
+
Examples:
|
|
16
|
+
npx local-ticket-board@latest kanban
|
|
17
|
+
npx local-ticket-board@latest apps/kanban --no-install
|
|
18
|
+
npx local-ticket-board@latest kanban --template https://github.com/you/your-template.git
|
|
19
|
+
`.trim());
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function fail(message) {
|
|
23
|
+
console.error(`\nError: ${message}\n`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function parseArgs(argv) {
|
|
28
|
+
const args = argv.slice(2);
|
|
29
|
+
let dir;
|
|
30
|
+
let template = DEFAULT_TEMPLATE;
|
|
31
|
+
let install = true;
|
|
32
|
+
|
|
33
|
+
for (let i = 0; i < args.length; i++) {
|
|
34
|
+
const a = args[i];
|
|
35
|
+
if (!a) continue;
|
|
36
|
+
|
|
37
|
+
if (a === "-h" || a === "--help") {
|
|
38
|
+
return { help: true };
|
|
39
|
+
}
|
|
40
|
+
if (a === "--no-install") {
|
|
41
|
+
install = false;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (a === "--template") {
|
|
45
|
+
const v = args[i + 1];
|
|
46
|
+
if (!v) fail("--template requires a value");
|
|
47
|
+
template = v;
|
|
48
|
+
i++;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (a.startsWith("-")) {
|
|
52
|
+
fail(`Unknown option: ${a}`);
|
|
53
|
+
}
|
|
54
|
+
if (!dir) {
|
|
55
|
+
dir = a;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
fail(`Unexpected extra argument: ${a}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { help: false, dir: dir ?? "kanban", template, install };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function run(cmd, cmdArgs, opts = {}) {
|
|
65
|
+
const res = spawnSync(cmd, cmdArgs, {
|
|
66
|
+
stdio: "inherit",
|
|
67
|
+
shell: process.platform === "win32",
|
|
68
|
+
...opts,
|
|
69
|
+
});
|
|
70
|
+
if (res.status !== 0) {
|
|
71
|
+
fail(`Command failed: ${cmd} ${cmdArgs.join(" ")}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function rmIfExists(p) {
|
|
76
|
+
if (fs.existsSync(p)) {
|
|
77
|
+
fs.rmSync(p, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function ensureTargetDirEmpty(targetDir) {
|
|
82
|
+
if (!fs.existsSync(targetDir)) return;
|
|
83
|
+
const entries = fs.readdirSync(targetDir);
|
|
84
|
+
if (entries.length > 0) {
|
|
85
|
+
fail(`Target directory is not empty: ${targetDir}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function setPackageNameIfPossible(targetDir, name) {
|
|
90
|
+
try {
|
|
91
|
+
const pkgPath = path.join(targetDir, "package.json");
|
|
92
|
+
if (!fs.existsSync(pkgPath)) return;
|
|
93
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
94
|
+
pkg.name = name;
|
|
95
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
96
|
+
} catch {
|
|
97
|
+
// best-effort
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const parsed = parseArgs(process.argv);
|
|
102
|
+
if (parsed.help) {
|
|
103
|
+
printHelp();
|
|
104
|
+
process.exit(0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const targetDir = path.resolve(process.cwd(), parsed.dir);
|
|
108
|
+
const targetBaseName = path.basename(targetDir);
|
|
109
|
+
|
|
110
|
+
ensureTargetDirEmpty(targetDir);
|
|
111
|
+
|
|
112
|
+
// Ensure parent folder exists (e.g. apps/kanban)
|
|
113
|
+
fs.mkdirSync(path.dirname(targetDir), { recursive: true });
|
|
114
|
+
|
|
115
|
+
console.log(`\nCreating Ticket Board in: ${targetDir}`);
|
|
116
|
+
console.log(`Template: ${parsed.template}\n`);
|
|
117
|
+
|
|
118
|
+
// Clone template repo
|
|
119
|
+
run("git", ["clone", "--depth", "1", parsed.template, targetDir]);
|
|
120
|
+
|
|
121
|
+
// Remove git history so it becomes "your" project
|
|
122
|
+
rmIfExists(path.join(targetDir, ".git"));
|
|
123
|
+
|
|
124
|
+
// Remove GitHub-only files if present
|
|
125
|
+
rmIfExists(path.join(targetDir, ".github"));
|
|
126
|
+
|
|
127
|
+
// If the template repo name differs, adjust package name
|
|
128
|
+
setPackageNameIfPossible(targetDir, targetBaseName);
|
|
129
|
+
|
|
130
|
+
if (parsed.install) {
|
|
131
|
+
console.log("\nInstalling dependencies...\n");
|
|
132
|
+
run("npm", ["install"], { cwd: targetDir });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
console.log("\nDone.\n");
|
|
136
|
+
console.log("Next steps:");
|
|
137
|
+
console.log(` cd ${parsed.dir}`);
|
|
138
|
+
if (!parsed.install) console.log(" npm install");
|
|
139
|
+
console.log(" npm run dev");
|
|
140
|
+
console.log("");
|
|
141
|
+
|
|
142
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "local-ticket-board",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Scaffold the Git Kanban local ticket board into any repo.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/Justbeingjustin/ticket-board.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/Justbeingjustin/ticket-board",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/Justbeingjustin/ticket-board/issues"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"bin": {
|
|
16
|
+
"local-ticket-board": "bin/create-ticket-board.js"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"bin/"
|
|
23
|
+
],
|
|
24
|
+
"keywords": [
|
|
25
|
+
"create",
|
|
26
|
+
"scaffold",
|
|
27
|
+
"nextjs",
|
|
28
|
+
"kanban"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|