create-githat-app 1.0.4 → 1.0.5

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/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ import gradient from "gradient-string";
11
11
  import chalk from "chalk";
12
12
 
13
13
  // src/constants.ts
14
- var VERSION = "1.0.4";
14
+ var VERSION = "1.0.5";
15
15
  var DEFAULT_API_URL = "https://api.githat.io";
16
16
  var DASHBOARD_URL = "https://githat.io/dashboard/apps";
17
17
  var BRAND_COLORS = ["#7c3aed", "#6366f1", "#8b5cf6"];
@@ -397,45 +397,22 @@ async function promptBackend() {
397
397
  }
398
398
 
399
399
  // src/prompts/githat.ts
400
- import { execSync } from "child_process";
401
400
  import * as p5 from "@clack/prompts";
402
- function openBrowser(url) {
403
- try {
404
- const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
405
- execSync(`${cmd} "${url}"`, { stdio: "ignore" });
406
- } catch {
407
- }
408
- }
409
401
  async function promptGitHat(existingKey) {
410
402
  let publishableKey = existingKey || "";
411
403
  if (!publishableKey) {
412
404
  const connectChoice = await p5.select({
413
405
  message: "Connect to GitHat",
414
406
  options: [
415
- { value: "browser", label: "Sign in with browser", hint: "opens githat.io \u2014 recommended" },
416
- { value: "paste", label: "I have a key", hint: "paste your pk_live_... key" },
417
- { value: "skip", label: "Skip for now", hint: "add key to .env later" }
407
+ { value: "skip", label: "Skip for now", hint: "auth works on localhost \u2014 add key later" },
408
+ { value: "paste", label: "I have a key", hint: "paste your pk_live_... key" }
418
409
  ]
419
410
  });
420
411
  if (p5.isCancel(connectChoice)) {
421
412
  p5.cancel("Setup cancelled.");
422
413
  process.exit(0);
423
414
  }
424
- if (connectChoice === "browser") {
425
- p5.log.step("Opening githat.io in your browser...");
426
- openBrowser("https://githat.io/sign-up");
427
- p5.log.info("Sign up (or sign in), then go to Dashboard \u2192 Apps to copy your key.");
428
- const pastedKey = await p5.text({
429
- message: "Paste your publishable key",
430
- placeholder: "pk_live_...",
431
- validate: validatePublishableKey
432
- });
433
- if (p5.isCancel(pastedKey)) {
434
- p5.cancel("Setup cancelled.");
435
- process.exit(0);
436
- }
437
- publishableKey = pastedKey || "";
438
- } else if (connectChoice === "paste") {
415
+ if (connectChoice === "paste") {
439
416
  const pastedKey = await p5.text({
440
417
  message: "Publishable key",
441
418
  placeholder: `pk_live_... (get one at ${DASHBOARD_URL})`,
@@ -446,9 +423,6 @@ async function promptGitHat(existingKey) {
446
423
  process.exit(0);
447
424
  }
448
425
  publishableKey = pastedKey || "";
449
- } else if (connectChoice === "skip") {
450
- p5.log.info("Auth works on localhost without a key (CORS bypass for development).");
451
- p5.log.info("Sign up at githat.io \u2014 a publishable key is auto-created for you.");
452
426
  }
453
427
  }
454
428
  const authFeatures = await p5.multiselect({
@@ -528,13 +502,15 @@ async function promptFinalize() {
528
502
  function toDisplayName(projectName) {
529
503
  return projectName.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
530
504
  }
531
- function getDefaults(projectName, publishableKey, typescript) {
505
+ function getDefaults(projectName, publishableKey, typescript, fullstack, backendFramework) {
532
506
  const displayName = toDisplayName(projectName);
507
+ const projectType = fullstack ? "fullstack" : "frontend";
533
508
  return {
534
509
  projectName,
535
510
  businessName: displayName,
536
511
  description: `${displayName} \u2014 Built with GitHat`,
537
- projectType: "frontend",
512
+ projectType,
513
+ backendFramework: fullstack ? backendFramework || "hono" : void 0,
538
514
  framework: "nextjs",
539
515
  typescript: typescript ?? true,
540
516
  packageManager: detectPackageManager(),
@@ -544,7 +520,7 @@ function getDefaults(projectName, publishableKey, typescript) {
544
520
  databaseChoice: "none",
545
521
  useTailwind: true,
546
522
  includeDashboard: true,
547
- includeGithatFolder: true,
523
+ includeGithatFolder: projectType === "frontend",
548
524
  initGit: true,
549
525
  installDeps: true
550
526
  };
@@ -552,7 +528,7 @@ function getDefaults(projectName, publishableKey, typescript) {
552
528
  async function runPrompts(args) {
553
529
  if (args.yes && args.initialName) {
554
530
  p8.log.info("Using defaults (--yes flag)");
555
- return getDefaults(args.initialName, args.publishableKey, args.typescript);
531
+ return getDefaults(args.initialName, args.publishableKey, args.typescript, args.fullstack, args.backendFramework);
556
532
  }
557
533
  p8.intro("Let's set up your GitHat app");
558
534
  sectionHeader("Project");
@@ -603,7 +579,7 @@ function answersToContext(answers) {
603
579
  // src/scaffold/index.ts
604
580
  import fs3 from "fs-extra";
605
581
  import path3 from "path";
606
- import { execSync as execSync3 } from "child_process";
582
+ import { execSync as execSync2 } from "child_process";
607
583
  import * as p9 from "@clack/prompts";
608
584
  import chalk2 from "chalk";
609
585
 
@@ -738,12 +714,12 @@ async function withSpinner(text4, fn, successText) {
738
714
  }
739
715
 
740
716
  // src/utils/git.ts
741
- import { execSync as execSync2 } from "child_process";
717
+ import { execSync } from "child_process";
742
718
  function initGit(cwd) {
743
719
  try {
744
- execSync2("git init", { cwd, stdio: "ignore" });
745
- execSync2("git add -A", { cwd, stdio: "ignore" });
746
- execSync2('git commit -m "Initial commit from create-githat-app"', {
720
+ execSync("git init", { cwd, stdio: "ignore" });
721
+ execSync("git add -A", { cwd, stdio: "ignore" });
722
+ execSync('git commit -m "Initial commit from create-githat-app"', {
747
723
  cwd,
748
724
  stdio: "ignore"
749
725
  });
@@ -800,7 +776,7 @@ async function scaffold(context, options) {
800
776
  `Installing dependencies with ${context.packageManager}...`,
801
777
  async () => {
802
778
  try {
803
- execSync3(installCmd, { cwd: root, stdio: "ignore", timeout: 12e4 });
779
+ execSync2(installCmd, { cwd: root, stdio: "ignore", timeout: 12e4 });
804
780
  } catch (err) {
805
781
  const msg = err.message || "";
806
782
  if (msg.includes("TIMEOUT")) {
@@ -823,7 +799,7 @@ async function scaffold(context, options) {
823
799
  if (!p9.isCancel(starPrompt) && starPrompt) {
824
800
  try {
825
801
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
826
- execSync3(`${cmd} "https://github.com/GitHat-IO/githat"`, { stdio: "ignore" });
802
+ execSync2(`${cmd} "https://github.com/GitHat-IO/githat"`, { stdio: "ignore" });
827
803
  } catch {
828
804
  p9.log.info("Visit https://github.com/GitHat-IO/githat to star us!");
829
805
  }
@@ -1436,7 +1412,7 @@ skillsCommand.action(() => {
1436
1412
  // src/cli.ts
1437
1413
  var program = new Command7();
1438
1414
  program.name("githat").description("GitHat CLI - Scaffold apps and manage skills").version(VERSION);
1439
- program.command("create [project-name]", { isDefault: true }).description("Scaffold a new GitHat app").option("--key <key>", "GitHat publishable key (pk_live_...)").option("--ts", "Use TypeScript (default)").option("--js", "Use JavaScript").option("-y, --yes", "Skip prompts and use defaults").action(async (projectName, opts) => {
1415
+ program.command("create [project-name]", { isDefault: true }).description("Scaffold a new GitHat app").option("--key <key>", "GitHat publishable key (pk_live_...)").option("--ts", "Use TypeScript (default)").option("--js", "Use JavaScript").option("--fullstack", "Create fullstack project (Turborepo)").option("--backend <framework>", "Backend framework (hono, express, fastify)").option("-y, --yes", "Skip prompts and use defaults").action(async (projectName, opts) => {
1440
1416
  try {
1441
1417
  displayBanner();
1442
1418
  const typescript = opts.js ? false : opts.ts ? true : void 0;
@@ -1448,7 +1424,9 @@ program.command("create [project-name]", { isDefault: true }).description("Scaff
1448
1424
  initialName: projectName,
1449
1425
  publishableKey: opts.key,
1450
1426
  typescript,
1451
- yes: opts.yes
1427
+ yes: opts.yes,
1428
+ fullstack: opts.fullstack,
1429
+ backendFramework: opts.backend
1452
1430
  });
1453
1431
  const context = answersToContext(answers);
1454
1432
  await scaffold(context, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-githat-app",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "GitHat CLI — scaffold apps and manage the skills marketplace",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,11 +1,39 @@
1
1
  {{#if includeForgotPassword}}
2
+ 'use client';
3
+
4
+ import { Suspense } from 'react';
5
+ import { useSearchParams } from 'next/navigation';
2
6
  import { ResetPasswordForm } from '@githat/nextjs';
3
7
 
4
- export default function ResetPasswordPage() {
8
+ function ResetPasswordContent() {
9
+ const searchParams = useSearchParams();
10
+ const token = searchParams.get('token');
11
+
12
+ if (!token) {
13
+ return (
14
+ <main {{#if useTailwind}}className="flex items-center justify-center min-h-screen bg-[#09090b]"{{else}}style=\{{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#09090b' }}{{/if}}>
15
+ <div {{#if useTailwind}}className="text-center"{{else}}style=\{{ textAlign: 'center' }}{{/if}}>
16
+ <h1 {{#if useTailwind}}className="text-xl font-semibold text-white mb-2"{{else}}style=\{{ fontSize: '1.25rem', fontWeight: 600, color: '#fafafa', marginBottom: '0.5rem' }}{{/if}}>Invalid reset link</h1>
17
+ <p {{#if useTailwind}}className="text-zinc-400"{{else}}style=\{{ color: '#a1a1aa' }}{{/if}}>
18
+ <a href="/forgot-password" {{#if useTailwind}}className="text-violet-500 hover:underline"{{else}}style=\{{ color: '#7c3aed' }}{{/if}}>Request a new one</a>
19
+ </p>
20
+ </div>
21
+ </main>
22
+ );
23
+ }
24
+
5
25
  return (
6
26
  <main {{#if useTailwind}}className="flex items-center justify-center min-h-screen bg-[#09090b]"{{else}}style=\{{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#09090b' }}{{/if}}>
7
- <ResetPasswordForm signInUrl="/sign-in" />
27
+ <ResetPasswordForm token={token} signInUrl="/sign-in" />
8
28
  </main>
9
29
  );
10
30
  }
31
+
32
+ export default function ResetPasswordPage() {
33
+ return (
34
+ <Suspense fallback={<div {{#if useTailwind}}className="flex items-center justify-center min-h-screen bg-[#09090b] text-zinc-400"{{else}}style=\{{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#09090b', color: '#a1a1aa' }}{{/if}}>Loading...</div>}>
35
+ <ResetPasswordContent />
36
+ </Suspense>
37
+ );
38
+ }
11
39
  {{/if}}
@@ -1,9 +1,15 @@
1
1
  {{#if includeDashboard}}
2
- import { withAuth } from '@githat/nextjs/server';
2
+ import { redirect } from 'next/navigation';
3
+ import { cookies } from 'next/headers';
4
+
5
+ export default async function DashboardLayout({ children }{{#if typescript}}: { children: React.ReactNode }{{/if}}) {
6
+ const cookieStore = await cookies();
7
+ const token = cookieStore.get('githat_access')?.value;
8
+
9
+ if (!token) {
10
+ redirect('/sign-in');
11
+ }
3
12
 
4
- async function DashboardLayout({ children }{{#if typescript}}: { children: React.ReactNode }{{/if}}) {
5
13
  return <>{children}</>;
6
14
  }
7
-
8
- export default withAuth(DashboardLayout);
9
15
  {{/if}}
@@ -1,9 +1,9 @@
1
1
  {{#if includeDashboard}}
2
2
  'use client';
3
- import { useGitHat, UserButton } from '@githat/nextjs';
3
+ import { useAuth, UserButton } from '@githat/nextjs';
4
4
 
5
5
  export default function DashboardPage() {
6
- const { user, org } = useGitHat();
6
+ const { user, org } = useAuth();
7
7
 
8
8
  return (
9
9
  <div {{#if useTailwind}}className="p-8"{{else}}style=\{{ padding: '2rem' }}{{/if}}>
@@ -11,5 +11,5 @@
11
11
  "devDependencies": {
12
12
  "turbo": "^2.3.0"
13
13
  },
14
- "packageManager": "{{packageManager}}@*"
14
+ "packageManager": "{{packageManager}}@10.9.2"
15
15
  }
@@ -1,13 +1,13 @@
1
1
  {{#if includeForgotPassword}}
2
2
  'use client';
3
3
 
4
- import { useState } from 'react';
4
+ import { Suspense, useState } from 'react';
5
5
  import { useSearchParams, useRouter } from 'next/navigation';
6
6
  {{#if includeGithatFolder}}
7
7
  import { authApi } from '../../../githat/api/auth{{#unless typescript}}.js{{/unless}}';
8
8
  {{/if}}
9
9
 
10
- export default function ResetPasswordPage() {
10
+ function ResetPasswordContent() {
11
11
  const searchParams = useSearchParams();
12
12
  const router = useRouter();
13
13
  const token = searchParams.get('token');
@@ -95,4 +95,12 @@ export default function ResetPasswordPage() {
95
95
  </main>
96
96
  );
97
97
  }
98
+
99
+ export default function ResetPasswordPage() {
100
+ return (
101
+ <Suspense fallback={<div {{#if useTailwind}}className="flex items-center justify-center min-h-screen bg-[#09090b] text-zinc-400"{{else}}style=\{{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#09090b', color: '#a1a1aa' }}{{/if}}>Loading...</div>}>
102
+ <ResetPasswordContent />
103
+ </Suspense>
104
+ );
105
+ }
98
106
  {{/if}}