create-blitzpack 0.1.0 → 0.1.2

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.
Files changed (259) hide show
  1. package/dist/index.js +92 -94
  2. package/package.json +5 -6
  3. package/template/.dockerignore +0 -59
  4. package/template/.github/workflows/ci.yml +0 -157
  5. package/template/.husky/pre-commit +0 -1
  6. package/template/.husky/pre-push +0 -1
  7. package/template/.lintstagedrc.cjs +0 -4
  8. package/template/.nvmrc +0 -1
  9. package/template/.prettierrc +0 -9
  10. package/template/.vscode/settings.json +0 -13
  11. package/template/CLAUDE.md +0 -175
  12. package/template/CONTRIBUTING.md +0 -32
  13. package/template/Dockerfile +0 -90
  14. package/template/GETTING_STARTED.md +0 -35
  15. package/template/LICENSE +0 -21
  16. package/template/README.md +0 -116
  17. package/template/apps/api/.dockerignore +0 -51
  18. package/template/apps/api/.env.local.example +0 -62
  19. package/template/apps/api/emails/account-deleted-email.tsx +0 -69
  20. package/template/apps/api/emails/components/email-layout.tsx +0 -154
  21. package/template/apps/api/emails/config.ts +0 -22
  22. package/template/apps/api/emails/password-changed-email.tsx +0 -88
  23. package/template/apps/api/emails/password-reset-email.tsx +0 -86
  24. package/template/apps/api/emails/verification-email.tsx +0 -85
  25. package/template/apps/api/emails/welcome-email.tsx +0 -70
  26. package/template/apps/api/package.json +0 -84
  27. package/template/apps/api/prisma/migrations/20251012111439_init/migration.sql +0 -13
  28. package/template/apps/api/prisma/migrations/20251018162629_add_better_auth_fields/migration.sql +0 -67
  29. package/template/apps/api/prisma/migrations/20251019142208_add_user_role_enum/migration.sql +0 -5
  30. package/template/apps/api/prisma/migrations/20251019182151_user_auth/migration.sql +0 -7
  31. package/template/apps/api/prisma/migrations/20251019211416_faster_session_lookup/migration.sql +0 -2
  32. package/template/apps/api/prisma/migrations/20251119124337_add_upload_model/migration.sql +0 -26
  33. package/template/apps/api/prisma/migrations/20251120071241_add_scope_to_account/migration.sql +0 -2
  34. package/template/apps/api/prisma/migrations/20251120072608_add_oauth_token_expiration_fields/migration.sql +0 -10
  35. package/template/apps/api/prisma/migrations/20251120144705_add_audit_logs/migration.sql +0 -29
  36. package/template/apps/api/prisma/migrations/20251127123614_remove_impersonated_by/migration.sql +0 -8
  37. package/template/apps/api/prisma/migrations/20251127125630_remove_audit_logs/migration.sql +0 -11
  38. package/template/apps/api/prisma/migrations/migration_lock.toml +0 -3
  39. package/template/apps/api/prisma/schema.prisma +0 -116
  40. package/template/apps/api/prisma/seed.ts +0 -159
  41. package/template/apps/api/prisma.config.ts +0 -14
  42. package/template/apps/api/src/app.ts +0 -377
  43. package/template/apps/api/src/common/logger.service.ts +0 -227
  44. package/template/apps/api/src/config/env.ts +0 -60
  45. package/template/apps/api/src/config/rate-limit.ts +0 -29
  46. package/template/apps/api/src/hooks/auth.ts +0 -122
  47. package/template/apps/api/src/plugins/auth.ts +0 -198
  48. package/template/apps/api/src/plugins/database.ts +0 -45
  49. package/template/apps/api/src/plugins/logger.ts +0 -33
  50. package/template/apps/api/src/plugins/multipart.ts +0 -16
  51. package/template/apps/api/src/plugins/scalar.ts +0 -20
  52. package/template/apps/api/src/plugins/schedule.ts +0 -52
  53. package/template/apps/api/src/plugins/services.ts +0 -66
  54. package/template/apps/api/src/plugins/swagger.ts +0 -56
  55. package/template/apps/api/src/routes/accounts.ts +0 -91
  56. package/template/apps/api/src/routes/admin-sessions.ts +0 -92
  57. package/template/apps/api/src/routes/metrics.ts +0 -71
  58. package/template/apps/api/src/routes/password.ts +0 -46
  59. package/template/apps/api/src/routes/sessions.ts +0 -53
  60. package/template/apps/api/src/routes/stats.ts +0 -38
  61. package/template/apps/api/src/routes/uploads-serve.ts +0 -27
  62. package/template/apps/api/src/routes/uploads.ts +0 -154
  63. package/template/apps/api/src/routes/users.ts +0 -114
  64. package/template/apps/api/src/routes/verification.ts +0 -90
  65. package/template/apps/api/src/server.ts +0 -34
  66. package/template/apps/api/src/services/accounts.service.ts +0 -125
  67. package/template/apps/api/src/services/authorization.service.ts +0 -162
  68. package/template/apps/api/src/services/email.service.ts +0 -170
  69. package/template/apps/api/src/services/file-storage.service.ts +0 -267
  70. package/template/apps/api/src/services/metrics.service.ts +0 -175
  71. package/template/apps/api/src/services/password.service.ts +0 -56
  72. package/template/apps/api/src/services/sessions.service.spec.ts +0 -134
  73. package/template/apps/api/src/services/sessions.service.ts +0 -276
  74. package/template/apps/api/src/services/stats.service.ts +0 -273
  75. package/template/apps/api/src/services/uploads.service.ts +0 -163
  76. package/template/apps/api/src/services/users.service.spec.ts +0 -249
  77. package/template/apps/api/src/services/users.service.ts +0 -198
  78. package/template/apps/api/src/utils/file-validation.ts +0 -108
  79. package/template/apps/api/start.sh +0 -33
  80. package/template/apps/api/test/helpers/fastify-app.ts +0 -24
  81. package/template/apps/api/test/helpers/mock-authorization.ts +0 -16
  82. package/template/apps/api/test/helpers/mock-logger.ts +0 -28
  83. package/template/apps/api/test/helpers/mock-prisma.ts +0 -30
  84. package/template/apps/api/test/helpers/test-db.ts +0 -125
  85. package/template/apps/api/test/integration/auth-flow.integration.spec.ts +0 -449
  86. package/template/apps/api/test/integration/password.integration.spec.ts +0 -427
  87. package/template/apps/api/test/integration/rate-limit.integration.spec.ts +0 -51
  88. package/template/apps/api/test/integration/sessions.integration.spec.ts +0 -445
  89. package/template/apps/api/test/integration/users.integration.spec.ts +0 -211
  90. package/template/apps/api/test/setup.ts +0 -31
  91. package/template/apps/api/tsconfig.json +0 -26
  92. package/template/apps/api/vitest.config.ts +0 -35
  93. package/template/apps/web/.env.local.example +0 -11
  94. package/template/apps/web/components.json +0 -24
  95. package/template/apps/web/next.config.ts +0 -22
  96. package/template/apps/web/package.json +0 -56
  97. package/template/apps/web/postcss.config.js +0 -5
  98. package/template/apps/web/public/apple-icon.png +0 -0
  99. package/template/apps/web/public/icon.png +0 -0
  100. package/template/apps/web/public/robots.txt +0 -3
  101. package/template/apps/web/src/app/(admin)/admin/layout.tsx +0 -222
  102. package/template/apps/web/src/app/(admin)/admin/page.tsx +0 -157
  103. package/template/apps/web/src/app/(admin)/admin/sessions/page.tsx +0 -18
  104. package/template/apps/web/src/app/(admin)/admin/users/page.tsx +0 -20
  105. package/template/apps/web/src/app/(auth)/forgot-password/page.tsx +0 -177
  106. package/template/apps/web/src/app/(auth)/login/page.tsx +0 -159
  107. package/template/apps/web/src/app/(auth)/reset-password/page.tsx +0 -245
  108. package/template/apps/web/src/app/(auth)/signup/page.tsx +0 -153
  109. package/template/apps/web/src/app/dashboard/change-password/page.tsx +0 -255
  110. package/template/apps/web/src/app/dashboard/page.tsx +0 -296
  111. package/template/apps/web/src/app/error.tsx +0 -32
  112. package/template/apps/web/src/app/examples/file-upload/page.tsx +0 -200
  113. package/template/apps/web/src/app/favicon.ico +0 -0
  114. package/template/apps/web/src/app/global-error.tsx +0 -96
  115. package/template/apps/web/src/app/globals.css +0 -22
  116. package/template/apps/web/src/app/icon.png +0 -0
  117. package/template/apps/web/src/app/layout.tsx +0 -34
  118. package/template/apps/web/src/app/not-found.tsx +0 -28
  119. package/template/apps/web/src/app/page.tsx +0 -192
  120. package/template/apps/web/src/components/admin/activity-feed.tsx +0 -101
  121. package/template/apps/web/src/components/admin/charts/auth-breakdown-chart.tsx +0 -114
  122. package/template/apps/web/src/components/admin/charts/chart-tooltip.tsx +0 -124
  123. package/template/apps/web/src/components/admin/charts/realtime-metrics-chart.tsx +0 -511
  124. package/template/apps/web/src/components/admin/charts/role-distribution-chart.tsx +0 -102
  125. package/template/apps/web/src/components/admin/charts/session-activity-chart.tsx +0 -90
  126. package/template/apps/web/src/components/admin/charts/user-growth-chart.tsx +0 -108
  127. package/template/apps/web/src/components/admin/health-indicator.tsx +0 -175
  128. package/template/apps/web/src/components/admin/refresh-control.tsx +0 -90
  129. package/template/apps/web/src/components/admin/session-revoke-all-dialog.tsx +0 -79
  130. package/template/apps/web/src/components/admin/session-revoke-dialog.tsx +0 -74
  131. package/template/apps/web/src/components/admin/sessions-management-table.tsx +0 -372
  132. package/template/apps/web/src/components/admin/stat-card.tsx +0 -137
  133. package/template/apps/web/src/components/admin/user-create-dialog.tsx +0 -152
  134. package/template/apps/web/src/components/admin/user-delete-dialog.tsx +0 -73
  135. package/template/apps/web/src/components/admin/user-edit-dialog.tsx +0 -170
  136. package/template/apps/web/src/components/admin/users-management-table.tsx +0 -285
  137. package/template/apps/web/src/components/auth/email-verification-banner.tsx +0 -85
  138. package/template/apps/web/src/components/auth/github-button.tsx +0 -40
  139. package/template/apps/web/src/components/auth/google-button.tsx +0 -54
  140. package/template/apps/web/src/components/auth/protected-route.tsx +0 -66
  141. package/template/apps/web/src/components/auth/redirect-if-authenticated.tsx +0 -31
  142. package/template/apps/web/src/components/auth/with-auth.tsx +0 -30
  143. package/template/apps/web/src/components/error/error-card.tsx +0 -47
  144. package/template/apps/web/src/components/error/forbidden.tsx +0 -25
  145. package/template/apps/web/src/components/landing/command-block.tsx +0 -64
  146. package/template/apps/web/src/components/landing/feature-card.tsx +0 -60
  147. package/template/apps/web/src/components/landing/included-feature-card.tsx +0 -63
  148. package/template/apps/web/src/components/landing/logo.tsx +0 -41
  149. package/template/apps/web/src/components/landing/tech-badge.tsx +0 -11
  150. package/template/apps/web/src/components/layout/auth-nav.tsx +0 -58
  151. package/template/apps/web/src/components/layout/footer.tsx +0 -3
  152. package/template/apps/web/src/config/landing-data.ts +0 -152
  153. package/template/apps/web/src/config/site.ts +0 -5
  154. package/template/apps/web/src/hooks/api/__tests__/use-users.test.tsx +0 -181
  155. package/template/apps/web/src/hooks/api/use-admin-sessions.ts +0 -75
  156. package/template/apps/web/src/hooks/api/use-admin-stats.ts +0 -33
  157. package/template/apps/web/src/hooks/api/use-sessions.ts +0 -52
  158. package/template/apps/web/src/hooks/api/use-uploads.ts +0 -156
  159. package/template/apps/web/src/hooks/api/use-users.ts +0 -149
  160. package/template/apps/web/src/hooks/use-mobile.ts +0 -21
  161. package/template/apps/web/src/hooks/use-realtime-metrics.ts +0 -120
  162. package/template/apps/web/src/lib/__tests__/utils.test.ts +0 -29
  163. package/template/apps/web/src/lib/api.ts +0 -151
  164. package/template/apps/web/src/lib/auth.ts +0 -13
  165. package/template/apps/web/src/lib/env.ts +0 -52
  166. package/template/apps/web/src/lib/form-utils.ts +0 -11
  167. package/template/apps/web/src/lib/utils.ts +0 -1
  168. package/template/apps/web/src/providers.tsx +0 -34
  169. package/template/apps/web/src/store/atoms.ts +0 -15
  170. package/template/apps/web/src/test/helpers/test-utils.tsx +0 -44
  171. package/template/apps/web/src/test/setup.ts +0 -8
  172. package/template/apps/web/tailwind.config.ts +0 -5
  173. package/template/apps/web/tsconfig.json +0 -26
  174. package/template/apps/web/vitest.config.ts +0 -32
  175. package/template/assets/logo-512.png +0 -0
  176. package/template/assets/logo.svg +0 -4
  177. package/template/docker-compose.prod.yml +0 -66
  178. package/template/docker-compose.yml +0 -36
  179. package/template/eslint.config.ts +0 -119
  180. package/template/package.json +0 -77
  181. package/template/packages/tailwind-config/package.json +0 -9
  182. package/template/packages/tailwind-config/theme.css +0 -179
  183. package/template/packages/types/package.json +0 -29
  184. package/template/packages/types/src/__tests__/schemas.test.ts +0 -255
  185. package/template/packages/types/src/api-response.ts +0 -53
  186. package/template/packages/types/src/health-check.ts +0 -11
  187. package/template/packages/types/src/pagination.ts +0 -41
  188. package/template/packages/types/src/role.ts +0 -5
  189. package/template/packages/types/src/session.ts +0 -48
  190. package/template/packages/types/src/stats.ts +0 -113
  191. package/template/packages/types/src/upload.ts +0 -51
  192. package/template/packages/types/src/user.ts +0 -36
  193. package/template/packages/types/tsconfig.json +0 -5
  194. package/template/packages/types/vitest.config.ts +0 -21
  195. package/template/packages/ui/components.json +0 -21
  196. package/template/packages/ui/package.json +0 -108
  197. package/template/packages/ui/src/__tests__/button.test.tsx +0 -70
  198. package/template/packages/ui/src/alert-dialog.tsx +0 -141
  199. package/template/packages/ui/src/alert.tsx +0 -66
  200. package/template/packages/ui/src/animated-theme-toggler.tsx +0 -167
  201. package/template/packages/ui/src/avatar.tsx +0 -53
  202. package/template/packages/ui/src/badge.tsx +0 -36
  203. package/template/packages/ui/src/button.tsx +0 -84
  204. package/template/packages/ui/src/card.tsx +0 -92
  205. package/template/packages/ui/src/checkbox.tsx +0 -32
  206. package/template/packages/ui/src/data-table/data-table-column-header.tsx +0 -68
  207. package/template/packages/ui/src/data-table/data-table-pagination.tsx +0 -99
  208. package/template/packages/ui/src/data-table/data-table-toolbar.tsx +0 -55
  209. package/template/packages/ui/src/data-table/data-table-view-options.tsx +0 -63
  210. package/template/packages/ui/src/data-table/data-table.tsx +0 -167
  211. package/template/packages/ui/src/dialog.tsx +0 -143
  212. package/template/packages/ui/src/dropdown-menu.tsx +0 -257
  213. package/template/packages/ui/src/empty-state.tsx +0 -52
  214. package/template/packages/ui/src/file-upload-input.tsx +0 -202
  215. package/template/packages/ui/src/form.tsx +0 -168
  216. package/template/packages/ui/src/hooks/use-mobile.ts +0 -19
  217. package/template/packages/ui/src/icons/brand-icons.tsx +0 -16
  218. package/template/packages/ui/src/input.tsx +0 -21
  219. package/template/packages/ui/src/label.tsx +0 -24
  220. package/template/packages/ui/src/lib/utils.ts +0 -6
  221. package/template/packages/ui/src/password-input.tsx +0 -102
  222. package/template/packages/ui/src/popover.tsx +0 -48
  223. package/template/packages/ui/src/radio-group.tsx +0 -45
  224. package/template/packages/ui/src/scroll-area.tsx +0 -58
  225. package/template/packages/ui/src/select.tsx +0 -187
  226. package/template/packages/ui/src/separator.tsx +0 -28
  227. package/template/packages/ui/src/sheet.tsx +0 -139
  228. package/template/packages/ui/src/sidebar.tsx +0 -726
  229. package/template/packages/ui/src/skeleton-variants.tsx +0 -87
  230. package/template/packages/ui/src/skeleton.tsx +0 -13
  231. package/template/packages/ui/src/slider.tsx +0 -63
  232. package/template/packages/ui/src/sonner.tsx +0 -25
  233. package/template/packages/ui/src/spinner.tsx +0 -16
  234. package/template/packages/ui/src/switch.tsx +0 -31
  235. package/template/packages/ui/src/table.tsx +0 -116
  236. package/template/packages/ui/src/tabs.tsx +0 -66
  237. package/template/packages/ui/src/textarea.tsx +0 -18
  238. package/template/packages/ui/src/tooltip.tsx +0 -61
  239. package/template/packages/ui/src/user-avatar.tsx +0 -97
  240. package/template/packages/ui/test-config.js +0 -3
  241. package/template/packages/ui/tsconfig.json +0 -12
  242. package/template/packages/ui/turbo.json +0 -18
  243. package/template/packages/ui/vitest.config.ts +0 -17
  244. package/template/packages/ui/vitest.setup.ts +0 -1
  245. package/template/packages/utils/package.json +0 -23
  246. package/template/packages/utils/src/__tests__/utils.test.ts +0 -223
  247. package/template/packages/utils/src/array.ts +0 -18
  248. package/template/packages/utils/src/async.ts +0 -3
  249. package/template/packages/utils/src/date.ts +0 -77
  250. package/template/packages/utils/src/errors.ts +0 -73
  251. package/template/packages/utils/src/number.ts +0 -11
  252. package/template/packages/utils/src/string.ts +0 -13
  253. package/template/packages/utils/tsconfig.json +0 -5
  254. package/template/packages/utils/vitest.config.ts +0 -21
  255. package/template/pnpm-workspace.yaml +0 -4
  256. package/template/tsconfig.base.json +0 -32
  257. package/template/turbo.json +0 -133
  258. package/template/vitest.shared.ts +0 -26
  259. package/template/vitest.workspace.ts +0 -9
package/dist/index.js CHANGED
@@ -2,14 +2,17 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
+ import { readFileSync } from "fs";
6
+ import { dirname, join } from "path";
7
+ import { fileURLToPath } from "url";
5
8
 
6
9
  // src/commands/create.ts
7
10
  import chalk2 from "chalk";
8
11
  import { spawn } from "child_process";
9
12
  import fs3 from "fs-extra";
10
13
  import ora from "ora";
11
- import path3 from "path";
12
- import { fileURLToPath } from "url";
14
+ import path4 from "path";
15
+ import prompts2 from "prompts";
13
16
 
14
17
  // src/git.ts
15
18
  import { execSync } from "child_process";
@@ -39,28 +42,6 @@ function initGit(targetDir) {
39
42
  import prompts from "prompts";
40
43
 
41
44
  // src/constants.ts
42
- var TEMPLATE_EXCLUDES = [
43
- "node_modules",
44
- ".next",
45
- ".turbo",
46
- "dist",
47
- "build",
48
- "coverage",
49
- ".git",
50
- "pnpm-lock.yaml",
51
- "*.tsbuildinfo",
52
- "tsconfig.tsbuildinfo",
53
- ".env.local",
54
- ".env.*.local",
55
- ".DS_Store",
56
- ".temp",
57
- ".claude",
58
- ".cursor",
59
- "create-blitzpack",
60
- "apps/api/src/generated",
61
- "apps/api/public/uploads",
62
- "scripts/setup.js"
63
- ];
64
45
  var REPLACEABLE_FILES = [
65
46
  "package.json",
66
47
  "apps/web/src/config/site.ts",
@@ -72,11 +53,18 @@ var DEFAULT_DESCRIPTION = "A full-stack TypeScript monorepo built with Blitzpack
72
53
 
73
54
  // src/utils.ts
74
55
  import chalk from "chalk";
56
+ import path from "path";
75
57
  import validatePackageName from "validate-npm-package-name";
58
+ function getCurrentDirName() {
59
+ return path.basename(process.cwd());
60
+ }
76
61
  function toSlug(name) {
77
62
  return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
78
63
  }
79
64
  function validateProjectName(name) {
65
+ if (name === ".") {
66
+ return { valid: true };
67
+ }
80
68
  const result = validatePackageName(name);
81
69
  if (result.validForNewPackages) {
82
70
  return { valid: true };
@@ -96,19 +84,25 @@ function printSuccess(projectName, targetDir) {
96
84
  console.log();
97
85
  console.log(chalk.bold(" Next steps:"));
98
86
  console.log();
99
- console.log(chalk.cyan(" 1."), `cd ${targetDir}`);
87
+ let stepNumber = 1;
88
+ if (targetDir !== ".") {
89
+ console.log(chalk.cyan(` ${stepNumber}.`), `cd ${targetDir}`);
90
+ stepNumber++;
91
+ }
100
92
  console.log(
101
- chalk.cyan(" 2."),
93
+ chalk.cyan(` ${stepNumber}.`),
102
94
  "docker compose up -d",
103
95
  chalk.dim(" # Start PostgreSQL")
104
96
  );
97
+ stepNumber++;
105
98
  console.log(
106
- chalk.cyan(" 3."),
99
+ chalk.cyan(` ${stepNumber}.`),
107
100
  "pnpm db:migrate",
108
101
  chalk.dim(" # Run database migrations")
109
102
  );
103
+ stepNumber++;
110
104
  console.log(
111
- chalk.cyan(" 4."),
105
+ chalk.cyan(` ${stepNumber}.`),
112
106
  "pnpm dev",
113
107
  chalk.dim(" # Start dev servers")
114
108
  );
@@ -167,63 +161,47 @@ async function getProjectOptions(providedName, flags = {}) {
167
161
  console.log(`Invalid project name: ${validation.problems?.[0]}`);
168
162
  return null;
169
163
  }
164
+ const useCurrentDir = projectName === ".";
165
+ const actualProjectName = useCurrentDir ? getCurrentDirName() : projectName;
170
166
  return {
171
- projectName,
172
- projectSlug: toSlug(projectName),
167
+ projectName: actualProjectName,
168
+ projectSlug: toSlug(actualProjectName),
173
169
  projectDescription: response.projectDescription || DEFAULT_DESCRIPTION,
174
170
  skipGit: flags.skipGit || false,
175
- skipInstall: flags.skipInstall || false
171
+ skipInstall: flags.skipInstall || false,
172
+ useCurrentDir
176
173
  };
177
174
  }
178
175
 
179
176
  // src/template.ts
180
177
  import fs from "fs-extra";
181
- import path from "path";
182
- function shouldExclude(relativePath) {
183
- const normalizedPath = relativePath.replace(/\\/g, "/");
184
- for (const pattern of TEMPLATE_EXCLUDES) {
185
- if (pattern.startsWith("*")) {
186
- const ext = pattern.slice(1);
187
- if (normalizedPath.endsWith(ext)) return true;
188
- } else if (normalizedPath === pattern || normalizedPath.startsWith(pattern + "/")) {
189
- return true;
190
- } else {
191
- const parts = normalizedPath.split("/");
192
- if (parts.includes(pattern)) return true;
193
- }
194
- }
195
- return false;
196
- }
197
- async function copyDir(src, dest, baseDir) {
198
- await fs.ensureDir(dest);
199
- const entries = await fs.readdir(src, { withFileTypes: true });
200
- for (const entry of entries) {
201
- const srcPath = path.join(src, entry.name);
202
- const destPath = path.join(dest, entry.name);
203
- const relativePath = path.relative(baseDir, srcPath);
204
- if (shouldExclude(relativePath)) {
205
- continue;
206
- }
207
- if (entry.isDirectory()) {
208
- await copyDir(srcPath, destPath, baseDir);
209
- } else {
210
- await fs.copy(srcPath, destPath);
178
+ import { downloadTemplate } from "giget";
179
+ import path2 from "path";
180
+ var GITHUB_REPO = "github:CarboxyDev/blitzpack";
181
+ var POST_DOWNLOAD_EXCLUDES = [
182
+ "create-blitzpack",
183
+ "scripts/setup.js",
184
+ ".github"
185
+ ];
186
+ async function cleanupExcludes(targetDir) {
187
+ for (const exclude of POST_DOWNLOAD_EXCLUDES) {
188
+ const fullPath = path2.join(targetDir, exclude);
189
+ if (await fs.pathExists(fullPath)) {
190
+ await fs.remove(fullPath);
211
191
  }
212
192
  }
213
193
  }
214
- async function copyTemplate(templateDir, targetDir) {
215
- if (await fs.pathExists(targetDir)) {
216
- const files = await fs.readdir(targetDir);
217
- if (files.length > 0) {
218
- throw new Error(`Directory ${targetDir} is not empty`);
219
- }
220
- }
221
- await copyDir(templateDir, targetDir, templateDir);
194
+ async function downloadAndPrepareTemplate(targetDir) {
195
+ await downloadTemplate(GITHUB_REPO, {
196
+ dir: targetDir,
197
+ force: true
198
+ });
199
+ await cleanupExcludes(targetDir);
222
200
  }
223
201
 
224
202
  // src/transform.ts
225
203
  import fs2 from "fs-extra";
226
- import path2 from "path";
204
+ import path3 from "path";
227
205
  function transformPackageJson(content, vars, filePath) {
228
206
  const pkg = JSON.parse(content);
229
207
  if (filePath === "package.json") {
@@ -237,10 +215,16 @@ function transformPackageJson(content, vars, filePath) {
237
215
  return JSON.stringify(pkg, null, 2) + "\n";
238
216
  }
239
217
  function transformSiteConfig(content, vars) {
240
- return content.replace(/name: ['"].*['"]/, `name: '${vars.projectName}'`).replace(/description: ['"].*['"]/, `description: '${vars.projectDescription}'`).replace(/github: ['"].*['"]/, `github: ''`);
218
+ return content.replace(/name: ['"].*['"]/, `name: '${vars.projectName}'`).replace(
219
+ /description: ['"].*['"]/,
220
+ `description: '${vars.projectDescription}'`
221
+ ).replace(/github: ['"].*['"]/, `github: ''`);
241
222
  }
242
223
  function transformLayout(content, vars) {
243
- return content.replace(/title: ['"].*['"]/, `title: '${vars.projectName}'`).replace(/description: ['"].*['"]/, `description: '${vars.projectDescription}'`);
224
+ return content.replace(/title: ['"].*['"]/, `title: '${vars.projectName}'`).replace(
225
+ /description: ['"].*['"]/,
226
+ `description: '${vars.projectDescription}'`
227
+ );
244
228
  }
245
229
  function transformSwagger(content, vars) {
246
230
  return content.replace(/title: ['"].*['"]/, `title: '${vars.projectName} API'`).replace(
@@ -295,7 +279,7 @@ Built with [Blitzpack](https://github.com/CarboxyDev/blitzpack)
295
279
  }
296
280
  async function transformFiles(targetDir, vars) {
297
281
  for (const relativePath of REPLACEABLE_FILES) {
298
- const filePath = path2.join(targetDir, relativePath);
282
+ const filePath = path3.join(targetDir, relativePath);
299
283
  if (!await fs2.pathExists(filePath)) {
300
284
  continue;
301
285
  }
@@ -319,15 +303,14 @@ async function transformFiles(targetDir, vars) {
319
303
  }
320
304
 
321
305
  // src/commands/create.ts
322
- var __dirname = path3.dirname(fileURLToPath(import.meta.url));
323
306
  var ENV_FILES = [
324
307
  { from: "apps/web/.env.local.example", to: "apps/web/.env.local" },
325
308
  { from: "apps/api/.env.local.example", to: "apps/api/.env.local" }
326
309
  ];
327
310
  async function copyEnvFiles(targetDir) {
328
311
  for (const { from, to } of ENV_FILES) {
329
- const source = path3.join(targetDir, from);
330
- const dest = path3.join(targetDir, to);
312
+ const source = path4.join(targetDir, from);
313
+ const dest = path4.join(targetDir, to);
331
314
  if (await fs3.pathExists(source)) {
332
315
  await fs3.copy(source, dest);
333
316
  }
@@ -358,7 +341,7 @@ function printDryRun(options) {
358
341
  console.log();
359
342
  console.log(chalk2.bold(" Would run:"));
360
343
  console.log();
361
- console.log(` ${chalk2.dim("\u2022")} Copy template files`);
344
+ console.log(` ${chalk2.dim("\u2022")} Download template from GitHub`);
362
345
  console.log(` ${chalk2.dim("\u2022")} Transform package.json files`);
363
346
  console.log(` ${chalk2.dim("\u2022")} Create .env.local files`);
364
347
  if (!options.skipGit) {
@@ -375,7 +358,7 @@ async function create(projectName, flags) {
375
358
  if (!options) {
376
359
  return;
377
360
  }
378
- const targetDir = path3.resolve(process.cwd(), options.projectName);
361
+ const targetDir = options.useCurrentDir ? process.cwd() : path4.resolve(process.cwd(), options.projectName);
379
362
  if (flags.dryRun) {
380
363
  printDryRun({
381
364
  projectName: options.projectName,
@@ -390,22 +373,27 @@ async function create(projectName, flags) {
390
373
  if (await fs3.pathExists(targetDir)) {
391
374
  const files = await fs3.readdir(targetDir);
392
375
  if (files.length > 0) {
393
- printError(`Directory "${options.projectName}" is not empty`);
394
- return;
376
+ if (options.useCurrentDir) {
377
+ const { confirm } = await prompts2({
378
+ type: "confirm",
379
+ name: "confirm",
380
+ message: `Current directory is not empty. Continue?`,
381
+ initial: false
382
+ });
383
+ if (!confirm) {
384
+ return;
385
+ }
386
+ } else {
387
+ printError(`Directory "${options.projectName}" is not empty`);
388
+ return;
389
+ }
395
390
  }
396
391
  }
397
- const templateDir = path3.resolve(__dirname, "..", "template");
398
- if (!await fs3.pathExists(templateDir)) {
399
- printError(
400
- "Template directory not found. This is a bug in create-blitzpack."
401
- );
402
- return;
403
- }
404
392
  const spinner = ora();
405
393
  try {
406
- spinner.start("Creating project structure...");
407
- await copyTemplate(templateDir, targetDir);
408
- spinner.succeed("Created project structure");
394
+ spinner.start("Downloading template from GitHub...");
395
+ await downloadAndPrepareTemplate(targetDir);
396
+ spinner.succeed("Downloaded template");
409
397
  spinner.start("Configuring project...");
410
398
  await transformFiles(targetDir, {
411
399
  projectName: options.projectName,
@@ -434,7 +422,10 @@ async function create(projectName, flags) {
434
422
  );
435
423
  }
436
424
  }
437
- printSuccess(options.projectName, options.projectName);
425
+ printSuccess(
426
+ options.projectName,
427
+ options.useCurrentDir ? "." : options.projectName
428
+ );
438
429
  } catch (error) {
439
430
  spinner.fail();
440
431
  printError(
@@ -445,8 +436,15 @@ async function create(projectName, flags) {
445
436
  }
446
437
 
447
438
  // src/index.ts
439
+ var __filename = fileURLToPath(import.meta.url);
440
+ var __dirname = dirname(__filename);
441
+ var packageJson = JSON.parse(
442
+ readFileSync(join(__dirname, "../package.json"), "utf-8")
443
+ );
448
444
  var program = new Command();
449
- program.name("create-blitzpack").description("Create a new Blitzpack project").version("0.1.0").argument("[project-name]", "Name of the project").option("--skip-git", "Skip git initialization").option("--skip-install", "Skip dependency installation").option("--dry-run", "Show what would be done without making changes").action(async (projectName, options) => {
450
- await create(projectName, options);
451
- });
445
+ program.name("create-blitzpack").description("Create a new Blitzpack project").version(packageJson.version).argument("[project-name]", "Name of the project").option("--skip-git", "Skip git initialization").option("--skip-install", "Skip dependency installation").option("--dry-run", "Show what would be done without making changes").action(
446
+ async (projectName, options) => {
447
+ await create(projectName, options);
448
+ }
449
+ );
452
450
  program.parse();
package/package.json CHANGED
@@ -1,26 +1,25 @@
1
1
  {
2
2
  "name": "create-blitzpack",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Create a new Blitzpack project - full-stack TypeScript monorepo with Next.js and Fastify",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "create-blitzpack": "./dist/index.js"
8
8
  },
9
9
  "files": [
10
- "dist",
11
- "template"
10
+ "dist"
12
11
  ],
13
12
  "scripts": {
14
13
  "dev": "tsup --watch",
15
- "build": "pnpm run build:template && tsup",
16
- "build:template": "node scripts/copy-template.js",
14
+ "build": "tsup",
17
15
  "typecheck": "tsc --noEmit",
18
- "clean": "rm -rf dist template"
16
+ "clean": "rm -rf dist"
19
17
  },
20
18
  "dependencies": {
21
19
  "chalk": "^5.4.1",
22
20
  "commander": "^13.1.0",
23
21
  "fs-extra": "^11.3.0",
22
+ "giget": "^2.0.0",
24
23
  "ora": "^8.2.0",
25
24
  "prompts": "^2.4.2",
26
25
  "validate-npm-package-name": "^6.0.0"
@@ -1,59 +0,0 @@
1
- # Dependencies
2
- node_modules
3
- npm-debug.log
4
- pnpm-debug.log
5
- yarn-error.log
6
-
7
- # Build outputs (but keep package dist/ folders for copying built packages)
8
- # We ignore these initially but packages/*/dist will be built during Docker build
9
- .next
10
- .turbo
11
- *.tsbuildinfo
12
- apps/*/dist
13
-
14
- # Testing
15
- coverage
16
- .vitest
17
-
18
- # Environment files (never include in image)
19
- .env
20
- .env.local
21
- .env.*.local
22
- .env.development
23
- .env.production
24
-
25
- # Git
26
- .git
27
- .gitignore
28
- .github
29
-
30
- # IDE
31
- .vscode
32
- .idea
33
- *.swp
34
- *.swo
35
- *~
36
-
37
- # OS
38
- .DS_Store
39
- Thumbs.db
40
-
41
- # Logs
42
- logs
43
- *.log
44
-
45
- # Documentation (not needed in production)
46
- README.md
47
- DEPLOYMENT.md
48
- CLAUDE.md
49
- *.md
50
-
51
- # Docker
52
- Dockerfile
53
- .dockerignore
54
- docker-compose.yml
55
-
56
- # Misc
57
- .husky
58
- scripts
59
- # Keep config/ for package builds
@@ -1,157 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- push:
5
- branches: [main, development]
6
- pull_request:
7
- branches: [main, development]
8
-
9
- # Cancel in-progress runs when a new commit is pushed
10
- concurrency:
11
- group: ${{ github.workflow }}-${{ github.ref }}
12
- cancel-in-progress: true
13
-
14
- jobs:
15
- # Fast checks that can run in parallel
16
- lint:
17
- runs-on: ubuntu-latest
18
- steps:
19
- - uses: actions/checkout@v4
20
-
21
- - name: Setup pnpm
22
- uses: pnpm/action-setup@v4
23
-
24
- - name: Setup Node.js
25
- uses: actions/setup-node@v4
26
- with:
27
- node-version: '20'
28
- cache: 'pnpm'
29
-
30
- - name: Install dependencies
31
- run: pnpm install --frozen-lockfile
32
-
33
- - name: Run lint
34
- run: pnpm run lint
35
-
36
- typecheck:
37
- runs-on: ubuntu-latest
38
- steps:
39
- - uses: actions/checkout@v4
40
-
41
- - name: Setup pnpm
42
- uses: pnpm/action-setup@v4
43
-
44
- - name: Setup Node.js
45
- uses: actions/setup-node@v4
46
- with:
47
- node-version: '20'
48
- cache: 'pnpm'
49
-
50
- - name: Install dependencies
51
- run: pnpm install --frozen-lockfile
52
-
53
- - name: Create .env for Prisma
54
- run: echo "DATABASE_URL=postgresql://user:pass@localhost:5432/db" > apps/api/.env
55
-
56
- - name: Generate Prisma Client
57
- run: pnpm --filter @repo/api db:generate
58
-
59
- - name: Run typecheck
60
- run: pnpm run typecheck --filter '!@repo/api' # FIXME: Temporary workaround because of prisma v7 issues
61
-
62
- # Tests and build run after lint/typecheck pass
63
- test:
64
- runs-on: ubuntu-latest
65
- needs: [lint, typecheck]
66
-
67
- # PostgreSQL service for integration tests
68
- services:
69
- postgres:
70
- image: postgres:17-alpine
71
- env:
72
- POSTGRES_USER: postgres
73
- POSTGRES_PASSWORD: postgres
74
- POSTGRES_DB: app_dev_test
75
- POSTGRES_HOST_AUTH_METHOD: trust
76
- options: >-
77
- --health-cmd "pg_isready -U postgres"
78
- --health-interval 10s
79
- --health-timeout 5s
80
- --health-retries 5
81
- ports:
82
- - 5432:5432
83
-
84
- env:
85
- NODE_ENV: test
86
- DATABASE_URL: postgresql://postgres:postgres@localhost:5432/app_dev
87
- API_URL: http://localhost:8080
88
- FRONTEND_URL: http://localhost:3000
89
- PORT: 8080
90
- LOG_LEVEL: minimal
91
- COOKIE_SECRET: test-cookie-secret-for-ci
92
- BETTER_AUTH_SECRET: test-secret-minimum-32-characters-long-for-ci
93
- BETTER_AUTH_URL: http://localhost:8080
94
-
95
- steps:
96
- - uses: actions/checkout@v4
97
-
98
- - name: Setup pnpm
99
- uses: pnpm/action-setup@v4
100
-
101
- - name: Setup Node.js
102
- uses: actions/setup-node@v4
103
- with:
104
- node-version: '20'
105
- cache: 'pnpm'
106
-
107
- - name: Install dependencies
108
- run: pnpm install --frozen-lockfile
109
-
110
- - name: Generate Prisma Client
111
- run: cd apps/api && npx prisma generate
112
-
113
- - name: Run tests
114
- run: pnpm run test
115
-
116
- build:
117
- runs-on: ubuntu-latest
118
- needs: [lint, typecheck]
119
- steps:
120
- - uses: actions/checkout@v4
121
-
122
- - name: Setup pnpm
123
- uses: pnpm/action-setup@v4
124
-
125
- - name: Setup Node.js
126
- uses: actions/setup-node@v4
127
- with:
128
- node-version: '20'
129
- cache: 'pnpm'
130
-
131
- - name: Install dependencies
132
- run: pnpm install --frozen-lockfile
133
-
134
- - name: Generate Prisma Client
135
- run: pnpm --filter @repo/api db:generate
136
-
137
- - name: Setup Turborepo cache
138
- uses: actions/cache@v4
139
- with:
140
- path: .turbo
141
- key: ${{ runner.os }}-turbo-${{ github.sha }}
142
- restore-keys: |
143
- ${{ runner.os }}-turbo-
144
-
145
- - name: Build
146
- run: pnpm run build
147
- env:
148
- NODE_ENV: production
149
- API_URL: 'http://localhost:8080'
150
- FRONTEND_URL: 'http://localhost:3000'
151
- DATABASE_URL: 'postgresql://user:pass@localhost:5432/db'
152
- PORT: '8080'
153
- LOG_LEVEL: 'minimal'
154
- COOKIE_SECRET: 'ci-test-secret-not-for-production'
155
- BETTER_AUTH_SECRET: 'ci-test-secret-not-for-production'
156
- BETTER_AUTH_URL: 'http://localhost:8080'
157
- NEXT_PUBLIC_API_URL: 'http://localhost:8080/api'
@@ -1 +0,0 @@
1
- pnpm lint-staged
@@ -1 +0,0 @@
1
- pnpm typecheck && pnpm test
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- '*.{ts,tsx,js,jsx}': ['eslint --fix', 'prettier --write'],
3
- '*.{json,md,yml,yaml}': ['prettier --write'],
4
- };
package/template/.nvmrc DELETED
@@ -1 +0,0 @@
1
- 20.0.0
@@ -1,9 +0,0 @@
1
- {
2
- "semi": true,
3
- "trailingComma": "es5",
4
- "singleQuote": true,
5
- "printWidth": 80,
6
- "tabWidth": 2,
7
- "useTabs": false,
8
- "plugins": ["prettier-plugin-tailwindcss"]
9
- }
@@ -1,13 +0,0 @@
1
- {
2
- "editor.formatOnSave": true,
3
- "editor.defaultFormatter": "esbenp.prettier-vscode",
4
- "editor.codeActionsOnSave": {
5
- "source.fixAll.eslint": "explicit"
6
- },
7
- "eslint.workingDirectories": [{ "mode": "auto" }],
8
- "typescript.tsdk": "node_modules/typescript/lib",
9
- "typescript.enablePromptUseWorkspaceTsdk": true,
10
- "typescript.preferences.includePackageJsonAutoImports": "on",
11
- "typescript.validate.enable": true,
12
- "prisma.pinToPrisma6": false
13
- }