@makemore/scaffold 0.1.0
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 +71 -0
- package/bin/create-scaffold.js +75 -0
- package/bin/scaffold.js +47 -0
- package/package.json +38 -0
- package/scripts/install.js +122 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# create-scaffold
|
|
2
|
+
|
|
3
|
+
Bootstrap any software stack with sensible defaults.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Create a new Django project
|
|
9
|
+
npx create-scaffold myapp --base django
|
|
10
|
+
|
|
11
|
+
# Create a new Next.js project
|
|
12
|
+
npx create-scaffold myapp --base nextjs
|
|
13
|
+
|
|
14
|
+
# Interactive mode
|
|
15
|
+
npx create-scaffold myapp
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Available Templates
|
|
19
|
+
|
|
20
|
+
| Template | Description |
|
|
21
|
+
|----------|-------------|
|
|
22
|
+
| `django` | Django REST API with authentication, Cloud Tasks, S3 storage |
|
|
23
|
+
| `nextjs` | Next.js 15 with TypeScript, Tailwind CSS, shadcn/ui |
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Using npx (recommended)
|
|
29
|
+
npx create-scaffold <project-name> [options]
|
|
30
|
+
|
|
31
|
+
# Or install globally
|
|
32
|
+
npm install -g create-scaffold
|
|
33
|
+
scaffold init <project-name> [options]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Options
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
-b, --base <template> Base template (django, nextjs, or URL)
|
|
40
|
+
-a, --add <module> Additional modules to layer
|
|
41
|
+
-v, --var <key=value> Template variables
|
|
42
|
+
-o, --output <dir> Output directory
|
|
43
|
+
--no-prompt Disable interactive prompts
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Custom Templates
|
|
47
|
+
|
|
48
|
+
Use any git repository as a template:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# GitHub
|
|
52
|
+
npx create-scaffold myapp --base github:org/repo
|
|
53
|
+
|
|
54
|
+
# GitLab
|
|
55
|
+
npx create-scaffold myapp --base gitlab:org/repo
|
|
56
|
+
|
|
57
|
+
# Any git URL
|
|
58
|
+
npx create-scaffold myapp --base git:https://git.example.com/repo
|
|
59
|
+
|
|
60
|
+
# Local path
|
|
61
|
+
npx create-scaffold myapp --base file:~/templates/my-template
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Documentation
|
|
65
|
+
|
|
66
|
+
For full documentation, visit: https://github.com/makemore/scaffold
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
MIT
|
|
71
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* create-scaffold - npx wrapper for scaffold CLI
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx create-scaffold myapp
|
|
8
|
+
* npx create-scaffold myapp --base django
|
|
9
|
+
* npx create-scaffold --help
|
|
10
|
+
*
|
|
11
|
+
* This is equivalent to:
|
|
12
|
+
* scaffold init myapp
|
|
13
|
+
* scaffold init myapp --base django
|
|
14
|
+
* scaffold init --help
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { spawn } = require("child_process");
|
|
18
|
+
const path = require("path");
|
|
19
|
+
const fs = require("fs");
|
|
20
|
+
|
|
21
|
+
const BINARY_NAME = "scaffold";
|
|
22
|
+
|
|
23
|
+
function getBinaryPath() {
|
|
24
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
25
|
+
return path.join(__dirname, `${BINARY_NAME}${ext}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function main() {
|
|
29
|
+
const binaryPath = getBinaryPath();
|
|
30
|
+
|
|
31
|
+
if (!fs.existsSync(binaryPath)) {
|
|
32
|
+
console.error("Scaffold binary not found. Running install...");
|
|
33
|
+
require("../scripts/install.js");
|
|
34
|
+
|
|
35
|
+
// Check again after install
|
|
36
|
+
if (!fs.existsSync(binaryPath)) {
|
|
37
|
+
console.error("Failed to install scaffold binary.");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Prepend "init" to arguments for create-scaffold usage
|
|
43
|
+
// npx create-scaffold myapp -> scaffold init myapp
|
|
44
|
+
const userArgs = process.argv.slice(2);
|
|
45
|
+
|
|
46
|
+
// If first arg is --help or -h, show init help
|
|
47
|
+
// If first arg is --version or -v, show version
|
|
48
|
+
const firstArg = userArgs[0];
|
|
49
|
+
let args;
|
|
50
|
+
|
|
51
|
+
if (firstArg === "--version" || firstArg === "-v") {
|
|
52
|
+
args = ["version"];
|
|
53
|
+
} else if (firstArg === "--help" || firstArg === "-h" || !firstArg) {
|
|
54
|
+
args = ["init", "--help"];
|
|
55
|
+
} else {
|
|
56
|
+
args = ["init", ...userArgs];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const child = spawn(binaryPath, args, {
|
|
60
|
+
stdio: "inherit",
|
|
61
|
+
env: process.env,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
child.on("error", (err) => {
|
|
65
|
+
console.error(`Failed to run scaffold: ${err.message}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
child.on("exit", (code) => {
|
|
70
|
+
process.exit(code || 0);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
main();
|
|
75
|
+
|
package/bin/scaffold.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
|
|
7
|
+
const BINARY_NAME = "scaffold";
|
|
8
|
+
|
|
9
|
+
function getBinaryPath() {
|
|
10
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
11
|
+
return path.join(__dirname, `${BINARY_NAME}${ext}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function main() {
|
|
15
|
+
const binaryPath = getBinaryPath();
|
|
16
|
+
|
|
17
|
+
if (!fs.existsSync(binaryPath)) {
|
|
18
|
+
console.error("Scaffold binary not found. Running install...");
|
|
19
|
+
require("../scripts/install.js");
|
|
20
|
+
|
|
21
|
+
// Check again after install
|
|
22
|
+
if (!fs.existsSync(binaryPath)) {
|
|
23
|
+
console.error("Failed to install scaffold binary.");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Forward all arguments to the binary
|
|
29
|
+
const args = process.argv.slice(2);
|
|
30
|
+
|
|
31
|
+
const child = spawn(binaryPath, args, {
|
|
32
|
+
stdio: "inherit",
|
|
33
|
+
env: process.env,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
child.on("error", (err) => {
|
|
37
|
+
console.error(`Failed to run scaffold: ${err.message}`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
child.on("exit", (code) => {
|
|
42
|
+
process.exit(code || 0);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
main();
|
|
47
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@makemore/scaffold",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Bootstrap any software stack with sensible defaults",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"scaffold",
|
|
7
|
+
"template",
|
|
8
|
+
"generator",
|
|
9
|
+
"cli",
|
|
10
|
+
"project-generator",
|
|
11
|
+
"boilerplate"
|
|
12
|
+
],
|
|
13
|
+
"author": "MakeMore",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/makemore/scaffold"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"create-scaffold": "./bin/create-scaffold.js",
|
|
21
|
+
"scaffold": "./bin/scaffold.js"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"postinstall": "node scripts/install.js"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"bin",
|
|
31
|
+
"scripts",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const https = require("https");
|
|
6
|
+
const { execSync } = require("child_process");
|
|
7
|
+
|
|
8
|
+
const VERSION = "0.1.0";
|
|
9
|
+
const BINARY_NAME = "scaffold";
|
|
10
|
+
const GITHUB_REPO = "makemore/scaffold";
|
|
11
|
+
|
|
12
|
+
// Map Node.js platform/arch to Go platform/arch
|
|
13
|
+
const PLATFORM_MAP = {
|
|
14
|
+
darwin: "darwin",
|
|
15
|
+
linux: "linux",
|
|
16
|
+
win32: "windows",
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const ARCH_MAP = {
|
|
20
|
+
x64: "amd64",
|
|
21
|
+
arm64: "arm64",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
function getPlatform() {
|
|
25
|
+
const platform = PLATFORM_MAP[process.platform];
|
|
26
|
+
const arch = ARCH_MAP[process.arch];
|
|
27
|
+
|
|
28
|
+
if (!platform || !arch) {
|
|
29
|
+
console.error(`Unsupported platform: ${process.platform}/${process.arch}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { platform, arch };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getBinaryPath() {
|
|
37
|
+
const binDir = path.join(__dirname, "..", "bin");
|
|
38
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
39
|
+
return path.join(binDir, `${BINARY_NAME}${ext}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getDownloadUrl() {
|
|
43
|
+
const { platform, arch } = getPlatform();
|
|
44
|
+
const ext = platform === "windows" ? ".exe" : "";
|
|
45
|
+
return `https://github.com/${GITHUB_REPO}/releases/download/v${VERSION}/scaffold-${platform}-${arch}${ext}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function downloadBinary(url, dest) {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const file = fs.createWriteStream(dest);
|
|
51
|
+
|
|
52
|
+
const request = (url) => {
|
|
53
|
+
https
|
|
54
|
+
.get(url, (response) => {
|
|
55
|
+
// Handle redirects
|
|
56
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
57
|
+
request(response.headers.location);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (response.statusCode !== 200) {
|
|
62
|
+
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
response.pipe(file);
|
|
67
|
+
file.on("finish", () => {
|
|
68
|
+
file.close();
|
|
69
|
+
resolve();
|
|
70
|
+
});
|
|
71
|
+
})
|
|
72
|
+
.on("error", (err) => {
|
|
73
|
+
fs.unlink(dest, () => {});
|
|
74
|
+
reject(err);
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
request(url);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function install() {
|
|
83
|
+
const binaryPath = getBinaryPath();
|
|
84
|
+
const binDir = path.dirname(binaryPath);
|
|
85
|
+
|
|
86
|
+
// Create bin directory if it doesn't exist
|
|
87
|
+
if (!fs.existsSync(binDir)) {
|
|
88
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Check if binary already exists
|
|
92
|
+
if (fs.existsSync(binaryPath)) {
|
|
93
|
+
console.log("Scaffold binary already installed.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const downloadUrl = getDownloadUrl();
|
|
98
|
+
console.log(`Downloading scaffold from ${downloadUrl}...`);
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
await downloadBinary(downloadUrl, binaryPath);
|
|
102
|
+
|
|
103
|
+
// Make binary executable on Unix
|
|
104
|
+
if (process.platform !== "win32") {
|
|
105
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log("Scaffold installed successfully!");
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error(`Failed to download scaffold: ${error.message}`);
|
|
111
|
+
console.error(
|
|
112
|
+
"\nYou can manually download the binary from:"
|
|
113
|
+
);
|
|
114
|
+
console.error(
|
|
115
|
+
`https://github.com/${GITHUB_REPO}/releases`
|
|
116
|
+
);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
install();
|
|
122
|
+
|