@framed-dev/cli 0.1.3 ā 0.1.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/index.js +142 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,62 +9,134 @@ import { execSync } from 'child_process';
|
|
|
9
9
|
async function detectProject(cwd) {
|
|
10
10
|
const packageJsonPath = path2.join(cwd, "package.json");
|
|
11
11
|
if (!await fs2.pathExists(packageJsonPath)) {
|
|
12
|
-
return {
|
|
12
|
+
return {
|
|
13
|
+
type: "unknown",
|
|
14
|
+
srcDir: false,
|
|
15
|
+
hasSupabase: false,
|
|
16
|
+
hasTailwind: false,
|
|
17
|
+
supabaseConfigured: false
|
|
18
|
+
};
|
|
13
19
|
}
|
|
14
20
|
const pkg = await fs2.readJson(packageJsonPath);
|
|
15
21
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
22
|
+
const hasSupabase = !!deps["@supabase/supabase-js"];
|
|
23
|
+
const hasTailwindDep = !!deps["tailwindcss"];
|
|
24
|
+
const hasTailwindConfig = await fs2.pathExists(path2.join(cwd, "tailwind.config.js")) || await fs2.pathExists(path2.join(cwd, "tailwind.config.ts")) || await fs2.pathExists(path2.join(cwd, "tailwind.config.mjs"));
|
|
25
|
+
const hasTailwind = hasTailwindDep || hasTailwindConfig;
|
|
26
|
+
let supabaseConfigured = false;
|
|
27
|
+
const envFiles = [".env.local", ".env", ".env.development", ".env.development.local"];
|
|
28
|
+
for (const envFile of envFiles) {
|
|
29
|
+
const envPath = path2.join(cwd, envFile);
|
|
30
|
+
if (await fs2.pathExists(envPath)) {
|
|
31
|
+
try {
|
|
32
|
+
const envContent = await fs2.readFile(envPath, "utf-8");
|
|
33
|
+
if (envContent.includes("SUPABASE_URL") || envContent.includes("NEXT_PUBLIC_SUPABASE_URL")) {
|
|
34
|
+
supabaseConfigured = true;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
16
41
|
if (deps["next"]) {
|
|
17
42
|
const hasAppDir = await fs2.pathExists(path2.join(cwd, "app")) || await fs2.pathExists(path2.join(cwd, "src/app"));
|
|
18
43
|
const srcDir = await fs2.pathExists(path2.join(cwd, "src"));
|
|
19
44
|
return {
|
|
20
45
|
type: hasAppDir ? "next-app" : "next-pages",
|
|
21
|
-
srcDir
|
|
46
|
+
srcDir,
|
|
47
|
+
hasSupabase,
|
|
48
|
+
hasTailwind,
|
|
49
|
+
supabaseConfigured
|
|
22
50
|
};
|
|
23
51
|
}
|
|
24
52
|
if (deps["vite"]) {
|
|
25
|
-
return {
|
|
53
|
+
return {
|
|
54
|
+
type: "vite",
|
|
55
|
+
srcDir: await fs2.pathExists(path2.join(cwd, "src")),
|
|
56
|
+
hasSupabase,
|
|
57
|
+
hasTailwind,
|
|
58
|
+
supabaseConfigured
|
|
59
|
+
};
|
|
26
60
|
}
|
|
27
|
-
return {
|
|
61
|
+
return {
|
|
62
|
+
type: "unknown",
|
|
63
|
+
srcDir: false,
|
|
64
|
+
hasSupabase,
|
|
65
|
+
hasTailwind,
|
|
66
|
+
supabaseConfigured
|
|
67
|
+
};
|
|
28
68
|
}
|
|
29
69
|
|
|
30
70
|
// src/templates/index.ts
|
|
31
71
|
function getTemplates(type) {
|
|
32
72
|
return {
|
|
33
|
-
dashboard: `
|
|
73
|
+
dashboard: `"use client";
|
|
74
|
+
|
|
75
|
+
import { FramedProvider, FramedStarter } from '@framed-dev/react';
|
|
34
76
|
|
|
35
77
|
export default function FramedPage() {
|
|
36
78
|
return (
|
|
37
|
-
<FramedProvider config={{
|
|
38
|
-
|
|
79
|
+
<FramedProvider config={{
|
|
80
|
+
mode: 'local',
|
|
81
|
+
sync: {
|
|
82
|
+
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
83
|
+
apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
84
|
+
},
|
|
85
|
+
}}>
|
|
86
|
+
<FramedStarter />
|
|
39
87
|
</FramedProvider>
|
|
40
88
|
);
|
|
41
89
|
}
|
|
42
90
|
`,
|
|
43
|
-
review: `
|
|
91
|
+
review: `"use client";
|
|
92
|
+
|
|
93
|
+
import { FramedProvider, FramedReview } from '@framed-dev/react';
|
|
44
94
|
|
|
45
95
|
export default function ReviewPage() {
|
|
46
96
|
return (
|
|
47
|
-
<FramedProvider config={{
|
|
97
|
+
<FramedProvider config={{
|
|
98
|
+
mode: 'local',
|
|
99
|
+
sync: {
|
|
100
|
+
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
101
|
+
apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
102
|
+
},
|
|
103
|
+
}}>
|
|
48
104
|
<FramedReview />
|
|
49
105
|
</FramedProvider>
|
|
50
106
|
);
|
|
51
107
|
}
|
|
52
108
|
`,
|
|
53
|
-
build: `
|
|
109
|
+
build: `"use client";
|
|
110
|
+
|
|
111
|
+
import { FramedProvider, FramedBuild } from '@framed-dev/react';
|
|
54
112
|
|
|
55
113
|
export default function BuildPage() {
|
|
56
114
|
return (
|
|
57
|
-
<FramedProvider config={{
|
|
115
|
+
<FramedProvider config={{
|
|
116
|
+
mode: 'local',
|
|
117
|
+
sync: {
|
|
118
|
+
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
119
|
+
apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
120
|
+
},
|
|
121
|
+
}}>
|
|
58
122
|
<FramedBuild />
|
|
59
123
|
</FramedProvider>
|
|
60
124
|
);
|
|
61
125
|
}
|
|
62
126
|
`,
|
|
63
|
-
manage: `
|
|
127
|
+
manage: `"use client";
|
|
128
|
+
|
|
129
|
+
import { FramedProvider, FramedManage } from '@framed-dev/react';
|
|
64
130
|
|
|
65
131
|
export default function ManagePage() {
|
|
66
132
|
return (
|
|
67
|
-
<FramedProvider config={{
|
|
133
|
+
<FramedProvider config={{
|
|
134
|
+
mode: 'local',
|
|
135
|
+
sync: {
|
|
136
|
+
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
137
|
+
apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
138
|
+
},
|
|
139
|
+
}}>
|
|
68
140
|
<FramedManage />
|
|
69
141
|
</FramedProvider>
|
|
70
142
|
);
|
|
@@ -76,7 +148,7 @@ export default function ManagePage() {
|
|
|
76
148
|
# Optional: For AI features (task parsing, SEO analysis)
|
|
77
149
|
NEXT_PUBLIC_FRAMED_LICENSE_KEY=
|
|
78
150
|
|
|
79
|
-
#
|
|
151
|
+
# Required: Connect your Supabase for data persistence
|
|
80
152
|
NEXT_PUBLIC_SUPABASE_URL=
|
|
81
153
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
|
82
154
|
`,
|
|
@@ -88,7 +160,13 @@ export default function RootLayout({ children }) {
|
|
|
88
160
|
return (
|
|
89
161
|
<html>
|
|
90
162
|
<body>
|
|
91
|
-
<FramedProvider config={{
|
|
163
|
+
<FramedProvider config={{
|
|
164
|
+
mode: 'local',
|
|
165
|
+
sync: {
|
|
166
|
+
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
167
|
+
apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
|
|
168
|
+
},
|
|
169
|
+
}}>
|
|
92
170
|
{children}
|
|
93
171
|
<FeedbackWidget />
|
|
94
172
|
</FramedProvider>
|
|
@@ -104,26 +182,66 @@ export default function RootLayout({ children }) {
|
|
|
104
182
|
async function init(options) {
|
|
105
183
|
const cwd = process.cwd();
|
|
106
184
|
console.log(pc.cyan("\n\u{1F5BC}\uFE0F Framed Setup\n"));
|
|
107
|
-
const { type, srcDir } = await detectProject(cwd);
|
|
185
|
+
const { type, srcDir, hasSupabase, hasTailwind, supabaseConfigured } = await detectProject(cwd);
|
|
108
186
|
if (type === "unknown") {
|
|
109
187
|
console.log(pc.red("Could not detect project type. Make sure you have a package.json."));
|
|
110
188
|
process.exit(1);
|
|
111
189
|
}
|
|
112
190
|
console.log(pc.green(`\u2713 Detected: ${formatType(type)}${srcDir ? " (src directory)" : ""}`));
|
|
191
|
+
console.log(pc.dim(` Tailwind CSS: ${hasTailwind ? pc.green("\u2713") : pc.yellow("\u25CB will install")}`));
|
|
192
|
+
console.log(pc.dim(` Supabase: ${hasSupabase ? pc.green("\u2713") : pc.yellow("\u25CB will install")}`));
|
|
193
|
+
if (hasSupabase) {
|
|
194
|
+
console.log(pc.dim(` Supabase configured: ${supabaseConfigured ? pc.green("\u2713") : pc.yellow("\u25CB add to .env")}`));
|
|
195
|
+
}
|
|
113
196
|
if (type === "next-pages" || type === "vite") {
|
|
114
197
|
console.log(pc.yellow("\nCurrently only Next.js App Router is supported."));
|
|
115
198
|
console.log("Support for Pages Router and Vite coming soon.\n");
|
|
116
199
|
process.exit(1);
|
|
117
200
|
}
|
|
118
|
-
|
|
201
|
+
const useYarn = await fs2.pathExists(path2.join(cwd, "yarn.lock"));
|
|
202
|
+
const usePnpm = await fs2.pathExists(path2.join(cwd, "pnpm-lock.yaml"));
|
|
203
|
+
const cmd = usePnpm ? "pnpm add" : useYarn ? "yarn add" : "npm install";
|
|
204
|
+
const toInstall = ["@framed-dev/react"];
|
|
205
|
+
if (!hasTailwind) {
|
|
206
|
+
toInstall.push("tailwindcss", "postcss", "autoprefixer");
|
|
207
|
+
}
|
|
208
|
+
if (!hasSupabase) {
|
|
209
|
+
toInstall.push("@supabase/supabase-js");
|
|
210
|
+
}
|
|
211
|
+
console.log(pc.cyan(`
|
|
212
|
+
Installing ${toInstall.join(", ")}...`));
|
|
119
213
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
execSync(`${cmd} @framed-dev/react`, { cwd, stdio: "inherit" });
|
|
124
|
-
console.log(pc.green("\u2713 Installed @framed-dev/react\n"));
|
|
214
|
+
execSync(`${cmd} ${toInstall.join(" ")}`, { cwd, stdio: "inherit" });
|
|
215
|
+
console.log(pc.green(`\u2713 Installed dependencies
|
|
216
|
+
`));
|
|
125
217
|
} catch (e) {
|
|
126
|
-
console.log(pc.yellow(
|
|
218
|
+
console.log(pc.yellow(`\u26A0 Could not auto-install. Run: npm install ${toInstall.join(" ")}
|
|
219
|
+
`));
|
|
220
|
+
}
|
|
221
|
+
if (!hasTailwind) {
|
|
222
|
+
console.log(pc.cyan("Initializing Tailwind CSS..."));
|
|
223
|
+
try {
|
|
224
|
+
execSync("npx tailwindcss init -p", { cwd, stdio: "inherit" });
|
|
225
|
+
console.log(pc.green("\u2713 Initialized Tailwind CSS\n"));
|
|
226
|
+
const tailwindConfigPath = path2.join(cwd, "tailwind.config.js");
|
|
227
|
+
if (await fs2.pathExists(tailwindConfigPath)) {
|
|
228
|
+
let tailwindConfig = await fs2.readFile(tailwindConfigPath, "utf-8");
|
|
229
|
+
if (tailwindConfig.includes("content: []")) {
|
|
230
|
+
tailwindConfig = tailwindConfig.replace(
|
|
231
|
+
"content: []",
|
|
232
|
+
`content: [
|
|
233
|
+
"./src/**/*.{js,ts,jsx,tsx,mdx}",
|
|
234
|
+
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
235
|
+
"./node_modules/@framed-dev/react/**/*.{js,ts,jsx,tsx}",
|
|
236
|
+
]`
|
|
237
|
+
);
|
|
238
|
+
await fs2.writeFile(tailwindConfigPath, tailwindConfig);
|
|
239
|
+
console.log(pc.green("\u2713 Updated tailwind.config.js with content paths\n"));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
} catch (e) {
|
|
243
|
+
console.log(pc.yellow("\u26A0 Could not initialize Tailwind. Run: npx tailwindcss init -p\n"));
|
|
244
|
+
}
|
|
127
245
|
}
|
|
128
246
|
const appDir = srcDir ? "src/app" : "app";
|
|
129
247
|
const framedDir = path2.join(cwd, appDir, "framed");
|
|
@@ -180,7 +298,7 @@ function formatType(type) {
|
|
|
180
298
|
|
|
181
299
|
// src/index.ts
|
|
182
300
|
var program = new Command();
|
|
183
|
-
program.name("framed").description("CLI for setting up Framed in your project").version("0.1.
|
|
301
|
+
program.name("framed").description("CLI for setting up Framed in your project").version("0.1.4");
|
|
184
302
|
program.command("init").description("Initialize Framed in your project").option("--force", "Overwrite existing files").action(init);
|
|
185
303
|
program.parse();
|
|
186
304
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/detect.ts","../src/templates/index.ts","../src/init.ts","../src/index.ts"],"names":["path","fs"],"mappings":"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","file":"index.js","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\n\nexport type ProjectType = 'next-app' | 'next-pages' | 'vite' | 'unknown';\n\nexport async function detectProject(cwd: string): Promise<{\n type: ProjectType;\n srcDir: boolean;\n}> {\n const packageJsonPath = path.join(cwd, 'package.json');\n\n if (!await fs.pathExists(packageJsonPath)) {\n return { type: 'unknown', srcDir: false };\n }\n\n const pkg = await fs.readJson(packageJsonPath);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n // Check for Next.js\n if (deps['next']) {\n const hasAppDir = await fs.pathExists(path.join(cwd, 'app')) ||\n await fs.pathExists(path.join(cwd, 'src/app'));\n const srcDir = await fs.pathExists(path.join(cwd, 'src'));\n\n return {\n type: hasAppDir ? 'next-app' : 'next-pages',\n srcDir\n };\n }\n\n // Check for Vite\n if (deps['vite']) {\n return { type: 'vite', srcDir: await fs.pathExists(path.join(cwd, 'src')) };\n }\n\n return { type: 'unknown', srcDir: false };\n}\n","export function getTemplates(type: 'next-app') {\n return {\n dashboard: `import { FramedProvider, FramedDashboard } from '@framed-dev/react';\n\nexport default function FramedPage() {\n return (\n <FramedProvider config={{ mode: 'local' }}>\n <FramedDashboard />\n </FramedProvider>\n );\n}\n`,\n review: `import { FramedProvider, FramedReview } from '@framed-dev/react';\n\nexport default function ReviewPage() {\n return (\n <FramedProvider config={{ mode: 'local' }}>\n <FramedReview />\n </FramedProvider>\n );\n}\n`,\n build: `import { FramedProvider, FramedBuild } from '@framed-dev/react';\n\nexport default function BuildPage() {\n return (\n <FramedProvider config={{ mode: 'local' }}>\n <FramedBuild />\n </FramedProvider>\n );\n}\n`,\n manage: `import { FramedProvider, FramedManage } from '@framed-dev/react';\n\nexport default function ManagePage() {\n return (\n <FramedProvider config={{ mode: 'local' }}>\n <FramedManage />\n </FramedProvider>\n );\n}\n`,\n env: `# Framed Configuration\n# Get your license key at https://framed.dev/dashboard\n\n# Optional: For AI features (task parsing, SEO analysis)\nNEXT_PUBLIC_FRAMED_LICENSE_KEY=\n\n# Optional: Connect your own Supabase for data persistence\nNEXT_PUBLIC_SUPABASE_URL=\nNEXT_PUBLIC_SUPABASE_ANON_KEY=\n`,\n layoutSnippet: `\n// app/layout.tsx\nimport { FramedProvider, FeedbackWidget } from '@framed-dev/react';\n\nexport default function RootLayout({ children }) {\n return (\n <html>\n <body>\n <FramedProvider config={{ mode: 'local' }}>\n {children}\n <FeedbackWidget />\n </FramedProvider>\n </body>\n </html>\n );\n}\n`\n };\n}\n","import fs from 'fs-extra';\nimport path from 'path';\nimport prompts from 'prompts';\nimport pc from 'picocolors';\nimport { execSync } from 'child_process';\nimport { detectProject, ProjectType } from './detect';\nimport { getTemplates } from './templates';\n\nexport async function init(options: { force?: boolean }) {\n const cwd = process.cwd();\n\n console.log(pc.cyan('\\nš¼ļø Framed Setup\\n'));\n\n // Detect project\n const { type, srcDir } = await detectProject(cwd);\n\n if (type === 'unknown') {\n console.log(pc.red('Could not detect project type. Make sure you have a package.json.'));\n process.exit(1);\n }\n\n console.log(pc.green(`ā Detected: ${formatType(type)}${srcDir ? ' (src directory)' : ''}`));\n\n if (type === 'next-pages' || type === 'vite') {\n console.log(pc.yellow('\\nCurrently only Next.js App Router is supported.'));\n console.log('Support for Pages Router and Vite coming soon.\\n');\n process.exit(1);\n }\n\n // Install @framed-dev/react\n console.log(pc.cyan('\\nInstalling @framed-dev/react...'));\n\n try {\n // Detect package manager\n const useYarn = await fs.pathExists(path.join(cwd, 'yarn.lock'));\n const usePnpm = await fs.pathExists(path.join(cwd, 'pnpm-lock.yaml'));\n\n const cmd = usePnpm ? 'pnpm add' : useYarn ? 'yarn add' : 'npm install';\n execSync(`${cmd} @framed-dev/react`, { cwd, stdio: 'inherit' });\n\n console.log(pc.green('ā Installed @framed-dev/react\\n'));\n } catch (e) {\n console.log(pc.yellow('ā Could not auto-install. Run: npm install @framed-dev/react\\n'));\n }\n\n // Get base path\n const appDir = srcDir ? 'src/app' : 'app';\n const framedDir = path.join(cwd, appDir, 'framed');\n\n // Check if already exists\n if (await fs.pathExists(framedDir) && !options.force) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: '/framed directory already exists. Overwrite?',\n initial: false\n });\n\n if (!overwrite) {\n console.log(pc.yellow('Aborted.'));\n process.exit(0);\n }\n }\n\n // Create files\n const templates = getTemplates('next-app');\n\n // Create framed pages\n await fs.ensureDir(framedDir);\n await fs.writeFile(path.join(framedDir, 'page.tsx'), templates.dashboard);\n console.log(pc.green(`ā Created: ${appDir}/framed/page.tsx`));\n\n await fs.ensureDir(path.join(framedDir, 'review'));\n await fs.writeFile(path.join(framedDir, 'review/page.tsx'), templates.review);\n console.log(pc.green(`ā Created: ${appDir}/framed/review/page.tsx`));\n\n await fs.ensureDir(path.join(framedDir, 'build'));\n await fs.writeFile(path.join(framedDir, 'build/page.tsx'), templates.build);\n console.log(pc.green(`ā Created: ${appDir}/framed/build/page.tsx`));\n\n await fs.ensureDir(path.join(framedDir, 'manage'));\n await fs.writeFile(path.join(framedDir, 'manage/page.tsx'), templates.manage);\n console.log(pc.green(`ā Created: ${appDir}/framed/manage/page.tsx`));\n\n // Create .env.example\n const envPath = path.join(cwd, '.env.example');\n if (!await fs.pathExists(envPath)) {\n await fs.writeFile(envPath, templates.env);\n console.log(pc.green(`ā Created: .env.example`));\n }\n\n // Instructions\n console.log(pc.cyan('\\n⨠Framed setup complete!\\n'));\n console.log('Next steps:');\n console.log(pc.dim(' 1. Add FramedProvider to your root layout'));\n console.log(pc.dim(' 2. Copy .env.example to .env.local and fill in values'));\n console.log(pc.dim(' 3. Visit /framed to get started\\n'));\n\n console.log('Add to your layout.tsx:');\n console.log(pc.dim(templates.layoutSnippet));\n}\n\nfunction formatType(type: ProjectType): string {\n switch (type) {\n case 'next-app': return 'Next.js (App Router)';\n case 'next-pages': return 'Next.js (Pages Router)';\n case 'vite': return 'Vite';\n default: return 'Unknown';\n }\n}\n","import { Command } from 'commander';\nimport { init } from './init';\n\nconst program = new Command();\n\nprogram\n .name('framed')\n .description('CLI for setting up Framed in your project')\n .version('0.1.1');\n\nprogram\n .command('init')\n .description('Initialize Framed in your project')\n .option('--force', 'Overwrite existing files')\n .action(init);\n\nprogram.parse();\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/detect.ts","../src/templates/index.ts","../src/init.ts","../src/index.ts"],"names":["path","fs"],"mappings":"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","file":"index.js","sourcesContent":["import fs from 'fs-extra';\nimport path from 'path';\n\nexport type ProjectType = 'next-app' | 'next-pages' | 'vite' | 'unknown';\n\nexport interface ProjectInfo {\n type: ProjectType;\n srcDir: boolean;\n hasSupabase: boolean;\n hasTailwind: boolean;\n supabaseConfigured: boolean;\n}\n\nexport async function detectProject(cwd: string): Promise<ProjectInfo> {\n const packageJsonPath = path.join(cwd, 'package.json');\n\n if (!await fs.pathExists(packageJsonPath)) {\n return {\n type: 'unknown',\n srcDir: false,\n hasSupabase: false,\n hasTailwind: false,\n supabaseConfigured: false,\n };\n }\n\n const pkg = await fs.readJson(packageJsonPath);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n // Detect Supabase\n const hasSupabase = !!deps['@supabase/supabase-js'];\n\n // Detect Tailwind\n const hasTailwindDep = !!deps['tailwindcss'];\n const hasTailwindConfig = await fs.pathExists(path.join(cwd, 'tailwind.config.js')) ||\n await fs.pathExists(path.join(cwd, 'tailwind.config.ts')) ||\n await fs.pathExists(path.join(cwd, 'tailwind.config.mjs'));\n const hasTailwind = hasTailwindDep || hasTailwindConfig;\n\n // Check .env files for Supabase configuration\n let supabaseConfigured = false;\n const envFiles = ['.env.local', '.env', '.env.development', '.env.development.local'];\n\n for (const envFile of envFiles) {\n const envPath = path.join(cwd, envFile);\n if (await fs.pathExists(envPath)) {\n try {\n const envContent = await fs.readFile(envPath, 'utf-8');\n if (envContent.includes('SUPABASE_URL') ||\n envContent.includes('NEXT_PUBLIC_SUPABASE_URL')) {\n supabaseConfigured = true;\n break;\n }\n } catch {\n // Ignore read errors\n }\n }\n }\n\n // Check for Next.js\n if (deps['next']) {\n const hasAppDir = await fs.pathExists(path.join(cwd, 'app')) ||\n await fs.pathExists(path.join(cwd, 'src/app'));\n const srcDir = await fs.pathExists(path.join(cwd, 'src'));\n\n return {\n type: hasAppDir ? 'next-app' : 'next-pages',\n srcDir,\n hasSupabase,\n hasTailwind,\n supabaseConfigured,\n };\n }\n\n // Check for Vite\n if (deps['vite']) {\n return {\n type: 'vite',\n srcDir: await fs.pathExists(path.join(cwd, 'src')),\n hasSupabase,\n hasTailwind,\n supabaseConfigured,\n };\n }\n\n return {\n type: 'unknown',\n srcDir: false,\n hasSupabase,\n hasTailwind,\n supabaseConfigured,\n };\n}\n","export function getTemplates(type: 'next-app') {\n return {\n dashboard: `\"use client\";\n\nimport { FramedProvider, FramedStarter } from '@framed-dev/react';\n\nexport default function FramedPage() {\n return (\n <FramedProvider config={{\n mode: 'local',\n sync: {\n supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,\n apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,\n },\n }}>\n <FramedStarter />\n </FramedProvider>\n );\n}\n`,\n review: `\"use client\";\n\nimport { FramedProvider, FramedReview } from '@framed-dev/react';\n\nexport default function ReviewPage() {\n return (\n <FramedProvider config={{\n mode: 'local',\n sync: {\n supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,\n apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,\n },\n }}>\n <FramedReview />\n </FramedProvider>\n );\n}\n`,\n build: `\"use client\";\n\nimport { FramedProvider, FramedBuild } from '@framed-dev/react';\n\nexport default function BuildPage() {\n return (\n <FramedProvider config={{\n mode: 'local',\n sync: {\n supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,\n apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,\n },\n }}>\n <FramedBuild />\n </FramedProvider>\n );\n}\n`,\n manage: `\"use client\";\n\nimport { FramedProvider, FramedManage } from '@framed-dev/react';\n\nexport default function ManagePage() {\n return (\n <FramedProvider config={{\n mode: 'local',\n sync: {\n supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,\n apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,\n },\n }}>\n <FramedManage />\n </FramedProvider>\n );\n}\n`,\n env: `# Framed Configuration\n# Get your license key at https://framed.dev/dashboard\n\n# Optional: For AI features (task parsing, SEO analysis)\nNEXT_PUBLIC_FRAMED_LICENSE_KEY=\n\n# Required: Connect your Supabase for data persistence\nNEXT_PUBLIC_SUPABASE_URL=\nNEXT_PUBLIC_SUPABASE_ANON_KEY=\n`,\n layoutSnippet: `\n// app/layout.tsx\nimport { FramedProvider, FeedbackWidget } from '@framed-dev/react';\n\nexport default function RootLayout({ children }) {\n return (\n <html>\n <body>\n <FramedProvider config={{\n mode: 'local',\n sync: {\n supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL,\n apiKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,\n },\n }}>\n {children}\n <FeedbackWidget />\n </FramedProvider>\n </body>\n </html>\n );\n}\n`\n };\n}\n","import fs from 'fs-extra';\nimport path from 'path';\nimport prompts from 'prompts';\nimport pc from 'picocolors';\nimport { execSync } from 'child_process';\nimport { detectProject, ProjectType } from './detect';\nimport { getTemplates } from './templates';\n\nexport async function init(options: { force?: boolean }) {\n const cwd = process.cwd();\n\n console.log(pc.cyan('\\nš¼ļø Framed Setup\\n'));\n\n // Detect project\n const { type, srcDir, hasSupabase, hasTailwind, supabaseConfigured } = await detectProject(cwd);\n\n if (type === 'unknown') {\n console.log(pc.red('Could not detect project type. Make sure you have a package.json.'));\n process.exit(1);\n }\n\n console.log(pc.green(`ā Detected: ${formatType(type)}${srcDir ? ' (src directory)' : ''}`));\n\n // Show detection status\n console.log(pc.dim(` Tailwind CSS: ${hasTailwind ? pc.green('ā') : pc.yellow('ā will install')}`));\n console.log(pc.dim(` Supabase: ${hasSupabase ? pc.green('ā') : pc.yellow('ā will install')}`));\n if (hasSupabase) {\n console.log(pc.dim(` Supabase configured: ${supabaseConfigured ? pc.green('ā') : pc.yellow('ā add to .env')}`));\n }\n\n if (type === 'next-pages' || type === 'vite') {\n console.log(pc.yellow('\\nCurrently only Next.js App Router is supported.'));\n console.log('Support for Pages Router and Vite coming soon.\\n');\n process.exit(1);\n }\n\n // Detect package manager\n const useYarn = await fs.pathExists(path.join(cwd, 'yarn.lock'));\n const usePnpm = await fs.pathExists(path.join(cwd, 'pnpm-lock.yaml'));\n const cmd = usePnpm ? 'pnpm add' : useYarn ? 'yarn add' : 'npm install';\n\n // Build list of packages to install\n const toInstall: string[] = ['@framed-dev/react'];\n\n if (!hasTailwind) {\n toInstall.push('tailwindcss', 'postcss', 'autoprefixer');\n }\n\n if (!hasSupabase) {\n toInstall.push('@supabase/supabase-js');\n }\n\n // Install dependencies\n console.log(pc.cyan(`\\nInstalling ${toInstall.join(', ')}...`));\n\n try {\n execSync(`${cmd} ${toInstall.join(' ')}`, { cwd, stdio: 'inherit' });\n console.log(pc.green(`ā Installed dependencies\\n`));\n } catch (e) {\n console.log(pc.yellow(`ā Could not auto-install. Run: npm install ${toInstall.join(' ')}\\n`));\n }\n\n // Initialize Tailwind if it wasn't present\n if (!hasTailwind) {\n console.log(pc.cyan('Initializing Tailwind CSS...'));\n try {\n execSync('npx tailwindcss init -p', { cwd, stdio: 'inherit' });\n console.log(pc.green('ā Initialized Tailwind CSS\\n'));\n\n // Update tailwind.config.js to include framed paths\n const tailwindConfigPath = path.join(cwd, 'tailwind.config.js');\n if (await fs.pathExists(tailwindConfigPath)) {\n let tailwindConfig = await fs.readFile(tailwindConfigPath, 'utf-8');\n if (tailwindConfig.includes('content: []')) {\n tailwindConfig = tailwindConfig.replace(\n 'content: []',\n `content: [\n \"./src/**/*.{js,ts,jsx,tsx,mdx}\",\n \"./app/**/*.{js,ts,jsx,tsx,mdx}\",\n \"./node_modules/@framed-dev/react/**/*.{js,ts,jsx,tsx}\",\n ]`\n );\n await fs.writeFile(tailwindConfigPath, tailwindConfig);\n console.log(pc.green('ā Updated tailwind.config.js with content paths\\n'));\n }\n }\n } catch (e) {\n console.log(pc.yellow('ā Could not initialize Tailwind. Run: npx tailwindcss init -p\\n'));\n }\n }\n\n // Get base path\n const appDir = srcDir ? 'src/app' : 'app';\n const framedDir = path.join(cwd, appDir, 'framed');\n\n // Check if already exists\n if (await fs.pathExists(framedDir) && !options.force) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: '/framed directory already exists. Overwrite?',\n initial: false\n });\n\n if (!overwrite) {\n console.log(pc.yellow('Aborted.'));\n process.exit(0);\n }\n }\n\n // Create files\n const templates = getTemplates('next-app');\n\n // Create framed pages\n await fs.ensureDir(framedDir);\n await fs.writeFile(path.join(framedDir, 'page.tsx'), templates.dashboard);\n console.log(pc.green(`ā Created: ${appDir}/framed/page.tsx`));\n\n await fs.ensureDir(path.join(framedDir, 'review'));\n await fs.writeFile(path.join(framedDir, 'review/page.tsx'), templates.review);\n console.log(pc.green(`ā Created: ${appDir}/framed/review/page.tsx`));\n\n await fs.ensureDir(path.join(framedDir, 'build'));\n await fs.writeFile(path.join(framedDir, 'build/page.tsx'), templates.build);\n console.log(pc.green(`ā Created: ${appDir}/framed/build/page.tsx`));\n\n await fs.ensureDir(path.join(framedDir, 'manage'));\n await fs.writeFile(path.join(framedDir, 'manage/page.tsx'), templates.manage);\n console.log(pc.green(`ā Created: ${appDir}/framed/manage/page.tsx`));\n\n // Create .env.example\n const envPath = path.join(cwd, '.env.example');\n if (!await fs.pathExists(envPath)) {\n await fs.writeFile(envPath, templates.env);\n console.log(pc.green(`ā Created: .env.example`));\n }\n\n // Instructions\n console.log(pc.cyan('\\n⨠Framed setup complete!\\n'));\n console.log('Next steps:');\n console.log(pc.dim(' 1. Add FramedProvider to your root layout'));\n console.log(pc.dim(' 2. Copy .env.example to .env.local and fill in values'));\n console.log(pc.dim(' 3. Visit /framed to get started\\n'));\n\n console.log('Add to your layout.tsx:');\n console.log(pc.dim(templates.layoutSnippet));\n}\n\nfunction formatType(type: ProjectType): string {\n switch (type) {\n case 'next-app': return 'Next.js (App Router)';\n case 'next-pages': return 'Next.js (Pages Router)';\n case 'vite': return 'Vite';\n default: return 'Unknown';\n }\n}\n","import { Command } from 'commander';\nimport { init } from './init';\n\nconst program = new Command();\n\nprogram\n .name('framed')\n .description('CLI for setting up Framed in your project')\n .version('0.1.4');\n\nprogram\n .command('init')\n .description('Initialize Framed in your project')\n .option('--force', 'Overwrite existing files')\n .action(init);\n\nprogram.parse();\n"]}
|