Skip to content

Commit 815a02d

Browse files
authored
Update CLI experience (#37)
* Refactor create-freedom-stack script to use cleye for CLI arguments - Integrated cleye for improved command-line argument parsing. - Updated project name retrieval to enhance usability and provide help documentation. - Modified success message formatting for clearer instructions on project setup. * Converted Turso CLI setup script to use Cleye * Refactor project setup and dependency management - Updated project name from "freedom-stack" to "create-freedom-stack" and adjusted version to 1.0.2 in package-lock.json and package.json. - Integrated `ora` for improved user feedback during dependency installation in create-freedom-stack script. - Enhanced the setup process by adding a spinner for better visibility of installation progress. - Cleaned up the setup-turso script by removing redundant readline interface initialization. - Added new dependencies: `cleye` for command-line argument parsing and `ora` for spinners. * fixed ts build errors * bumped package version * Update dependencies in package.json and package-lock.json - Bump versions for several packages including @alpinejs, astro, better-auth, better-sqlite3, isomorphic-dompurify, marked, ora, prettier, and others. - Remove outdated dependencies and update to the latest versions for improved performance and security. - Clean up package structure by removing unnecessary entries. These changes ensure the project is using the latest stable versions of its dependencies, enhancing overall functionality and security. * Add 'required' attribute to form fields in post creation and editing pages * Add GitHubButton component and update index.astro to include it - Introduced a new GitHubButton component that fetches and displays the star count from the GitHub API. - Updated index.astro to replace the previous GitHub link with the new GitHubButton component, enhancing user interaction. - Adjusted the Netlify link in the Navbar for better deployment guidance. * Update FAQ in index.astro to include Astro DB's Getting Started Guide - Revised the answer for the question about learning the libSQL database layer to recommend starting with Astro DB's Getting Started Guide before the High Performance SQLite course. - This change enhances the guidance provided to users seeking to learn about the database layer.
1 parent 86317bd commit 815a02d

File tree

13 files changed

+325
-205
lines changed

13 files changed

+325
-205
lines changed

Diff for: package-lock.json

+190-141
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+16-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "create-freedom-stack",
33
"type": "module",
4-
"version": "1.0.2",
4+
"version": "1.0.3",
55
"description": "Create a new Freedom Stack project - A modern, type-safe web development stack using Astro, TypeScript, HTMX, Alpine.js, and more",
66
"author": "Cameron Pak",
77
"license": "MIT",
@@ -51,36 +51,38 @@
5151
"host:login": "npx netlify login"
5252
},
5353
"dependencies": {
54-
"@alpinejs/collapse": "^3.14.3",
55-
"@alpinejs/intersect": "^3.14.3",
56-
"@alpinejs/mask": "^3.14.3",
57-
"@alpinejs/persist": "^3.14.3",
54+
"@alpinejs/collapse": "^3.14.4",
55+
"@alpinejs/intersect": "^3.14.4",
56+
"@alpinejs/mask": "^3.14.4",
57+
"@alpinejs/persist": "^3.14.4",
5858
"@astrojs/alpinejs": "^0.4.0",
5959
"@astrojs/check": "^0.9.4",
6060
"@astrojs/db": "^0.14.3",
6161
"@astrojs/netlify": "^5.5.4",
6262
"@astrojs/tailwind": "^5.1.2",
63-
"@iconify-json/lucide": "^1.2.15",
63+
"@iconify-json/lucide": "^1.2.16",
6464
"@iconify-json/lucide-lab": "^1.2.2",
65-
"alpinejs": "^3.14.3",
66-
"astro": "^4.16.14",
65+
"alpinejs": "^3.14.4",
66+
"astro": "^4.16.16",
6767
"astro-iconify": "^1.2.0",
6868
"astro-seo": "^0.8.4",
69-
"better-auth": "^1.0.0",
70-
"better-sqlite3": "^11.5.0",
69+
"better-auth": "^1.0.6",
70+
"better-sqlite3": "^11.6.0",
71+
"cleye": "^1.3.2",
7172
"drizzle-orm": "^0.36.4",
7273
"htmx.org": "2.0.1",
73-
"isomorphic-dompurify": "^2.16.0",
74-
"marked": "^14.1.3",
74+
"isomorphic-dompurify": "^2.17.0",
75+
"marked": "^15.0.2",
76+
"ora": "^8.1.1",
7577
"trix": "^2.1.8"
7678
},
7779
"devDependencies": {
7880
"@tailwindcss/typography": "^0.5.15",
79-
"@types/alpinejs": "^3.13.10",
81+
"@types/alpinejs": "^3.13.11",
8082
"@types/better-sqlite3": "^7.6.12",
8183
"daisyui": "^4.12.14",
8284
"netlify-cli": "^17.37.2",
83-
"prettier": "^3.3.3",
85+
"prettier": "^3.4.1",
8486
"prettier-plugin-astro": "^0.14.1",
8587
"tailwindcss": "^3.4.15",
8688
"typescript": "^5.7.2"

Diff for: scripts/create-freedom-stack.js

+28-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#!/usr/bin/env node
22

3+
import { cli } from "cleye";
34
import { execSync } from "child_process";
45
import fs from "fs";
56
import path from "path";
67
import { fileURLToPath } from "url";
78
import { randomUUID } from "crypto";
9+
import ora from "ora";
810

911
const __filename = fileURLToPath(import.meta.url);
1012
const __dirname = path.dirname(__filename);
@@ -113,29 +115,42 @@ pnpm-debug.log*
113115
);
114116
}
115117

118+
console.log("\n🕊️ Running create-freedom-stack...\n\n");
119+
116120
// Install dependencies
117-
console.log("Installing dependencies...");
118-
execSync("npm install", { stdio: "inherit" });
121+
const spinner = ora("Installing dependencies...").start();
122+
try {
123+
execSync("npm install", { stdio: ["pipe", "pipe", "pipe"] });
124+
spinner.succeed("Dependencies installed successfully!");
125+
} catch (error) {
126+
spinner.fail("Failed to install dependencies");
127+
console.error(error.message);
128+
process.exit(1);
129+
}
119130

120131
console.log(`
121132
🚀 Freedom Stack project created successfully!
122133
123134
To get started:
124-
cd ${projectName}
125-
npm run db:setup # Set up your Turso database
126-
npm run dev # Start the development server
135+
1. cd ${projectName}
136+
2. npm run db:setup # Set up your Turso database
137+
3. npm run dev # Start the development server
127138
128139
Visit http://localhost:4321 to see your app.
129140
`);
130141
}
131142

132-
// Get project name from command line arguments
133-
const projectName = process.argv[2];
134-
135-
if (!projectName) {
136-
console.error("Please specify a project name:");
137-
console.error(" npx create-freedom-stack my-app");
138-
process.exit(1);
139-
}
143+
const argv = cli({
144+
name: "create-freedom-stack",
145+
version: "0.1.0",
146+
description: "Create a new Freedom Stack project with best practices and modern tooling",
147+
flags: {},
148+
parameters: ["<projectName>"],
149+
help: {
150+
description: "Create a new Freedom Stack project",
151+
examples: ["npx create-freedom-stack my-app"]
152+
}
153+
});
140154

155+
const { projectName } = argv._;
141156
createProject(projectName);

Diff for: scripts/setup-turso.js

+32-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
#!/usr/bin/env node
22

3+
import { cli } from "cleye";
34
import { execSync } from "child_process";
45
import fs from "fs";
56
import path from "path";
6-
import { fileURLToPath } from "url";
77
import readline from "readline";
88

9-
const __filename = fileURLToPath(import.meta.url);
10-
const __dirname = path.dirname(__filename);
11-
129
const rl = readline.createInterface({
1310
input: process.stdin,
1411
output: process.stdout
@@ -27,7 +24,7 @@ function checkTursoAuth() {
2724
}
2825
}
2926

30-
async function setupTurso() {
27+
async function setupTurso(argv) {
3128
console.log("🔧 Setting up Turso database...");
3229

3330
try {
@@ -49,13 +46,14 @@ async function setupTurso() {
4946
console.log("\nRun these commands in order:");
5047
console.log("1. turso auth login");
5148
console.log("2. npm run db:setup");
52-
rl.close();
5349
process.exit(1);
5450
}
5551

56-
// Get database name from user
52+
// Use database name from CLI args or prompt
5753
const dbName =
58-
(await question("\nEnter a name for your database (default: freedom-stack-db): ")) || "freedom-stack-db";
54+
argv.flags.name ||
55+
(await question("\nEnter a name for your database (default: freedom-stack-db): ")) ||
56+
"freedom-stack-db";
5957

6058
// Create database
6159
console.log(`\n📚 Creating database: ${dbName}...`);
@@ -67,7 +65,6 @@ async function setupTurso() {
6765
console.log("\nRun these commands in order:");
6866
console.log("1. turso auth login");
6967
console.log("2. npm run db:setup");
70-
rl.close();
7168
process.exit(1);
7269
}
7370
throw error;
@@ -125,4 +122,29 @@ npm run dev # To start your development server
125122
}
126123
}
127124

128-
setupTurso();
125+
cli(
126+
{
127+
name: "setup-turso",
128+
version: "0.1.0",
129+
description: "Set up a Turso database for your Freedom Stack project",
130+
flags: {
131+
name: {
132+
type: String,
133+
description: "Name of the database to create",
134+
alias: "n"
135+
},
136+
force: {
137+
type: Boolean,
138+
description: "Override existing database if it exists",
139+
alias: "f",
140+
default: false
141+
}
142+
},
143+
help: {
144+
examples: ["npm run db:setup", "npm run db:setup --name my-database", "npm run db:setup -n my-database --force"]
145+
}
146+
},
147+
async (argv) => {
148+
await setupTurso(argv);
149+
}
150+
);

Diff for: src/actions/auth.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function setAuthCookiesFromResponse(cookiesArray: string[], cookies: Astr
3131

3232
async function handleAuthResponse(
3333
apiCall: () => Promise<Response>,
34-
context: ActionAPIContext,
34+
_context: ActionAPIContext,
3535
errorCode: ActionErrorCode
3636
) {
3737
try {

Diff for: src/components/TrixEditor.astro

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,5 @@ const { content, id = "content", name = "content", alpineRefName = "contentInput
1515
</div>
1616

1717
<script>
18-
// @ts-ignore - no types available
19-
import Trix from "trix";
18+
import "trix";
2019
</script>

Diff for: src/components/server/GithubButton.astro

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
import { Icon } from "astro-iconify";
3+
4+
// https://docs.astro.build/en/basics/astro-pages/#page-partials
5+
const repo = await fetch("https://api.github.com/repos/cameronapak/freedom-stack", {
6+
headers: {
7+
// Cache for 4 hours
8+
"Cache-Control": "public, max-age=14400",
9+
// Accept JSON response
10+
Accept: "application/json"
11+
}
12+
});
13+
const repoData = await repo.json();
14+
const stars = repoData.stargazers_count;
15+
---
16+
17+
<a id="cta-secondary" href="https://github.com/cameronapak/freedom-stack" class="max-sm:w-full btn btn-outline btn-sm">
18+
GitHub
19+
<div class="badge flex items-center gap-1">
20+
<Icon pack="lucide" name="star" class="w-4 h-4" />
21+
<span>{stars}</span>
22+
</div>
23+
</a>

Diff for: src/pages/api/htmx-partials/rick-roll.astro

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export const partial = true;
55

66
<iframe
77
src="https://www.youtube.com/embed/dQw4w9WgXcQ"
8-
frameborder="0"
98
class="aspect-video max-w-sm w-full rounded-lg shadow-lg"
109
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
1110
allowfullscreen

Diff for: src/pages/dashboard/index.astro

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
---
2-
import { actions } from "astro:actions";
32
import { Posts, db, desc, eq } from "astro:db";
43
import Icon from "astro-iconify";
54
import Layout from "@/layouts/Layout.astro";

Diff for: src/pages/dashboard/posts/edit/[slug].astro

+6-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ let post;
2222
// Fetch the post
2323
post = await db.select().from(Posts).where(eq(Posts.slug, slug)).get();
2424
25-
const result = await Astro.getActionResult(actions.posts.update);
25+
const result = Astro.getActionResult(actions.posts.update);
2626
if (result?.data?.success) {
2727
post = result.data.post;
2828
return Astro.redirect(`/posts/${post.slug}`);
@@ -64,6 +64,7 @@ if (!post) {
6464
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
6565
id="title"
6666
name="title"
67+
required
6768
value={post.title || ""}
6869
placeholder="Enter the post title"
6970
/>
@@ -81,6 +82,7 @@ if (!post) {
8182
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
8283
id="pubDate"
8384
name="pubDate"
85+
required
8486
placeholder="Select the publication date"
8587
type="date"
8688
/>
@@ -96,7 +98,8 @@ if (!post) {
9698
id="description"
9799
name="description"
98100
placeholder="Enter a brief description of the post"
99-
rows="3">{post.description || ""}</textarea
101+
rows="3"
102+
required>{post.description || ""}</textarea
100103
>
101104
</div>
102105
<div class="grid grid-cols-2 gap-6">
@@ -124,6 +127,7 @@ if (!post) {
124127
type="text"
125128
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
126129
id="slug"
130+
required
127131
name="slug"
128132
placeholder="blog-post-slug"
129133
pattern="[a-z0-9\\-]+"

Diff for: src/pages/dashboard/posts/new.astro

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ if (result?.data?.success) {
4848
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
4949
id="title"
5050
name="title"
51+
required
5152
placeholder="Enter the post title"
5253
/>
5354
</div>
@@ -78,6 +79,7 @@ if (result?.data?.success) {
7879
class="flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
7980
id="description"
8081
name="description"
82+
required
8183
placeholder="Enter a brief description of the post"
8284
rows="3"></textarea>
8385
</div>
@@ -107,6 +109,7 @@ if (result?.data?.success) {
107109
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
108110
id="slug"
109111
name="slug"
112+
required
110113
placeholder="blog-post-slug"
111114
pattern="[a-z0-9\\-]+"
112115
x-data="{ slug: '' }"

0 commit comments

Comments
 (0)