r9stack 0.4.1
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/LICENSE +190 -0
- package/README.md +217 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +239 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/payload/assets/.gitkeep +0 -0
- package/dist/payload/assets/favicon.ico +0 -0
- package/dist/payload/assets/images/r9stack-logo-markonly-circle.png +0 -0
- package/dist/payload/assets/images/r9stack-logo-markonly-whitebg.png +0 -0
- package/dist/payload/assets/images/r9stack-logo-markonly.png +0 -0
- package/dist/payload/assets/images/r9stack-logo.png +0 -0
- package/dist/payload/assets/logo192.png +0 -0
- package/dist/payload/assets/logo512.png +0 -0
- package/dist/payload/assets/manifest.json +26 -0
- package/dist/payload/assets/robots.txt +3 -0
- package/dist/payload/templates/.gitkeep +0 -0
- package/dist/payload/templates/config/components.json +25 -0
- package/dist/payload/templates/config/env.example +14 -0
- package/dist/payload/templates/config/tsconfig.json +26 -0
- package/dist/payload/templates/config/vite.config.ts +23 -0
- package/dist/payload/templates/convex/auth.config.ts +7 -0
- package/dist/payload/templates/convex/messages.ts +28 -0
- package/dist/payload/templates/convex/schema.ts +24 -0
- package/dist/payload/templates/convex/tsconfig.json +21 -0
- package/dist/payload/templates/src/components/AppShell.tsx +21 -0
- package/dist/payload/templates/src/components/AuthProvider.tsx +50 -0
- package/dist/payload/templates/src/components/ConvexClientProvider.tsx +20 -0
- package/dist/payload/templates/src/components/NavGroup.tsx +46 -0
- package/dist/payload/templates/src/components/NavItem.tsx +36 -0
- package/dist/payload/templates/src/components/Sidebar.tsx +76 -0
- package/dist/payload/templates/src/components/UserMenu.tsx +102 -0
- package/dist/payload/templates/src/components/ui/button.tsx +59 -0
- package/dist/payload/templates/src/lib/auth-client.ts +29 -0
- package/dist/payload/templates/src/lib/auth-server.ts +97 -0
- package/dist/payload/templates/src/lib/auth.ts +15 -0
- package/dist/payload/templates/src/lib/utils.ts +7 -0
- package/dist/payload/templates/src/router.tsx +18 -0
- package/dist/payload/templates/src/routes/__root.tsx +53 -0
- package/dist/payload/templates/src/routes/app/demo/convex.messages.tsx +66 -0
- package/dist/payload/templates/src/routes/app/index.tsx +20 -0
- package/dist/payload/templates/src/routes/app/route.tsx +23 -0
- package/dist/payload/templates/src/routes/auth/callback.tsx +36 -0
- package/dist/payload/templates/src/routes/auth/sign-in.tsx +22 -0
- package/dist/payload/templates/src/routes/auth/sign-out.tsx +22 -0
- package/dist/payload/templates/src/routes/index.tsx +85 -0
- package/dist/payload/templates/src/styles.css +141 -0
- package/dist/utils/exec.d.ts +17 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +49 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/flight-rules.d.ts +5 -0
- package/dist/utils/flight-rules.d.ts.map +1 -0
- package/dist/utils/flight-rules.js +23 -0
- package/dist/utils/flight-rules.js.map +1 -0
- package/dist/utils/github.d.ts +17 -0
- package/dist/utils/github.d.ts.map +1 -0
- package/dist/utils/github.js +64 -0
- package/dist/utils/github.js.map +1 -0
- package/dist/utils/logger.d.ts +10 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +27 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/starters.d.ts +20 -0
- package/dist/utils/starters.d.ts.map +1 -0
- package/dist/utils/starters.js +43 -0
- package/dist/utils/starters.js.map +1 -0
- package/dist/utils/templates.d.ts +12 -0
- package/dist/utils/templates.d.ts.map +1 -0
- package/dist/utils/templates.js +77 -0
- package/dist/utils/templates.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
@import "shadcn/tailwind.css";
|
|
4
|
+
@import "@fontsource-variable/inter";
|
|
5
|
+
|
|
6
|
+
@custom-variant dark (&:is(.dark *));
|
|
7
|
+
|
|
8
|
+
body {
|
|
9
|
+
@apply m-0;
|
|
10
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
|
11
|
+
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
12
|
+
sans-serif;
|
|
13
|
+
-webkit-font-smoothing: antialiased;
|
|
14
|
+
-moz-osx-font-smoothing: grayscale;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
code {
|
|
18
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
|
19
|
+
monospace;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@theme inline {
|
|
23
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
24
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
25
|
+
--radius-lg: var(--radius);
|
|
26
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
27
|
+
--radius-2xl: calc(var(--radius) + 8px);
|
|
28
|
+
--radius-3xl: calc(var(--radius) + 12px);
|
|
29
|
+
--radius-4xl: calc(var(--radius) + 16px);
|
|
30
|
+
--color-background: var(--background);
|
|
31
|
+
--color-foreground: var(--foreground);
|
|
32
|
+
--color-card: var(--card);
|
|
33
|
+
--color-card-foreground: var(--card-foreground);
|
|
34
|
+
--color-popover: var(--popover);
|
|
35
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
36
|
+
--color-primary: var(--primary);
|
|
37
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
38
|
+
--color-secondary: var(--secondary);
|
|
39
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
40
|
+
--color-muted: var(--muted);
|
|
41
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
42
|
+
--color-accent: var(--accent);
|
|
43
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
44
|
+
--color-destructive: var(--destructive);
|
|
45
|
+
--color-border: var(--border);
|
|
46
|
+
--color-input: var(--input);
|
|
47
|
+
--color-ring: var(--ring);
|
|
48
|
+
--color-chart-1: var(--chart-1);
|
|
49
|
+
--color-chart-2: var(--chart-2);
|
|
50
|
+
--color-chart-3: var(--chart-3);
|
|
51
|
+
--color-chart-4: var(--chart-4);
|
|
52
|
+
--color-chart-5: var(--chart-5);
|
|
53
|
+
--color-sidebar: var(--sidebar);
|
|
54
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
55
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
56
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
57
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
58
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
59
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
60
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
61
|
+
--font-sans: 'Inter Variable', sans-serif;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:root {
|
|
65
|
+
--radius: 0.625rem;
|
|
66
|
+
--background: oklch(1 0 0);
|
|
67
|
+
--foreground: oklch(0.13 0.028 261.692);
|
|
68
|
+
--card: oklch(1 0 0);
|
|
69
|
+
--card-foreground: oklch(0.13 0.028 261.692);
|
|
70
|
+
--popover: oklch(1 0 0);
|
|
71
|
+
--popover-foreground: oklch(0.13 0.028 261.692);
|
|
72
|
+
--primary: oklch(0.21 0.034 264.665);
|
|
73
|
+
--primary-foreground: oklch(0.985 0.002 247.839);
|
|
74
|
+
--secondary: oklch(0.967 0.003 264.542);
|
|
75
|
+
--secondary-foreground: oklch(0.21 0.034 264.665);
|
|
76
|
+
--muted: oklch(0.967 0.003 264.542);
|
|
77
|
+
--muted-foreground: oklch(0.551 0.027 264.364);
|
|
78
|
+
--accent: oklch(0.967 0.003 264.542);
|
|
79
|
+
--accent-foreground: oklch(0.21 0.034 264.665);
|
|
80
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
81
|
+
--border: oklch(0.928 0.006 264.531);
|
|
82
|
+
--input: oklch(0.928 0.006 264.531);
|
|
83
|
+
--ring: oklch(0.707 0.022 261.325);
|
|
84
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
85
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
86
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
87
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
88
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
89
|
+
--sidebar: oklch(0.985 0.002 247.839);
|
|
90
|
+
--sidebar-foreground: oklch(0.13 0.028 261.692);
|
|
91
|
+
--sidebar-primary: oklch(0.21 0.034 264.665);
|
|
92
|
+
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
|
|
93
|
+
--sidebar-accent: oklch(0.967 0.003 264.542);
|
|
94
|
+
--sidebar-accent-foreground: oklch(0.21 0.034 264.665);
|
|
95
|
+
--sidebar-border: oklch(0.928 0.006 264.531);
|
|
96
|
+
--sidebar-ring: oklch(0.707 0.022 261.325);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.dark {
|
|
100
|
+
--background: oklch(0.13 0.028 261.692);
|
|
101
|
+
--foreground: oklch(0.985 0.002 247.839);
|
|
102
|
+
--card: oklch(0.21 0.034 264.665);
|
|
103
|
+
--card-foreground: oklch(0.985 0.002 247.839);
|
|
104
|
+
--popover: oklch(0.21 0.034 264.665);
|
|
105
|
+
--popover-foreground: oklch(0.985 0.002 247.839);
|
|
106
|
+
--primary: oklch(0.928 0.006 264.531);
|
|
107
|
+
--primary-foreground: oklch(0.21 0.034 264.665);
|
|
108
|
+
--secondary: oklch(0.278 0.033 256.848);
|
|
109
|
+
--secondary-foreground: oklch(0.985 0.002 247.839);
|
|
110
|
+
--muted: oklch(0.278 0.033 256.848);
|
|
111
|
+
--muted-foreground: oklch(0.707 0.022 261.325);
|
|
112
|
+
--accent: oklch(0.278 0.033 256.848);
|
|
113
|
+
--accent-foreground: oklch(0.985 0.002 247.839);
|
|
114
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
115
|
+
--border: oklch(1 0 0 / 10%);
|
|
116
|
+
--input: oklch(1 0 0 / 15%);
|
|
117
|
+
--ring: oklch(0.551 0.027 264.364);
|
|
118
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
119
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
120
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
121
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
122
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
123
|
+
--sidebar: oklch(0.21 0.034 264.665);
|
|
124
|
+
--sidebar-foreground: oklch(0.985 0.002 247.839);
|
|
125
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
126
|
+
--sidebar-primary-foreground: oklch(0.985 0.002 247.839);
|
|
127
|
+
--sidebar-accent: oklch(0.278 0.033 256.848);
|
|
128
|
+
--sidebar-accent-foreground: oklch(0.985 0.002 247.839);
|
|
129
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
130
|
+
--sidebar-ring: oklch(0.551 0.027 264.364);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@layer base {
|
|
134
|
+
* {
|
|
135
|
+
@apply border-border outline-ring/50;
|
|
136
|
+
}
|
|
137
|
+
body {
|
|
138
|
+
@apply font-sans bg-background text-foreground;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ExecOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
silent?: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Execute a command and stream its output to the console.
|
|
7
|
+
* Returns the exit code (0 for success).
|
|
8
|
+
*/
|
|
9
|
+
export declare function execCommand(command: string, args: string[], options?: ExecOptions): Promise<number>;
|
|
10
|
+
export interface CreateProjectOptions {
|
|
11
|
+
packageManager?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Execute npx create command for TanStack Start with a starter.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createTanStackProject(projectName: string, starterUrl: string, options?: CreateProjectOptions): Promise<boolean>;
|
|
17
|
+
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,OAAO,CAAC,CAwBlB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Execute a command and stream its output to the console.
|
|
5
|
+
* Returns the exit code (0 for success).
|
|
6
|
+
*/
|
|
7
|
+
export async function execCommand(command, args, options = {}) {
|
|
8
|
+
const { cwd, silent = false } = options;
|
|
9
|
+
try {
|
|
10
|
+
const subprocess = execa(command, args, {
|
|
11
|
+
cwd,
|
|
12
|
+
stdout: silent ? "pipe" : "inherit",
|
|
13
|
+
stderr: silent ? "pipe" : "inherit",
|
|
14
|
+
stdin: "inherit",
|
|
15
|
+
});
|
|
16
|
+
const result = await subprocess;
|
|
17
|
+
return result.exitCode ?? 0;
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (error && typeof error === "object" && "exitCode" in error) {
|
|
21
|
+
return error.exitCode;
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Execute npx create command for TanStack Start with a starter.
|
|
28
|
+
*/
|
|
29
|
+
export async function createTanStackProject(projectName, starterUrl, options = {}) {
|
|
30
|
+
const { packageManager = "npm" } = options;
|
|
31
|
+
const args = [
|
|
32
|
+
"@tanstack/create-start@latest",
|
|
33
|
+
projectName,
|
|
34
|
+
"--starter",
|
|
35
|
+
starterUrl,
|
|
36
|
+
"--package-manager",
|
|
37
|
+
packageManager,
|
|
38
|
+
"--no-git",
|
|
39
|
+
];
|
|
40
|
+
logger.step(1, 1, "Creating r9stack project...");
|
|
41
|
+
logger.blank();
|
|
42
|
+
const exitCode = await execCommand("npx", args);
|
|
43
|
+
if (exitCode !== 0) {
|
|
44
|
+
logger.error("Failed to create project");
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOrC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,IAAc,EACd,UAAuB,EAAE;IAEzB,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACtC,GAAG;YACH,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YACnC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YACnC,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;QAChC,OAAO,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,UAAU,IAAI,KAAK,EAAE,CAAC;YAC9D,OAAQ,KAA8B,CAAC,QAAQ,CAAC;QAClD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAMD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,WAAmB,EACnB,UAAkB,EAClB,UAAgC,EAAE;IAElC,MAAM,EAAE,cAAc,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAE3C,MAAM,IAAI,GAAG;QACX,+BAA+B;QAC/B,WAAW;QACX,WAAW;QACX,UAAU;QACV,mBAAmB;QACnB,cAAc;QACd,UAAU;KACX,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,6BAA6B,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,EAAE,CAAC;IAEf,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEhD,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flight-rules.d.ts","sourceRoot":"","sources":["../../src/utils/flight-rules.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB7E"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Install Flight Rules documentation framework in the specified directory.
|
|
5
|
+
*/
|
|
6
|
+
export async function installFlightRules(projectDir) {
|
|
7
|
+
try {
|
|
8
|
+
logger.info("Installing Flight Rules documentation framework...");
|
|
9
|
+
await execa("npx", ["flight-rules@dev", "init", "--yes"], {
|
|
10
|
+
cwd: projectDir,
|
|
11
|
+
stdio: "inherit",
|
|
12
|
+
});
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
logger.error("Failed to install Flight Rules");
|
|
17
|
+
if (error instanceof Error) {
|
|
18
|
+
logger.error(error.message);
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=flight-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flight-rules.js","sourceRoot":"","sources":["../../src/utils/flight-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAAkB;IACzD,IAAI,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;QAElE,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,kBAAkB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;YACxD,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAC/C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if the GitHub CLI (gh) is installed and authenticated.
|
|
3
|
+
*/
|
|
4
|
+
export declare function isGhCliInstalled(): Promise<boolean>;
|
|
5
|
+
/**
|
|
6
|
+
* Check if the GitHub CLI is authenticated.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isGhCliAuthenticated(): Promise<boolean>;
|
|
9
|
+
/**
|
|
10
|
+
* Initialize a git repository in the specified directory.
|
|
11
|
+
*/
|
|
12
|
+
export declare function initGitRepo(projectDir: string): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Create a GitHub repository and push the initial commit.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createGitHubRepo(projectDir: string, projectName: string, isPrivate: boolean): Promise<boolean>;
|
|
17
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/utils/github.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOzD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO7D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAetE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,OAAO,CAAC,CAkBlB"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Check if the GitHub CLI (gh) is installed and authenticated.
|
|
5
|
+
*/
|
|
6
|
+
export async function isGhCliInstalled() {
|
|
7
|
+
try {
|
|
8
|
+
await execa("gh", ["--version"]);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if the GitHub CLI is authenticated.
|
|
17
|
+
*/
|
|
18
|
+
export async function isGhCliAuthenticated() {
|
|
19
|
+
try {
|
|
20
|
+
const result = await execa("gh", ["auth", "status"]);
|
|
21
|
+
return result.exitCode === 0;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Initialize a git repository in the specified directory.
|
|
29
|
+
*/
|
|
30
|
+
export async function initGitRepo(projectDir) {
|
|
31
|
+
try {
|
|
32
|
+
await execa("git", ["init"], { cwd: projectDir });
|
|
33
|
+
await execa("git", ["add", "-A"], { cwd: projectDir });
|
|
34
|
+
await execa("git", ["commit", "-m", "Initial commit from r9stack"], {
|
|
35
|
+
cwd: projectDir,
|
|
36
|
+
});
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
logger.error("Failed to initialize git repository");
|
|
41
|
+
if (error instanceof Error) {
|
|
42
|
+
logger.error(error.message);
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create a GitHub repository and push the initial commit.
|
|
49
|
+
*/
|
|
50
|
+
export async function createGitHubRepo(projectDir, projectName, isPrivate) {
|
|
51
|
+
try {
|
|
52
|
+
const visibility = isPrivate ? "--private" : "--public";
|
|
53
|
+
await execa("gh", ["repo", "create", projectName, "--source", ".", visibility, "--push"], { cwd: projectDir });
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
logger.error("Failed to create GitHub repository");
|
|
58
|
+
if (error instanceof Error) {
|
|
59
|
+
logger.error(error.message);
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/utils/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB;IAClD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QAClD,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;QACvD,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,6BAA6B,CAAC,EAAE;YAClE,GAAG,EAAE,UAAU;SAChB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACpD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkB,EAClB,WAAmB,EACnB,SAAkB;IAElB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC;QAExD,MAAM,KAAK,CACT,IAAI,EACJ,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,EACtE,EAAE,GAAG,EAAE,UAAU,EAAE,CACpB,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACnD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const logger: {
|
|
2
|
+
info: (message: string) => void;
|
|
3
|
+
success: (message: string) => void;
|
|
4
|
+
warn: (message: string) => void;
|
|
5
|
+
error: (message: string) => void;
|
|
6
|
+
step: (step: number, total: number, message: string) => void;
|
|
7
|
+
blank: () => void;
|
|
8
|
+
banner: (text: string) => void;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;oBACD,MAAM;uBAIH,MAAM;oBAIT,MAAM;qBAIL,MAAM;iBAIV,MAAM,SAAS,MAAM,WAAW,MAAM;;mBAQpC,MAAM;CAKtB,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
export const logger = {
|
|
3
|
+
info: (message) => {
|
|
4
|
+
console.log(pc.blue("ℹ"), message);
|
|
5
|
+
},
|
|
6
|
+
success: (message) => {
|
|
7
|
+
console.log(pc.green("✔"), message);
|
|
8
|
+
},
|
|
9
|
+
warn: (message) => {
|
|
10
|
+
console.log(pc.yellow("⚠"), message);
|
|
11
|
+
},
|
|
12
|
+
error: (message) => {
|
|
13
|
+
console.log(pc.red("✖"), message);
|
|
14
|
+
},
|
|
15
|
+
step: (step, total, message) => {
|
|
16
|
+
console.log(pc.cyan(`[${step}/${total}]`), message);
|
|
17
|
+
},
|
|
18
|
+
blank: () => {
|
|
19
|
+
console.log();
|
|
20
|
+
},
|
|
21
|
+
banner: (text) => {
|
|
22
|
+
console.log();
|
|
23
|
+
console.log(pc.bold(pc.magenta(text)));
|
|
24
|
+
console.log();
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,EAAE,CAAC,OAAe,EAAE,EAAE;QAC3B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,EAAE,CAAC,OAAe,EAAE,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE;QACzB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,EAAE,CAAC,IAAY,EAAE,KAAa,EAAE,OAAe,EAAE,EAAE;QACrD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,EAAE,GAAG,EAAE;QACV,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;QACvB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface Starter {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
version: string;
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fetch the list of available starters from GitHub.
|
|
10
|
+
*/
|
|
11
|
+
export declare function fetchStarters(): Promise<Starter[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Get the default starter (first in the list).
|
|
14
|
+
*/
|
|
15
|
+
export declare function getDefaultStarter(): Promise<Starter>;
|
|
16
|
+
/**
|
|
17
|
+
* Find a starter by its ID.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getStarterById(id: string): Promise<Starter | undefined>;
|
|
20
|
+
//# sourceMappingURL=starters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starters.d.ts","sourceRoot":"","sources":["../../src/utils/starters.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAsBxD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAQ1D;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAG7E"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { logger } from "./logger.js";
|
|
2
|
+
const STARTERS_URL = "https://raw.githubusercontent.com/ryanpacker/r9stack/main/starters/starters.json";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch the list of available starters from GitHub.
|
|
5
|
+
*/
|
|
6
|
+
export async function fetchStarters() {
|
|
7
|
+
try {
|
|
8
|
+
const response = await fetch(STARTERS_URL);
|
|
9
|
+
if (!response.ok) {
|
|
10
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
11
|
+
}
|
|
12
|
+
const data = (await response.json());
|
|
13
|
+
if (!data.starters || !Array.isArray(data.starters)) {
|
|
14
|
+
throw new Error("Invalid starters index format");
|
|
15
|
+
}
|
|
16
|
+
return data.starters;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
logger.error("Failed to fetch starters list");
|
|
20
|
+
if (error instanceof Error) {
|
|
21
|
+
logger.error(error.message);
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get the default starter (first in the list).
|
|
28
|
+
*/
|
|
29
|
+
export async function getDefaultStarter() {
|
|
30
|
+
const starters = await fetchStarters();
|
|
31
|
+
if (starters.length === 0) {
|
|
32
|
+
throw new Error("No starters available");
|
|
33
|
+
}
|
|
34
|
+
return starters[0];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Find a starter by its ID.
|
|
38
|
+
*/
|
|
39
|
+
export async function getStarterById(id) {
|
|
40
|
+
const starters = await fetchStarters();
|
|
41
|
+
return starters.find((s) => s.id === id || s.id.endsWith(`-${id}`));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=starters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starters.js","sourceRoot":"","sources":["../../src/utils/starters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,YAAY,GAChB,kFAAkF,CAAC;AAcrF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,YAAY,CAAC,CAAC;QAE3C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkB,CAAC;QAEtD,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC9C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC;IAEvC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAU;IAC7C,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC;IACvC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a project name (kebab-case) to a display name (Title Case).
|
|
3
|
+
* Examples:
|
|
4
|
+
* my-awesome-project -> My Awesome Project
|
|
5
|
+
* test-app -> Test App
|
|
6
|
+
*/
|
|
7
|
+
export declare function toDisplayName(projectName: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Replace placeholder strings in all files within a project directory.
|
|
10
|
+
*/
|
|
11
|
+
export declare function replaceProjectNamePlaceholder(projectDir: string, projectName: string): void;
|
|
12
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/utils/templates.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,IAAI,CA4CN"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
const PROJECT_NAME_PLACEHOLDER = "__PROJECT_NAME__";
|
|
5
|
+
/**
|
|
6
|
+
* Recursively find all files in a directory.
|
|
7
|
+
*/
|
|
8
|
+
function getAllFiles(dir, files = []) {
|
|
9
|
+
const entries = readdirSync(dir);
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
const fullPath = join(dir, entry);
|
|
12
|
+
const stat = statSync(fullPath);
|
|
13
|
+
if (stat.isDirectory()) {
|
|
14
|
+
// Skip node_modules and hidden directories
|
|
15
|
+
if (entry !== "node_modules" && !entry.startsWith(".")) {
|
|
16
|
+
getAllFiles(fullPath, files);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
else if (stat.isFile()) {
|
|
20
|
+
files.push(fullPath);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return files;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert a project name (kebab-case) to a display name (Title Case).
|
|
27
|
+
* Examples:
|
|
28
|
+
* my-awesome-project -> My Awesome Project
|
|
29
|
+
* test-app -> Test App
|
|
30
|
+
*/
|
|
31
|
+
export function toDisplayName(projectName) {
|
|
32
|
+
return projectName
|
|
33
|
+
.split("-")
|
|
34
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
35
|
+
.join(" ");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Replace placeholder strings in all files within a project directory.
|
|
39
|
+
*/
|
|
40
|
+
export function replaceProjectNamePlaceholder(projectDir, projectName) {
|
|
41
|
+
const displayName = toDisplayName(projectName);
|
|
42
|
+
const files = getAllFiles(projectDir);
|
|
43
|
+
let replacedCount = 0;
|
|
44
|
+
for (const file of files) {
|
|
45
|
+
// Only process text files
|
|
46
|
+
const ext = file.split(".").pop()?.toLowerCase();
|
|
47
|
+
const textExtensions = [
|
|
48
|
+
"ts",
|
|
49
|
+
"tsx",
|
|
50
|
+
"js",
|
|
51
|
+
"jsx",
|
|
52
|
+
"json",
|
|
53
|
+
"html",
|
|
54
|
+
"css",
|
|
55
|
+
"md",
|
|
56
|
+
"txt",
|
|
57
|
+
];
|
|
58
|
+
if (!ext || !textExtensions.includes(ext)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const content = readFileSync(file, "utf-8");
|
|
63
|
+
if (content.includes(PROJECT_NAME_PLACEHOLDER)) {
|
|
64
|
+
const newContent = content.replaceAll(PROJECT_NAME_PLACEHOLDER, displayName);
|
|
65
|
+
writeFileSync(file, newContent, "utf-8");
|
|
66
|
+
replacedCount++;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Skip files that can't be read (binary, etc.)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (replacedCount > 0) {
|
|
74
|
+
logger.info(`Customized ${replacedCount} file(s) with project name`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/utils/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAEpD;;GAEG;AACH,SAAS,WAAW,CAAC,GAAW,EAAE,QAAkB,EAAE;IACpD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAEjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEhC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,2CAA2C;YAC3C,IAAI,KAAK,KAAK,cAAc,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvD,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,OAAO,WAAW;SACf,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAC3C,UAAkB,EAClB,WAAmB;IAEnB,MAAM,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAEtC,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,CAAC;QACjD,MAAM,cAAc,GAAG;YACrB,IAAI;YACJ,KAAK;YACL,IAAI;YACJ,KAAK;YACL,MAAM;YACN,MAAM;YACN,KAAK;YACL,IAAI;YACJ,KAAK;SACN,CAAC;QAEF,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAE5C,IAAI,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CACnC,wBAAwB,EACxB,WAAW,CACZ,CAAC;gBACF,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;gBACzC,aAAa,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+CAA+C;QACjD,CAAC;IACH,CAAC;IAED,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,cAAc,aAAa,4BAA4B,CAAC,CAAC;IACvE,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "r9stack",
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "CLI tool that scaffolds opinionated SaaS projects with a fully functional walking skeleton",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"r9stack": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"dev": "tsc --watch",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"cli",
|
|
20
|
+
"scaffold",
|
|
21
|
+
"tanstack",
|
|
22
|
+
"convex",
|
|
23
|
+
"saas",
|
|
24
|
+
"starter",
|
|
25
|
+
"boilerplate"
|
|
26
|
+
],
|
|
27
|
+
"author": "",
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/ryanpacker/r9stack"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@inquirer/prompts": "^7.2.1",
|
|
38
|
+
"commander": "^13.0.0",
|
|
39
|
+
"execa": "^9.5.2",
|
|
40
|
+
"picocolors": "^1.1.1"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^22.10.2",
|
|
44
|
+
"typescript": "^5.7.2"
|
|
45
|
+
}
|
|
46
|
+
}
|