@buoy-design/cli 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.
- package/dist/commands/audit.d.ts +3 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +235 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/baseline.d.ts +39 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +298 -0
- package/dist/commands/baseline.js.map +1 -0
- package/dist/commands/check.d.ts +16 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +168 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/ci.d.ts +2 -2
- package/dist/commands/ci.d.ts.map +1 -1
- package/dist/commands/ci.js +124 -142
- package/dist/commands/ci.js.map +1 -1
- package/dist/commands/compare.d.ts +3 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +170 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/drift.d.ts +1 -1
- package/dist/commands/drift.d.ts.map +1 -1
- package/dist/commands/drift.js +79 -121
- package/dist/commands/drift.js.map +1 -1
- package/dist/commands/explain.d.ts +3 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +212 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/graph.d.ts +3 -0
- package/dist/commands/graph.d.ts.map +1 -0
- package/dist/commands/graph.js +430 -0
- package/dist/commands/graph.js.map +1 -0
- package/dist/commands/index.d.ts +14 -8
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +14 -8
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +404 -237
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +32 -41
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/scan.d.ts +1 -1
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +107 -219
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +114 -122
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/tokens.d.ts +3 -0
- package/dist/commands/tokens.d.ts.map +1 -0
- package/dist/commands/tokens.js +261 -0
- package/dist/commands/tokens.js.map +1 -0
- package/dist/config/auto-detect.d.ts +21 -0
- package/dist/config/auto-detect.d.ts.map +1 -0
- package/dist/config/auto-detect.js +278 -0
- package/dist/config/auto-detect.js.map +1 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +17 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +63 -63
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +20 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/constants.d.ts +36 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +37 -0
- package/dist/constants.js.map +1 -0
- package/dist/detect/frameworks.d.ts +11 -2
- package/dist/detect/frameworks.d.ts.map +1 -1
- package/dist/detect/frameworks.js +78 -78
- package/dist/detect/frameworks.js.map +1 -1
- package/dist/detect/index.d.ts +1 -0
- package/dist/detect/index.d.ts.map +1 -1
- package/dist/detect/index.js +3 -0
- package/dist/detect/index.js.map +1 -1
- package/dist/detect/monorepo-patterns.d.ts +54 -0
- package/dist/detect/monorepo-patterns.d.ts.map +1 -0
- package/dist/detect/monorepo-patterns.js +209 -0
- package/dist/detect/monorepo-patterns.js.map +1 -0
- package/dist/detect/project-detector.d.ts +1 -1
- package/dist/detect/project-detector.d.ts.map +1 -1
- package/dist/detect/project-detector.js +132 -0
- package/dist/detect/project-detector.js.map +1 -1
- package/dist/explain/agents.d.ts +31 -0
- package/dist/explain/agents.d.ts.map +1 -0
- package/dist/explain/agents.js +507 -0
- package/dist/explain/agents.js.map +1 -0
- package/dist/hooks/index.d.ts +26 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +283 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/dist/integrations/github-formatter.d.ts +55 -0
- package/dist/integrations/github-formatter.d.ts.map +1 -0
- package/dist/integrations/github-formatter.js +391 -0
- package/dist/integrations/github-formatter.js.map +1 -0
- package/dist/integrations/github.d.ts +95 -0
- package/dist/integrations/github.d.ts.map +1 -0
- package/dist/integrations/github.js +281 -0
- package/dist/integrations/github.js.map +1 -0
- package/dist/integrations/index.d.ts +4 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +4 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/output/formatters.d.ts.map +1 -1
- package/dist/output/formatters.js +5 -10
- package/dist/output/formatters.js.map +1 -1
- package/dist/scan/orchestrator.d.ts +76 -0
- package/dist/scan/orchestrator.d.ts.map +1 -0
- package/dist/scan/orchestrator.js +247 -0
- package/dist/scan/orchestrator.js.map +1 -0
- package/dist/services/ai-analysis.d.ts +54 -0
- package/dist/services/ai-analysis.d.ts.map +1 -0
- package/dist/services/ai-analysis.js +239 -0
- package/dist/services/ai-analysis.js.map +1 -0
- package/dist/services/drift-analysis.d.ts +77 -0
- package/dist/services/drift-analysis.d.ts.map +1 -0
- package/dist/services/drift-analysis.js +145 -0
- package/dist/services/drift-analysis.js.map +1 -0
- package/package.json +17 -5
- package/dist/commands/__tests__/ci.test.d.ts +0 -2
- package/dist/commands/__tests__/ci.test.d.ts.map +0 -1
- package/dist/commands/__tests__/ci.test.js +0 -33
- package/dist/commands/__tests__/ci.test.js.map +0 -1
- package/dist/commands/bootstrap.d.ts +0 -3
- package/dist/commands/bootstrap.d.ts.map +0 -1
- package/dist/commands/bootstrap.js +0 -458
- package/dist/commands/bootstrap.js.map +0 -1
- package/dist/plugins/index.d.ts +0 -3
- package/dist/plugins/index.d.ts.map +0 -1
- package/dist/plugins/index.js +0 -3
- package/dist/plugins/index.js.map +0 -1
- package/dist/plugins/loader.d.ts +0 -11
- package/dist/plugins/loader.d.ts.map +0 -1
- package/dist/plugins/loader.js +0 -77
- package/dist/plugins/loader.js.map +0 -1
- package/dist/plugins/registry.d.ts +0 -15
- package/dist/plugins/registry.d.ts.map +0 -1
- package/dist/plugins/registry.js +0 -32
- package/dist/plugins/registry.js.map +0 -1
package/dist/commands/init.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { Command } from
|
|
2
|
-
import { writeFileSync, existsSync } from
|
|
3
|
-
import { resolve } from
|
|
4
|
-
import chalk from
|
|
5
|
-
import ora from
|
|
6
|
-
import { createInterface } from
|
|
7
|
-
import { success, error, info, warning } from
|
|
8
|
-
import { ProjectDetector } from
|
|
9
|
-
import { detectFrameworks, getPluginInstallCommand, PLUGIN_INFO } from
|
|
10
|
-
import {
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { writeFileSync, existsSync } from "fs";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
import { createInterface } from "readline";
|
|
7
|
+
import { success, error, info, warning } from "../output/reporters.js";
|
|
8
|
+
import { ProjectDetector, detectMonorepoConfig, expandPatternsForMonorepo, } from "../detect/index.js";
|
|
9
|
+
import { detectFrameworks, getPluginInstallCommand, PLUGIN_INFO, BUILTIN_SCANNERS, } from "../detect/frameworks.js";
|
|
10
|
+
import { setupHooks, generateStandaloneHook, detectHookSystem, } from "../hooks/index.js";
|
|
11
11
|
function generateConfig(project) {
|
|
12
12
|
const lines = [];
|
|
13
|
+
// Detect monorepo configuration for pattern expansion
|
|
14
|
+
const monorepoConfig = detectMonorepoConfig(project.root);
|
|
13
15
|
lines.push(`/** @type {import('@buoy-design/cli').BuoyConfig} */`);
|
|
14
16
|
lines.push(`export default {`);
|
|
15
17
|
lines.push(` project: {`);
|
|
@@ -19,44 +21,53 @@ function generateConfig(project) {
|
|
|
19
21
|
// Determine the correct source key based on framework
|
|
20
22
|
const getSourceKey = (frameworkName) => {
|
|
21
23
|
// React-based frameworks
|
|
22
|
-
if ([
|
|
23
|
-
|
|
24
|
+
if ([
|
|
25
|
+
"react",
|
|
26
|
+
"nextjs",
|
|
27
|
+
"remix",
|
|
28
|
+
"gatsby",
|
|
29
|
+
"react-native",
|
|
30
|
+
"expo",
|
|
31
|
+
"preact",
|
|
32
|
+
"solid",
|
|
33
|
+
].includes(frameworkName)) {
|
|
34
|
+
return "react";
|
|
24
35
|
}
|
|
25
36
|
// Vue-based frameworks
|
|
26
|
-
if ([
|
|
27
|
-
return
|
|
37
|
+
if (["vue", "nuxt"].includes(frameworkName)) {
|
|
38
|
+
return "vue";
|
|
28
39
|
}
|
|
29
40
|
// Svelte-based frameworks
|
|
30
|
-
if ([
|
|
31
|
-
return
|
|
41
|
+
if (["svelte", "sveltekit"].includes(frameworkName)) {
|
|
42
|
+
return "svelte";
|
|
32
43
|
}
|
|
33
44
|
// Angular
|
|
34
|
-
if (frameworkName ===
|
|
35
|
-
return
|
|
45
|
+
if (frameworkName === "angular") {
|
|
46
|
+
return "angular";
|
|
36
47
|
}
|
|
37
48
|
// Web Components
|
|
38
|
-
if ([
|
|
39
|
-
return
|
|
49
|
+
if (["lit", "stencil"].includes(frameworkName)) {
|
|
50
|
+
return "webcomponent";
|
|
40
51
|
}
|
|
41
52
|
// Astro is special - can use multiple frameworks
|
|
42
|
-
if (frameworkName ===
|
|
43
|
-
return
|
|
53
|
+
if (frameworkName === "astro") {
|
|
54
|
+
return "react"; // Default to React for Astro
|
|
44
55
|
}
|
|
45
56
|
return null;
|
|
46
57
|
};
|
|
47
58
|
// File extensions by framework
|
|
48
59
|
const getExtensions = (sourceKey, typescript) => {
|
|
49
60
|
switch (sourceKey) {
|
|
50
|
-
case
|
|
51
|
-
return [
|
|
52
|
-
case
|
|
53
|
-
return [
|
|
54
|
-
case
|
|
55
|
-
return [
|
|
56
|
-
case
|
|
57
|
-
return [
|
|
61
|
+
case "vue":
|
|
62
|
+
return ["vue"];
|
|
63
|
+
case "svelte":
|
|
64
|
+
return ["svelte"];
|
|
65
|
+
case "angular":
|
|
66
|
+
return ["component.ts"];
|
|
67
|
+
case "webcomponent":
|
|
68
|
+
return ["ts"];
|
|
58
69
|
default: // react
|
|
59
|
-
return typescript ? [
|
|
70
|
+
return typescript ? ["tsx", "jsx"] : ["jsx", "tsx"];
|
|
60
71
|
}
|
|
61
72
|
};
|
|
62
73
|
// JS Framework config (React, Vue, Svelte, Angular, Web Components)
|
|
@@ -67,23 +78,34 @@ function generateConfig(project) {
|
|
|
67
78
|
if (sourceKey && !addedSourceKeys.has(sourceKey)) {
|
|
68
79
|
addedSourceKeys.add(sourceKey);
|
|
69
80
|
const extensions = getExtensions(sourceKey, framework.typescript);
|
|
70
|
-
const jsComponents = project.components.filter(c => c.type ===
|
|
81
|
+
const jsComponents = project.components.filter((c) => c.type === "jsx" ||
|
|
82
|
+
c.type === "vue" ||
|
|
83
|
+
c.type === "svelte" ||
|
|
84
|
+
!c.type);
|
|
71
85
|
let includePatterns;
|
|
72
86
|
if (jsComponents.length > 0) {
|
|
73
|
-
includePatterns = jsComponents.flatMap(c => extensions.map(ext => `${c.path}/**/*.${ext}`));
|
|
87
|
+
includePatterns = jsComponents.flatMap((c) => extensions.map((ext) => `${c.path}/**/*.${ext}`));
|
|
74
88
|
}
|
|
75
89
|
else {
|
|
76
|
-
|
|
90
|
+
// Use default patterns, but expand for monorepo if detected
|
|
91
|
+
const defaultPatterns = extensions.map((ext) => `src/**/*.${ext}`);
|
|
92
|
+
if (monorepoConfig.type) {
|
|
93
|
+
const expanded = expandPatternsForMonorepo(defaultPatterns, monorepoConfig);
|
|
94
|
+
includePatterns = expanded.allPatterns;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
includePatterns = defaultPatterns;
|
|
98
|
+
}
|
|
77
99
|
}
|
|
78
100
|
lines.push(` ${sourceKey}: {`);
|
|
79
101
|
lines.push(` enabled: true,`);
|
|
80
|
-
lines.push(` include: [${includePatterns.map((p) => `'${p}'`).join(
|
|
102
|
+
lines.push(` include: [${includePatterns.map((p) => `'${p}'`).join(", ")}],`);
|
|
81
103
|
lines.push(` exclude: ['**/*.test.*', '**/*.spec.*', '**/*.stories.*'],`);
|
|
82
104
|
if (project.designSystem) {
|
|
83
105
|
lines.push(` designSystemPackage: '${project.designSystem.package}',`);
|
|
84
106
|
}
|
|
85
|
-
if (sourceKey ===
|
|
86
|
-
const wcFramework = framework.name ===
|
|
107
|
+
if (sourceKey === "webcomponent") {
|
|
108
|
+
const wcFramework = framework.name === "lit" ? "lit" : "stencil";
|
|
87
109
|
lines.push(` framework: '${wcFramework}',`);
|
|
88
110
|
}
|
|
89
111
|
lines.push(` },`);
|
|
@@ -91,40 +113,97 @@ function generateConfig(project) {
|
|
|
91
113
|
}
|
|
92
114
|
// Server-side / template-based framework config
|
|
93
115
|
const serverFrameworks = [
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
"php",
|
|
117
|
+
"laravel",
|
|
118
|
+
"symfony",
|
|
119
|
+
"rails",
|
|
120
|
+
"django",
|
|
121
|
+
"flask",
|
|
122
|
+
"fastapi",
|
|
123
|
+
"express",
|
|
124
|
+
"nestjs",
|
|
125
|
+
"spring",
|
|
126
|
+
"aspnet",
|
|
127
|
+
"go",
|
|
128
|
+
"hugo",
|
|
129
|
+
"jekyll",
|
|
130
|
+
"eleventy",
|
|
101
131
|
];
|
|
102
132
|
// Map framework to template type
|
|
103
133
|
const getTemplateType = (frameworkName, componentType) => {
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
134
|
+
// Return component type directly if it's a known template type
|
|
135
|
+
const knownTypes = [
|
|
136
|
+
// Server-side templates
|
|
137
|
+
"blade", "erb", "twig", "njk", "razor", "hbs", "mustache",
|
|
138
|
+
"ejs", "pug", "liquid", "slim", "haml", "jinja", "django",
|
|
139
|
+
"thymeleaf", "freemarker", "go-template", "edge", "eta", "heex",
|
|
140
|
+
"velocity", "xslt",
|
|
141
|
+
// JS frameworks
|
|
142
|
+
"astro", "solid", "qwik", "marko", "lit", "fast", "angular",
|
|
143
|
+
"stencil", "alpine", "htmx",
|
|
144
|
+
// Static site generators
|
|
145
|
+
"hugo", "jekyll", "eleventy", "shopify",
|
|
146
|
+
// Documentation
|
|
147
|
+
"markdown", "mdx", "asciidoc",
|
|
148
|
+
// Graphics
|
|
149
|
+
"svg",
|
|
150
|
+
// Data templates
|
|
151
|
+
"yaml-template", "json-template"
|
|
152
|
+
];
|
|
153
|
+
if (componentType && knownTypes.includes(componentType)) {
|
|
154
|
+
return componentType;
|
|
155
|
+
}
|
|
112
156
|
// Framework-based defaults
|
|
113
|
-
if (frameworkName ===
|
|
114
|
-
return
|
|
115
|
-
if (frameworkName ===
|
|
116
|
-
return
|
|
117
|
-
if (frameworkName ===
|
|
118
|
-
return
|
|
119
|
-
if (frameworkName ===
|
|
120
|
-
return
|
|
121
|
-
|
|
157
|
+
if (frameworkName === "laravel")
|
|
158
|
+
return "blade";
|
|
159
|
+
if (frameworkName === "rails")
|
|
160
|
+
return "erb";
|
|
161
|
+
if (frameworkName === "symfony")
|
|
162
|
+
return "twig";
|
|
163
|
+
if (frameworkName === "eleventy")
|
|
164
|
+
return "eleventy";
|
|
165
|
+
if (frameworkName === "aspnet")
|
|
166
|
+
return "razor";
|
|
167
|
+
if (frameworkName === "express")
|
|
168
|
+
return "ejs";
|
|
169
|
+
if (frameworkName === "flask")
|
|
170
|
+
return "jinja";
|
|
171
|
+
if (frameworkName === "django")
|
|
172
|
+
return "django";
|
|
173
|
+
if (frameworkName === "spring")
|
|
174
|
+
return "thymeleaf";
|
|
175
|
+
if (frameworkName === "go")
|
|
176
|
+
return "go-template";
|
|
177
|
+
if (frameworkName === "astro")
|
|
178
|
+
return "astro";
|
|
179
|
+
if (frameworkName === "hugo")
|
|
180
|
+
return "hugo";
|
|
181
|
+
if (frameworkName === "jekyll")
|
|
182
|
+
return "jekyll";
|
|
183
|
+
return "html";
|
|
122
184
|
};
|
|
123
185
|
// Check if any framework is a server-side framework
|
|
124
|
-
const serverFramework = project.frameworks.find(f => serverFrameworks.includes(f.name));
|
|
186
|
+
const serverFramework = project.frameworks.find((f) => serverFrameworks.includes(f.name));
|
|
125
187
|
if (serverFramework) {
|
|
126
|
-
const
|
|
127
|
-
|
|
188
|
+
const templateTypes = [
|
|
189
|
+
// Server-side templates
|
|
190
|
+
"php", "blade", "erb", "twig", "html", "njk", "razor", "hbs",
|
|
191
|
+
"mustache", "ejs", "pug", "liquid", "slim", "haml", "jinja",
|
|
192
|
+
"django", "thymeleaf", "freemarker", "go-template", "edge",
|
|
193
|
+
"eta", "heex", "velocity", "xslt",
|
|
194
|
+
// JS frameworks
|
|
195
|
+
"astro", "solid", "qwik", "marko", "lit", "fast", "angular",
|
|
196
|
+
"stencil", "alpine", "htmx",
|
|
197
|
+
// Static site generators
|
|
198
|
+
"hugo", "jekyll", "eleventy", "shopify",
|
|
199
|
+
// Documentation
|
|
200
|
+
"markdown", "mdx", "asciidoc",
|
|
201
|
+
// Graphics
|
|
202
|
+
"svg",
|
|
203
|
+
// Data templates
|
|
204
|
+
"yaml-template", "json-template"
|
|
205
|
+
];
|
|
206
|
+
const templateComponents = project.components.filter((c) => c.type && templateTypes.includes(c.type));
|
|
128
207
|
if (templateComponents.length > 0) {
|
|
129
208
|
// Use the first component's type to determine template type
|
|
130
209
|
const templateType = getTemplateType(serverFramework.name, templateComponents[0]?.type);
|
|
@@ -146,8 +225,8 @@ function generateConfig(project) {
|
|
|
146
225
|
lines.push(` },`);
|
|
147
226
|
}
|
|
148
227
|
// Token files config
|
|
149
|
-
const tokenFiles = project.tokens.filter((t) => t.type !==
|
|
150
|
-
const hasTailwind = project.tokens.some((t) => t.type ===
|
|
228
|
+
const tokenFiles = project.tokens.filter((t) => t.type !== "tailwind");
|
|
229
|
+
const hasTailwind = project.tokens.some((t) => t.type === "tailwind");
|
|
151
230
|
if (tokenFiles.length > 0 || hasTailwind) {
|
|
152
231
|
lines.push(` tokens: {`);
|
|
153
232
|
lines.push(` enabled: true,`);
|
|
@@ -173,66 +252,84 @@ function generateConfig(project) {
|
|
|
173
252
|
lines.push(` },`);
|
|
174
253
|
lines.push(`};`);
|
|
175
254
|
lines.push(``);
|
|
176
|
-
return lines.join(
|
|
255
|
+
return lines.join("\n");
|
|
177
256
|
}
|
|
178
257
|
function printDetectionResults(project) {
|
|
179
|
-
console.log(
|
|
180
|
-
console.log(chalk.bold(
|
|
258
|
+
console.log("");
|
|
259
|
+
console.log(chalk.bold(" Detected:"));
|
|
181
260
|
const frameworkNames = {
|
|
182
261
|
// JS frameworks
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
262
|
+
react: "React",
|
|
263
|
+
vue: "Vue",
|
|
264
|
+
svelte: "Svelte",
|
|
265
|
+
angular: "Angular",
|
|
266
|
+
solid: "Solid",
|
|
267
|
+
preact: "Preact",
|
|
189
268
|
// Meta-frameworks
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
269
|
+
nextjs: "Next.js",
|
|
270
|
+
nuxt: "Nuxt",
|
|
271
|
+
astro: "Astro",
|
|
272
|
+
remix: "Remix",
|
|
273
|
+
sveltekit: "SvelteKit",
|
|
274
|
+
gatsby: "Gatsby",
|
|
196
275
|
// Mobile
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
276
|
+
"react-native": "React Native",
|
|
277
|
+
flutter: "Flutter",
|
|
278
|
+
expo: "Expo",
|
|
200
279
|
// Web Components
|
|
201
|
-
|
|
202
|
-
|
|
280
|
+
lit: "Lit",
|
|
281
|
+
stencil: "Stencil",
|
|
203
282
|
// Server-side
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
283
|
+
php: "PHP",
|
|
284
|
+
laravel: "Laravel",
|
|
285
|
+
symfony: "Symfony",
|
|
286
|
+
rails: "Ruby on Rails",
|
|
287
|
+
django: "Django",
|
|
288
|
+
flask: "Flask",
|
|
289
|
+
fastapi: "FastAPI",
|
|
290
|
+
express: "Express",
|
|
291
|
+
nestjs: "NestJS",
|
|
292
|
+
spring: "Spring Boot",
|
|
293
|
+
aspnet: "ASP.NET",
|
|
294
|
+
go: "Go",
|
|
216
295
|
// Static site generators
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
296
|
+
hugo: "Hugo",
|
|
297
|
+
jekyll: "Jekyll",
|
|
298
|
+
eleventy: "Eleventy",
|
|
220
299
|
};
|
|
221
300
|
// Frameworks - show all detected
|
|
222
301
|
if (project.frameworks.length > 0) {
|
|
223
302
|
// Show warning if multiple UI frameworks detected (framework sprawl)
|
|
224
|
-
const uiFrameworks = [
|
|
225
|
-
|
|
226
|
-
|
|
303
|
+
const uiFrameworks = [
|
|
304
|
+
"react",
|
|
305
|
+
"vue",
|
|
306
|
+
"svelte",
|
|
307
|
+
"angular",
|
|
308
|
+
"solid",
|
|
309
|
+
"preact",
|
|
310
|
+
"lit",
|
|
311
|
+
"stencil",
|
|
312
|
+
"nextjs",
|
|
313
|
+
"nuxt",
|
|
314
|
+
"astro",
|
|
315
|
+
"remix",
|
|
316
|
+
"sveltekit",
|
|
317
|
+
"gatsby",
|
|
318
|
+
"react-native",
|
|
319
|
+
"expo",
|
|
320
|
+
"flutter",
|
|
321
|
+
];
|
|
322
|
+
const uiCount = project.frameworks.filter((f) => uiFrameworks.includes(f.name)).length;
|
|
227
323
|
if (uiCount > 1) {
|
|
228
|
-
console.log(chalk.yellow(
|
|
324
|
+
console.log(chalk.yellow(" ⚠ ") +
|
|
325
|
+
chalk.yellow.bold("Multiple UI frameworks detected (framework sprawl)"));
|
|
229
326
|
}
|
|
230
327
|
for (const framework of project.frameworks) {
|
|
231
|
-
const ts = framework.typescript ?
|
|
328
|
+
const ts = framework.typescript ? " + TypeScript" : "";
|
|
232
329
|
const frameworkName = frameworkNames[framework.name] || capitalize(framework.name);
|
|
233
|
-
const meta = framework.meta ? chalk.dim(` (${framework.meta})`) :
|
|
234
|
-
const version = framework.version !==
|
|
235
|
-
console.log(chalk.green(
|
|
330
|
+
const meta = framework.meta ? chalk.dim(` (${framework.meta})`) : "";
|
|
331
|
+
const version = framework.version !== "unknown" ? ` ${framework.version}` : "";
|
|
332
|
+
console.log(chalk.green(" ✓ ") +
|
|
236
333
|
chalk.bold(frameworkName) +
|
|
237
334
|
ts +
|
|
238
335
|
meta +
|
|
@@ -243,18 +340,66 @@ function printDetectionResults(project) {
|
|
|
243
340
|
if (project.components.length > 0) {
|
|
244
341
|
for (const comp of project.components) {
|
|
245
342
|
const typeLabels = {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
343
|
+
// JS frameworks
|
|
344
|
+
jsx: "component files",
|
|
345
|
+
tsx: "TypeScript components",
|
|
346
|
+
vue: "Vue components",
|
|
347
|
+
svelte: "Svelte components",
|
|
348
|
+
astro: "Astro components",
|
|
349
|
+
solid: "Solid components",
|
|
350
|
+
qwik: "Qwik components",
|
|
351
|
+
marko: "Marko components",
|
|
352
|
+
lit: "Lit elements",
|
|
353
|
+
fast: "FAST elements",
|
|
354
|
+
// Server-side templates
|
|
355
|
+
php: "PHP templates",
|
|
356
|
+
blade: "Blade templates",
|
|
357
|
+
erb: "ERB templates",
|
|
358
|
+
twig: "Twig templates",
|
|
359
|
+
html: "HTML templates",
|
|
360
|
+
njk: "Nunjucks templates",
|
|
361
|
+
razor: "Razor views",
|
|
362
|
+
hbs: "Handlebars templates",
|
|
363
|
+
mustache: "Mustache templates",
|
|
364
|
+
ejs: "EJS templates",
|
|
365
|
+
pug: "Pug templates",
|
|
366
|
+
liquid: "Liquid templates",
|
|
367
|
+
slim: "Slim templates",
|
|
368
|
+
haml: "Haml templates",
|
|
369
|
+
jinja: "Jinja templates",
|
|
370
|
+
django: "Django templates",
|
|
371
|
+
thymeleaf: "Thymeleaf templates",
|
|
372
|
+
freemarker: "Freemarker templates",
|
|
373
|
+
velocity: "Velocity templates",
|
|
374
|
+
"go-template": "Go templates",
|
|
375
|
+
edge: "Edge.js templates",
|
|
376
|
+
eta: "Eta templates",
|
|
377
|
+
heex: "HEEx templates",
|
|
378
|
+
xslt: "XSLT stylesheets",
|
|
379
|
+
// Static site generators
|
|
380
|
+
hugo: "Hugo layouts",
|
|
381
|
+
jekyll: "Jekyll layouts",
|
|
382
|
+
eleventy: "Eleventy templates",
|
|
383
|
+
shopify: "Shopify templates",
|
|
384
|
+
// Documentation
|
|
385
|
+
markdown: "Markdown files",
|
|
386
|
+
mdx: "MDX files",
|
|
387
|
+
asciidoc: "AsciiDoc files",
|
|
388
|
+
// Data templates
|
|
389
|
+
"yaml-template": "YAML templates",
|
|
390
|
+
"json-template": "JSON templates",
|
|
391
|
+
// Additional JS frameworks
|
|
392
|
+
angular: "Angular components",
|
|
393
|
+
stencil: "Stencil components",
|
|
394
|
+
alpine: "Alpine.js templates",
|
|
395
|
+
htmx: "HTMX templates",
|
|
396
|
+
// Graphics
|
|
397
|
+
svg: "SVG components",
|
|
255
398
|
};
|
|
256
|
-
const typeLabel = comp.type
|
|
257
|
-
|
|
399
|
+
const typeLabel = comp.type
|
|
400
|
+
? typeLabels[comp.type] || "template files"
|
|
401
|
+
: "component files";
|
|
402
|
+
console.log(chalk.green(" ✓ ") +
|
|
258
403
|
`${comp.fileCount} ${typeLabel} in ` +
|
|
259
404
|
chalk.cyan(comp.path));
|
|
260
405
|
}
|
|
@@ -262,36 +407,47 @@ function printDetectionResults(project) {
|
|
|
262
407
|
// Tokens
|
|
263
408
|
if (project.tokens.length > 0) {
|
|
264
409
|
for (const token of project.tokens) {
|
|
265
|
-
|
|
266
|
-
console.log(chalk.green(icon) + `${token.name}: ` + chalk.cyan(token.path));
|
|
410
|
+
console.log(chalk.green(" ✓ ") + `${token.name}: ` + chalk.cyan(token.path));
|
|
267
411
|
}
|
|
268
412
|
}
|
|
269
413
|
// Storybook
|
|
270
414
|
if (project.storybook) {
|
|
271
|
-
const version = project.storybook.version
|
|
272
|
-
|
|
415
|
+
const version = project.storybook.version
|
|
416
|
+
? ` (${project.storybook.version})`
|
|
417
|
+
: "";
|
|
418
|
+
console.log(chalk.green(" ✓ ") + `Storybook` + chalk.dim(version));
|
|
273
419
|
}
|
|
274
420
|
// Design system
|
|
275
421
|
if (project.designSystem) {
|
|
276
|
-
console.log(chalk.green(
|
|
422
|
+
console.log(chalk.green(" ✓ ") +
|
|
277
423
|
`Design system: ` +
|
|
278
424
|
chalk.cyan(project.designSystem.package));
|
|
279
425
|
}
|
|
280
426
|
// Monorepo
|
|
281
427
|
if (project.monorepo) {
|
|
282
|
-
|
|
428
|
+
// Show basic monorepo info
|
|
429
|
+
console.log(chalk.green(" ✓ ") +
|
|
283
430
|
capitalize(project.monorepo.type) +
|
|
284
431
|
` monorepo (${project.monorepo.packages.length} packages)`);
|
|
432
|
+
// Show monorepo component paths if detected
|
|
433
|
+
const monorepoComponents = project.components.filter((c) => c.path.startsWith("packages/") ||
|
|
434
|
+
c.path.startsWith("apps/") ||
|
|
435
|
+
c.path.startsWith("libs/") ||
|
|
436
|
+
c.path.startsWith("modules/"));
|
|
437
|
+
if (monorepoComponents.length > 0) {
|
|
438
|
+
console.log(chalk.dim(" ") +
|
|
439
|
+
chalk.dim(`Scanning: ${monorepoComponents.map((c) => c.path).slice(0, 3).join(", ")}${monorepoComponents.length > 3 ? ` +${monorepoComponents.length - 3} more` : ""}`));
|
|
440
|
+
}
|
|
285
441
|
}
|
|
286
442
|
// Nothing found
|
|
287
443
|
if (project.frameworks.length === 0 &&
|
|
288
444
|
project.components.length === 0 &&
|
|
289
445
|
project.tokens.length === 0 &&
|
|
290
446
|
!project.storybook) {
|
|
291
|
-
console.log(chalk.yellow(
|
|
292
|
-
console.log(chalk.dim(
|
|
447
|
+
console.log(chalk.yellow(" ⚠ ") + "No sources auto-detected");
|
|
448
|
+
console.log(chalk.dim(" You can manually configure sources in buoy.config.mjs"));
|
|
293
449
|
}
|
|
294
|
-
console.log(
|
|
450
|
+
console.log("");
|
|
295
451
|
}
|
|
296
452
|
function capitalize(s) {
|
|
297
453
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
@@ -301,35 +457,36 @@ async function promptConfirm(message, defaultValue = true) {
|
|
|
301
457
|
input: process.stdin,
|
|
302
458
|
output: process.stdout,
|
|
303
459
|
});
|
|
304
|
-
const suffix = defaultValue ?
|
|
460
|
+
const suffix = defaultValue ? "[Y/n]" : "[y/N]";
|
|
305
461
|
return new Promise((resolve) => {
|
|
306
462
|
rl.question(`${message} ${suffix} `, (answer) => {
|
|
307
463
|
rl.close();
|
|
308
464
|
const trimmed = answer.trim().toLowerCase();
|
|
309
|
-
if (trimmed ===
|
|
465
|
+
if (trimmed === "") {
|
|
310
466
|
resolve(defaultValue);
|
|
311
467
|
}
|
|
312
468
|
else {
|
|
313
|
-
resolve(trimmed ===
|
|
469
|
+
resolve(trimmed === "y" || trimmed === "yes");
|
|
314
470
|
}
|
|
315
471
|
});
|
|
316
472
|
});
|
|
317
473
|
}
|
|
318
474
|
export function createInitCommand() {
|
|
319
|
-
const cmd = new Command(
|
|
320
|
-
.description(
|
|
321
|
-
.option(
|
|
322
|
-
.option(
|
|
323
|
-
.option(
|
|
324
|
-
.option(
|
|
325
|
-
.option(
|
|
475
|
+
const cmd = new Command("init")
|
|
476
|
+
.description("Initialize Buoy configuration in the current project")
|
|
477
|
+
.option("-f, --force", "Overwrite existing configuration")
|
|
478
|
+
.option("-n, --name <name>", "Project name")
|
|
479
|
+
.option("--skip-detect", "Skip auto-detection and create minimal config")
|
|
480
|
+
.option("-y, --yes", "Auto-install recommended plugins without prompting")
|
|
481
|
+
.option("--no-install", "Skip plugin installation prompts")
|
|
482
|
+
.option("--hooks", "Setup pre-commit hook for drift checking")
|
|
326
483
|
.action(async (options) => {
|
|
327
484
|
const cwd = process.cwd();
|
|
328
|
-
const configPath = resolve(cwd,
|
|
485
|
+
const configPath = resolve(cwd, "buoy.config.mjs");
|
|
329
486
|
// Check if config already exists
|
|
330
487
|
if (existsSync(configPath) && !options.force) {
|
|
331
488
|
warning(`Configuration already exists at ${configPath}`);
|
|
332
|
-
info(
|
|
489
|
+
info("Use --force to overwrite");
|
|
333
490
|
return;
|
|
334
491
|
}
|
|
335
492
|
let project;
|
|
@@ -350,7 +507,7 @@ export function createInitCommand() {
|
|
|
350
507
|
}
|
|
351
508
|
else {
|
|
352
509
|
// Run auto-detection
|
|
353
|
-
const spinner = ora(
|
|
510
|
+
const spinner = ora("Scanning project...").start();
|
|
354
511
|
try {
|
|
355
512
|
const detector = new ProjectDetector(cwd);
|
|
356
513
|
project = await detector.detect();
|
|
@@ -361,122 +518,132 @@ export function createInitCommand() {
|
|
|
361
518
|
printDetectionResults(project);
|
|
362
519
|
}
|
|
363
520
|
catch (err) {
|
|
364
|
-
spinner.fail(
|
|
521
|
+
spinner.fail("Detection failed");
|
|
365
522
|
const message = err instanceof Error ? err.message : String(err);
|
|
366
523
|
error(message);
|
|
367
524
|
process.exit(1);
|
|
368
525
|
}
|
|
369
526
|
}
|
|
370
|
-
//
|
|
527
|
+
// Show detected frameworks and scanners
|
|
371
528
|
const detectedFrameworks = await detectFrameworks(cwd);
|
|
372
|
-
const installedPlugins = await discoverPlugins();
|
|
373
529
|
if (detectedFrameworks.length > 0) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if (fw.matchedFiles && fw.matchedFiles.length > 0) {
|
|
389
|
-
console.log(` ${chalk.dim('│')} ${chalk.white('Detected:')} ${detectsLabel}`);
|
|
390
|
-
const filesToShow = fw.matchedFiles.slice(0, 3);
|
|
391
|
-
for (const file of filesToShow) {
|
|
392
|
-
console.log(` ${chalk.dim('│')} ${chalk.dim('•')} ${chalk.cyan(file)}`);
|
|
393
|
-
}
|
|
394
|
-
if (fw.matchedFiles.length > 3) {
|
|
395
|
-
console.log(` ${chalk.dim('│')} ${chalk.dim(` ...and ${fw.matchedFiles.length - 3} more`)}`);
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
// Package-based detection
|
|
400
|
-
console.log(` ${chalk.dim('│')} ${chalk.white('Detected:')} ${detectsLabel} ${chalk.dim(`(${fw.evidence.toLowerCase()})`)}`);
|
|
401
|
-
}
|
|
402
|
-
console.log(` ${chalk.dim('│')}`);
|
|
403
|
-
// What the plugin does
|
|
404
|
-
if (pluginInfo?.description) {
|
|
405
|
-
console.log(` ${chalk.dim('│')} ${chalk.white('What it does:')}`);
|
|
406
|
-
// Word wrap description at ~60 chars
|
|
407
|
-
const words = pluginInfo.description.split(' ');
|
|
408
|
-
let line = '';
|
|
409
|
-
for (const word of words) {
|
|
410
|
-
if (line.length + word.length > 55) {
|
|
411
|
-
console.log(` ${chalk.dim('│')} ${chalk.dim(line.trim())}`);
|
|
412
|
-
line = word + ' ';
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
line += word + ' ';
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
if (line.trim()) {
|
|
419
|
-
console.log(` ${chalk.dim('│')} ${chalk.dim(line.trim())}`);
|
|
420
|
-
}
|
|
530
|
+
// Separate built-in scanners from optional plugins
|
|
531
|
+
const builtIn = detectedFrameworks.filter((fw) => fw.scanner);
|
|
532
|
+
const optionalPlugins = detectedFrameworks.filter((fw) => fw.plugin && !fw.scanner);
|
|
533
|
+
// Show built-in scanners (no install needed)
|
|
534
|
+
if (builtIn.length > 0) {
|
|
535
|
+
console.log(chalk.bold(" Built-in Scanners") +
|
|
536
|
+
chalk.dim(" (no install needed)"));
|
|
537
|
+
console.log("");
|
|
538
|
+
for (const fw of builtIn) {
|
|
539
|
+
const scannerInfo = BUILTIN_SCANNERS[fw.scanner];
|
|
540
|
+
const scannerLabel = scannerInfo?.description || capitalize(fw.name);
|
|
541
|
+
console.log(` ${chalk.green("✓")} ${chalk.cyan.bold(scannerLabel)}`);
|
|
542
|
+
console.log(` ${chalk.dim(fw.evidence)}`);
|
|
543
|
+
console.log("");
|
|
421
544
|
}
|
|
422
|
-
// Footer with install command or ready status
|
|
423
|
-
console.log(` ${chalk.dim('│')}`);
|
|
424
|
-
if (installed) {
|
|
425
|
-
console.log(` ${chalk.dim('└─')} ${chalk.green('Ready to use')}`);
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
console.log(` ${chalk.dim('└─')} ${chalk.dim(getPluginInstallCommand([fw.plugin]))}`);
|
|
429
|
-
}
|
|
430
|
-
console.log('');
|
|
431
545
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
.
|
|
435
|
-
.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
// Only prompt if --no-install was not passed and stdin is a TTY
|
|
449
|
-
if (process.stdin.isTTY) {
|
|
450
|
-
shouldInstall = await promptConfirm('Install recommended plugins now?', true);
|
|
546
|
+
// Show optional plugins (need install)
|
|
547
|
+
if (optionalPlugins.length > 0) {
|
|
548
|
+
console.log(chalk.bold(" Optional Plugins"));
|
|
549
|
+
console.log("");
|
|
550
|
+
for (const fw of optionalPlugins) {
|
|
551
|
+
const pluginInfo = PLUGIN_INFO[fw.plugin];
|
|
552
|
+
const pluginName = pluginInfo?.name || `@buoy-design/plugin-${fw.plugin}`;
|
|
553
|
+
console.log(` ${chalk.dim("┌")} ${chalk.cyan.bold(pluginName)}`);
|
|
554
|
+
console.log(` ${chalk.dim("│")}`);
|
|
555
|
+
// What was detected
|
|
556
|
+
const detectsLabel = pluginInfo?.detects || capitalize(fw.name);
|
|
557
|
+
console.log(` ${chalk.dim("│")} ${chalk.white("Detected:")} ${detectsLabel} ${chalk.dim(`(${fw.evidence.toLowerCase()})`)}`);
|
|
558
|
+
console.log(` ${chalk.dim("│")}`);
|
|
559
|
+
// What the plugin does
|
|
560
|
+
if (pluginInfo?.description) {
|
|
561
|
+
console.log(` ${chalk.dim("│")} ${chalk.dim(pluginInfo.description)}`);
|
|
451
562
|
}
|
|
563
|
+
console.log(` ${chalk.dim("└─")} ${chalk.dim(getPluginInstallCommand([fw.plugin]))}`);
|
|
564
|
+
console.log("");
|
|
452
565
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
566
|
+
const missingPlugins = optionalPlugins
|
|
567
|
+
.map((fw) => fw.plugin)
|
|
568
|
+
.filter((plugin, index, self) => self.indexOf(plugin) === index);
|
|
569
|
+
if (missingPlugins.length > 0) {
|
|
570
|
+
console.log(chalk.dim(" " + "─".repeat(65)));
|
|
571
|
+
console.log("");
|
|
572
|
+
console.log(chalk.bold(" Install all optional plugins:"));
|
|
573
|
+
console.log(` ${chalk.cyan(getPluginInstallCommand(missingPlugins))}`);
|
|
574
|
+
console.log("");
|
|
575
|
+
// Determine if we should install plugins
|
|
576
|
+
let shouldInstall = false;
|
|
577
|
+
if (options.yes) {
|
|
578
|
+
shouldInstall = true;
|
|
579
|
+
}
|
|
580
|
+
else if (options.install !== false) {
|
|
581
|
+
// Only prompt if --no-install was not passed and stdin is a TTY
|
|
582
|
+
if (process.stdin.isTTY) {
|
|
583
|
+
shouldInstall = await promptConfirm("Install optional plugins now?", true);
|
|
584
|
+
}
|
|
460
585
|
}
|
|
461
|
-
|
|
462
|
-
|
|
586
|
+
if (shouldInstall) {
|
|
587
|
+
const { execSync } = await import("node:child_process");
|
|
588
|
+
console.log("");
|
|
589
|
+
console.log("Installing plugins...");
|
|
590
|
+
try {
|
|
591
|
+
execSync(getPluginInstallCommand(missingPlugins), {
|
|
592
|
+
stdio: "inherit",
|
|
593
|
+
});
|
|
594
|
+
success("Plugins installed successfully");
|
|
595
|
+
}
|
|
596
|
+
catch {
|
|
597
|
+
warning("Plugin installation failed. You can install manually with the command above.");
|
|
598
|
+
}
|
|
463
599
|
}
|
|
464
600
|
}
|
|
465
601
|
}
|
|
466
|
-
console.log(
|
|
602
|
+
console.log("");
|
|
467
603
|
}
|
|
468
604
|
// Generate and write config
|
|
469
605
|
const content = generateConfig(project);
|
|
470
606
|
try {
|
|
471
|
-
writeFileSync(configPath, content,
|
|
607
|
+
writeFileSync(configPath, content, "utf-8");
|
|
472
608
|
success(`Created buoy.config.mjs`);
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
609
|
+
// Setup hooks if --hooks flag is provided
|
|
610
|
+
if (options.hooks) {
|
|
611
|
+
console.log("");
|
|
612
|
+
const hookSystem = detectHookSystem(cwd);
|
|
613
|
+
if (hookSystem) {
|
|
614
|
+
info(`Detected hook system: ${hookSystem}`);
|
|
615
|
+
const hookResult = setupHooks(cwd);
|
|
616
|
+
if (hookResult.success) {
|
|
617
|
+
success(hookResult.message);
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
warning(hookResult.message);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
// No hook system detected, create standalone hook
|
|
625
|
+
const standaloneResult = generateStandaloneHook(cwd);
|
|
626
|
+
if (standaloneResult.success) {
|
|
627
|
+
success(standaloneResult.message);
|
|
628
|
+
info("To use this hook, copy it to .git/hooks/pre-commit or configure your hook system");
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
warning(standaloneResult.message);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
console.log("");
|
|
636
|
+
info("Next steps:");
|
|
637
|
+
info(" 1. Run " + chalk.cyan("buoy scan") + " to scan your codebase");
|
|
638
|
+
info(" 2. Run " + chalk.cyan("buoy drift check") + " to detect drift");
|
|
639
|
+
if (!options.hooks) {
|
|
640
|
+
info(" 3. Run " +
|
|
641
|
+
chalk.cyan("buoy init --hooks") +
|
|
642
|
+
" to setup pre-commit hooks");
|
|
643
|
+
}
|
|
477
644
|
if (!project.storybook) {
|
|
478
|
-
console.log(
|
|
479
|
-
info(chalk.dim(
|
|
645
|
+
console.log("");
|
|
646
|
+
info(chalk.dim("Optional: Connect Figma by adding your API key to the config"));
|
|
480
647
|
}
|
|
481
648
|
}
|
|
482
649
|
catch (err) {
|