Skip to content

Commit b06f938

Browse files
committed
[Fixes #4] Add support for examples
1 parent 10b2ae8 commit b06f938

File tree

2 files changed

+79
-15
lines changed

2 files changed

+79
-15
lines changed

config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ const starters = [
99
},
1010
];
1111

12+
const examples = {
13+
repoUrl: "https://github.com/stackbit-themes/stackbit-examples",
14+
directories: ["algolia-search", "dynamic-app", "sb-countdown", "sb-typist"],
15+
};
16+
1217
export default {
1318
defaults: { dirName: "my-stackbit-site", starter: starters[0] },
19+
examples,
1420
starters,
1521
};

index.js

Lines changed: 73 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ function prompt(question, defaultAnswer) {
2727
});
2828
}
2929

30+
async function installDependencies() {
31+
console.log(`Installing dependencies ...`);
32+
await run(`cd ${dirName} && npm install`);
33+
}
34+
35+
async function initGit() {
36+
console.log(`Setting up Git ...`);
37+
await run(`rm -rf ${dirName}/.git`);
38+
await run(
39+
`cd ${dirName} && git init && git add . && git commit -m "New Stackbit project"`
40+
);
41+
}
42+
3043
/* --- Parse CLI Arguments */
3144

3245
const args = yargs(hideBin(process.argv))
@@ -35,6 +48,11 @@ const args = yargs(hideBin(process.argv))
3548
describe: "Choose a starter",
3649
choices: config.starters.map((s) => s.name),
3750
})
51+
.option("example", {
52+
alias: "e",
53+
describe: "Start from an example",
54+
choices: config.examples.directories,
55+
})
3856
.help()
3957
.parse();
4058

@@ -43,27 +61,23 @@ const args = yargs(hideBin(process.argv))
4361
const starter = config.starters.find(
4462
(s) => s.name === (args.starter ?? config.defaults.starter.name)
4563
);
64+
65+
const timestamp = new Date().getTime();
66+
4667
const dirName =
4768
args._[0] ?? `${config.defaults.dirName}-${nanoid(8).toLowerCase()}`;
4869

49-
/* --- New Project --- */
70+
/* --- New Project from Starter --- */
5071

5172
async function cloneStarter() {
5273
// Clone repo
5374
const cloneCommand = `git clone --depth=1 ${starter.repoUrl} ${dirName}`;
5475
console.log(`\nCreating new project in ${dirName} ...`);
5576
await run(cloneCommand);
5677

57-
// Install dependencies
58-
console.log(`Installing dependencies ...`);
59-
await run(`cd ${dirName} && npm install`);
60-
61-
// Set up git
62-
console.log(`Setting up Git ...`);
63-
await run(`rm -rf ${dirName}/.git`);
64-
await run(
65-
`cd ${dirName} && git init && git add . && git commit -m "New Stackbit project"`
66-
);
78+
// Project Setup
79+
await installDependencies();
80+
await initGit();
6781

6882
// Output next steps:
6983
console.log(`
@@ -75,6 +89,37 @@ Follow the instructions for getting Started here:
7589
`);
7690
}
7791

92+
/* --- New Project from Example --- */
93+
94+
async function cloneExample() {
95+
const tmpDir = `examples-sparse-${timestamp}`;
96+
console.log(`\nCreating new project in ${dirName} ...`);
97+
98+
// Sparse clone the monorepo.
99+
await run(
100+
`git clone --depth 1 --filter=blob:none --sparse ${config.examples.repoUrl} ${tmpDir}`
101+
);
102+
// Checkout just the example dir.
103+
await run(`cd ${tmpDir} && git sparse-checkout set ${args.example}`);
104+
// Copy out into a new directory within current working directory.
105+
await run(`cp -R ${tmpDir}/${args.example} ${dirName}`);
106+
// Delete the clone.
107+
await run(`rm -rf ${tmpDir}`);
108+
109+
// Project Setup
110+
await installDependencies();
111+
await initGit();
112+
113+
// Output next steps:
114+
console.log(`
115+
🎉 ${chalk.bold("Your example project is ready!")} 🎉
116+
117+
Follow the instructions and learn more about the example here:
118+
119+
${config.examples.repoUrl}/tree/main/${args.example}#readme
120+
`);
121+
}
122+
78123
/* --- Existing Project --- */
79124

80125
async function integrateStackbit() {
@@ -96,9 +141,22 @@ Visit the following URL to learn more about the integration process:
96141

97142
/* --- Run --- */
98143

99-
const packageJsonFilePath = path.join(process.cwd(), "package.json");
100-
const hasPackageJson = fs.existsSync(packageJsonFilePath);
101-
const runFunc = hasPackageJson ? integrateStackbit : cloneStarter;
102-
await runFunc();
144+
async function doCreate() {
145+
// If the current directory has a package.json file, we assume we're in an
146+
// active project, and will not create a new project.
147+
const packageJsonFilePath = path.join(process.cwd(), "package.json");
148+
if (fs.existsSync(packageJsonFilePath)) return integrateStackbit();
149+
// If both starter and example were specified, throw an error message.
150+
if (args.starter && args.example) {
151+
console.error("[ERROR] Cannot specify a starter and an example.");
152+
process.exit(1);
153+
}
154+
// Start from an example if specified.
155+
if (args.example) return cloneExample();
156+
// Otherwise, use a starter, which falls back to the default if not set.
157+
return cloneStarter();
158+
}
159+
160+
await doCreate();
103161

104162
rl.close();

0 commit comments

Comments
 (0)