nextworks 0.2.0-alpha.2 → 0.2.0-alpha.20
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/README.md +280 -228
- package/dist/cli_manifests/blocks_manifest.json +193 -194
- package/dist/commands/blocks.d.ts +3 -0
- package/dist/commands/blocks.d.ts.map +1 -1
- package/dist/commands/blocks.js +128 -19
- package/dist/commands/blocks.js.map +1 -1
- package/dist/commands/doctor.d.ts +136 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +696 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/remove-blocks.d.ts +4 -1
- package/dist/commands/remove-blocks.d.ts.map +1 -1
- package/dist/commands/remove-blocks.js +24 -6
- package/dist/commands/remove-blocks.js.map +1 -1
- package/dist/index.js +125 -4
- package/dist/index.js.map +1 -1
- package/dist/kits/blocks/.nextworks/docs/BLOCKS_QUICKSTART.md +104 -194
- package/dist/kits/blocks/.nextworks/docs/BLOCKS_README.md +115 -75
- package/dist/kits/blocks/.nextworks/docs/THEME_GUIDE.md +269 -251
- package/dist/kits/blocks/app/templates/digitalagency/PresetThemeVars.tsx +80 -80
- package/dist/kits/blocks/app/templates/digitalagency/README.md +42 -36
- package/dist/kits/blocks/app/templates/digitalagency/components/About.tsx +71 -99
- package/dist/kits/blocks/app/templates/digitalagency/components/CTA.tsx +40 -74
- package/dist/kits/blocks/app/templates/digitalagency/components/Contact.tsx +123 -227
- package/dist/kits/blocks/app/templates/digitalagency/components/Footer.tsx +89 -89
- package/dist/kits/blocks/app/templates/digitalagency/components/Hero.tsx +83 -90
- package/dist/kits/blocks/app/templates/digitalagency/components/Navbar.tsx +121 -168
- package/dist/kits/blocks/app/templates/digitalagency/components/NetworkPattern.tsx +288 -297
- package/dist/kits/blocks/app/templates/digitalagency/components/Portfolio.tsx +157 -157
- package/dist/kits/blocks/app/templates/digitalagency/components/Pricing.tsx +114 -114
- package/dist/kits/blocks/app/templates/digitalagency/components/Process.tsx +59 -59
- package/dist/kits/blocks/app/templates/digitalagency/components/Services.tsx +55 -55
- package/dist/kits/blocks/app/templates/digitalagency/components/Team.tsx +28 -28
- package/dist/kits/blocks/app/templates/digitalagency/components/Testimonials.tsx +65 -65
- package/dist/kits/blocks/app/templates/digitalagency/page.tsx +38 -38
- package/dist/kits/blocks/app/templates/gallery/PresetThemeVars.tsx +130 -85
- package/dist/kits/blocks/app/templates/gallery/page.tsx +357 -303
- package/dist/kits/blocks/app/templates/productlaunch/PresetThemeVars.tsx +75 -74
- package/dist/kits/blocks/app/templates/productlaunch/README.md +62 -55
- package/dist/kits/blocks/app/templates/productlaunch/components/About.tsx +84 -178
- package/dist/kits/blocks/app/templates/productlaunch/components/CTA.tsx +50 -93
- package/dist/kits/blocks/app/templates/productlaunch/components/Contact.tsx +231 -231
- package/dist/kits/blocks/app/templates/productlaunch/components/FAQ.tsx +86 -93
- package/dist/kits/blocks/app/templates/productlaunch/components/Features.tsx +83 -84
- package/dist/kits/blocks/app/templates/productlaunch/components/Footer.tsx +132 -132
- package/dist/kits/blocks/app/templates/productlaunch/components/Hero.tsx +88 -89
- package/dist/kits/blocks/app/templates/productlaunch/components/Navbar.tsx +116 -162
- package/dist/kits/blocks/app/templates/productlaunch/components/Pricing.tsx +106 -106
- package/dist/kits/blocks/app/templates/productlaunch/components/ProcessTimeline.tsx +110 -110
- package/dist/kits/blocks/app/templates/productlaunch/components/ServicesGrid.tsx +68 -68
- package/dist/kits/blocks/app/templates/productlaunch/components/Team.tsx +104 -104
- package/dist/kits/blocks/app/templates/productlaunch/components/Testimonials.tsx +90 -89
- package/dist/kits/blocks/app/templates/productlaunch/components/TrustBadges.tsx +76 -76
- package/dist/kits/blocks/app/templates/productlaunch/page.tsx +43 -43
- package/dist/kits/blocks/app/templates/saasdashboard/PresetThemeVars.tsx +80 -80
- package/dist/kits/blocks/app/templates/saasdashboard/README.md +44 -38
- package/dist/kits/blocks/app/templates/saasdashboard/components/Contact.tsx +129 -176
- package/dist/kits/blocks/app/templates/saasdashboard/components/Dashboard.tsx +293 -293
- package/dist/kits/blocks/app/templates/saasdashboard/components/FAQ.tsx +55 -55
- package/dist/kits/blocks/app/templates/saasdashboard/components/Features.tsx +90 -91
- package/dist/kits/blocks/app/templates/saasdashboard/components/Footer.tsx +77 -77
- package/dist/kits/blocks/app/templates/saasdashboard/components/Hero.tsx +104 -105
- package/dist/kits/blocks/app/templates/saasdashboard/components/Hero_mask.tsx +126 -127
- package/dist/kits/blocks/app/templates/saasdashboard/components/Navbar.tsx +117 -159
- package/dist/kits/blocks/app/templates/saasdashboard/components/Pricing.tsx +90 -90
- package/dist/kits/blocks/app/templates/saasdashboard/components/SmoothScroll.tsx +96 -97
- package/dist/kits/blocks/app/templates/saasdashboard/components/Testimonials.tsx +72 -72
- package/dist/kits/blocks/app/templates/saasdashboard/components/TrustBadges.tsx +53 -53
- package/dist/kits/blocks/app/templates/saasdashboard/page.tsx +39 -39
- package/dist/kits/blocks/components/enhanced-theme-provider.tsx +195 -183
- package/dist/kits/blocks/components/providers/BlocksAppProviders.tsx +27 -27
- package/dist/kits/blocks/components/sections/About.tsx +291 -291
- package/dist/kits/blocks/components/sections/CTA.tsx +257 -258
- package/dist/kits/blocks/components/sections/CommandShowcase.tsx +517 -0
- package/dist/kits/blocks/components/sections/Contact.tsx +267 -267
- package/dist/kits/blocks/components/sections/FAQ.tsx +214 -225
- package/dist/kits/blocks/components/sections/FeaturedProjectShowcase.tsx +687 -0
- package/dist/kits/blocks/components/sections/Features.tsx +268 -270
- package/dist/kits/blocks/components/sections/Footer.tsx +302 -302
- package/dist/kits/blocks/components/sections/HeroMotion.tsx +308 -308
- package/dist/kits/blocks/components/sections/HeroOverlay.tsx +358 -358
- package/dist/kits/blocks/components/sections/HeroProductDemo.tsx +246 -0
- package/dist/kits/blocks/components/sections/HeroSplit.tsx +352 -352
- package/dist/kits/blocks/components/sections/HeroWithVideo.tsx +495 -0
- package/dist/kits/blocks/components/sections/Navbar.tsx +352 -353
- package/dist/kits/blocks/components/sections/PortfolioSimple.tsx +549 -550
- package/dist/kits/blocks/components/sections/Pricing.tsx +264 -264
- package/dist/kits/blocks/components/sections/ProcessTimeline.tsx +325 -325
- package/dist/kits/blocks/components/sections/ProjectDeepDive.tsx +805 -0
- package/dist/kits/blocks/components/sections/SelectedWorkRail.tsx +485 -0
- package/dist/kits/blocks/components/sections/ServicesGrid.tsx +210 -210
- package/dist/kits/blocks/components/sections/Team.tsx +309 -309
- package/dist/kits/blocks/components/sections/Testimonials.tsx +158 -158
- package/dist/kits/blocks/components/sections/TrustBadges.tsx +162 -162
- package/dist/kits/blocks/components/sections/product-demo/ApprovalInboxPanel.tsx +128 -0
- package/dist/kits/blocks/components/sections/product-demo/DemoStage.tsx +519 -0
- package/dist/kits/blocks/components/sections/product-demo/DemoWindow.tsx +140 -0
- package/dist/kits/blocks/components/sections/product-demo/KnowledgePanel.tsx +130 -0
- package/dist/kits/blocks/components/sections/product-demo/RunConsolePanel.tsx +430 -0
- package/dist/kits/blocks/components/sections/product-demo/TaskListPanel.tsx +302 -0
- package/dist/kits/blocks/components/sections/product-demo/WorkflowStudioPanel.tsx +744 -0
- package/dist/kits/blocks/components/sections/product-demo/types.ts +262 -0
- package/dist/kits/blocks/components/theme-provider.tsx +1 -34
- package/dist/kits/blocks/components/ui/alert-dialog.tsx +134 -134
- package/dist/kits/blocks/components/ui/brand-node.tsx +121 -121
- package/dist/kits/blocks/components/ui/button.tsx +122 -122
- package/dist/kits/blocks/components/ui/card.tsx +95 -95
- package/dist/kits/blocks/components/ui/checkbox.tsx +30 -30
- package/dist/kits/blocks/components/ui/cta-button.tsx +125 -125
- package/dist/kits/blocks/components/ui/dropdown-menu.tsx +201 -201
- package/dist/kits/blocks/components/ui/feature-card.tsx +91 -91
- package/dist/kits/blocks/components/ui/input.tsx +27 -27
- package/dist/kits/blocks/components/ui/label.tsx +29 -29
- package/dist/kits/blocks/components/ui/pricing-card.tsx +120 -120
- package/dist/kits/blocks/components/ui/select.tsx +25 -25
- package/dist/kits/blocks/components/ui/skeleton.tsx +13 -13
- package/dist/kits/blocks/components/ui/table.tsx +98 -98
- package/dist/kits/blocks/components/ui/testimonial-card.tsx +108 -108
- package/dist/kits/blocks/components/ui/textarea.tsx +26 -26
- package/dist/kits/blocks/components/ui/theme-selector.tsx +243 -247
- package/dist/kits/blocks/components/ui/theme-toggle.tsx +74 -74
- package/dist/kits/blocks/components/ui/toaster.tsx +7 -7
- package/dist/kits/blocks/lib/themes.ts +400 -400
- package/dist/kits/blocks/lib/utils.ts +6 -9
- package/dist/kits/blocks/package-deps.json +40 -28
- package/dist/kits/blocks/tsconfig.json +11 -0
- package/dist/kits/blocks/tsconfig.tsbuildinfo +1 -0
- package/dist/utils/file-operations.d.ts +3 -1
- package/dist/utils/file-operations.d.ts.map +1 -1
- package/dist/utils/file-operations.js +84 -12
- package/dist/utils/file-operations.js.map +1 -1
- package/dist/utils/installation-tracker.d.ts +2 -2
- package/dist/utils/installation-tracker.d.ts.map +1 -1
- package/dist/utils/installation-tracker.js +11 -11
- package/dist/utils/installation-tracker.js.map +1 -1
- package/dist/utils/package-manager.d.ts +6 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/package-manager.js +58 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/yarn-pnp.d.ts +6 -0
- package/dist/utils/yarn-pnp.d.ts.map +1 -0
- package/dist/utils/yarn-pnp.js +39 -0
- package/dist/utils/yarn-pnp.js.map +1 -0
- package/package.json +5 -2
- package/dist/kits/blocks/notes/THEME_GUIDE.md +0 -29
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.doctor = doctor;
|
|
7
|
+
exports.formatDoctorResult = formatDoctorResult;
|
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const file_operations_1 = require("../utils/file-operations");
|
|
11
|
+
const package_manager_1 = require("../utils/package-manager");
|
|
12
|
+
const yarn_pnp_1 = require("../utils/yarn-pnp");
|
|
13
|
+
const installation_tracker_1 = require("../utils/installation-tracker");
|
|
14
|
+
const TEMPLATE_SLUGS = [
|
|
15
|
+
"productlaunch",
|
|
16
|
+
"saasdashboard",
|
|
17
|
+
"digitalagency",
|
|
18
|
+
"gallery",
|
|
19
|
+
];
|
|
20
|
+
const COLLISION_CANDIDATES = {
|
|
21
|
+
src: [
|
|
22
|
+
"src/components/app-providers.tsx",
|
|
23
|
+
"src/components/ui",
|
|
24
|
+
"src/components/sections",
|
|
25
|
+
"src/app/globals.css",
|
|
26
|
+
"src/app/tw-animate.css",
|
|
27
|
+
"src/lib/utils.ts",
|
|
28
|
+
"src/app/layout.tsx",
|
|
29
|
+
"src/pages/_app.tsx",
|
|
30
|
+
"src/pages/_document.tsx",
|
|
31
|
+
],
|
|
32
|
+
root: [
|
|
33
|
+
"components/app-providers.tsx",
|
|
34
|
+
"components/ui",
|
|
35
|
+
"components/sections",
|
|
36
|
+
"app/globals.css",
|
|
37
|
+
"app/tw-animate.css",
|
|
38
|
+
"lib/utils.ts",
|
|
39
|
+
"app/layout.tsx",
|
|
40
|
+
"pages/_app.tsx",
|
|
41
|
+
"pages/_document.tsx",
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
function hasTailwindDependency(pkg) {
|
|
45
|
+
return Boolean(pkg.dependencies?.tailwindcss || pkg.devDependencies?.tailwindcss);
|
|
46
|
+
}
|
|
47
|
+
function hasTypeScriptDependency(pkg) {
|
|
48
|
+
return Boolean(pkg.dependencies?.typescript || pkg.devDependencies?.typescript);
|
|
49
|
+
}
|
|
50
|
+
async function hasTsconfig(cwd) {
|
|
51
|
+
return (0, file_operations_1.fileExists)(path_1.default.join(cwd, "tsconfig.json"));
|
|
52
|
+
}
|
|
53
|
+
async function hasCssBasedTailwindUsage(cwd) {
|
|
54
|
+
const cssCandidates = [
|
|
55
|
+
path_1.default.join(cwd, "app", "globals.css"),
|
|
56
|
+
path_1.default.join(cwd, "src", "app", "globals.css"),
|
|
57
|
+
path_1.default.join(cwd, "styles", "globals.css"),
|
|
58
|
+
path_1.default.join(cwd, "src", "styles", "globals.css"),
|
|
59
|
+
path_1.default.join(cwd, "pages", "_app.tsx"),
|
|
60
|
+
path_1.default.join(cwd, "src", "pages", "_app.tsx"),
|
|
61
|
+
];
|
|
62
|
+
for (const candidate of cssCandidates) {
|
|
63
|
+
if (!(await (0, file_operations_1.fileExists)(candidate))) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const content = await fs_extra_1.default.readFile(candidate, "utf8");
|
|
68
|
+
if (content.includes('@import "tailwindcss"') ||
|
|
69
|
+
content.includes("@import 'tailwindcss'") ||
|
|
70
|
+
content.includes("@theme")) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const MIN_MAJOR_NODE_VERSION = 20;
|
|
81
|
+
const YARN_PNP_MESSAGE = "Set nodeLinker: node-modules in .yarnrc.yml";
|
|
82
|
+
function createInitialDoctorResult() {
|
|
83
|
+
return {
|
|
84
|
+
projectSanity: {
|
|
85
|
+
hasPackageJson: false,
|
|
86
|
+
hasNext: false,
|
|
87
|
+
projectRoot: null,
|
|
88
|
+
routerType: null,
|
|
89
|
+
projectRootMode: null,
|
|
90
|
+
},
|
|
91
|
+
environmentChecks: {
|
|
92
|
+
nodeVersion: { status: "ok", message: "" },
|
|
93
|
+
packageManager: { pm: "pnpm", installCommand: "" },
|
|
94
|
+
yarnPnPDetection: {
|
|
95
|
+
isPnP: false,
|
|
96
|
+
message: YARN_PNP_MESSAGE,
|
|
97
|
+
},
|
|
98
|
+
tailwind: {
|
|
99
|
+
hasTailwindDependency: false,
|
|
100
|
+
hasCssBasedTailwindUsage: false,
|
|
101
|
+
detected: false,
|
|
102
|
+
},
|
|
103
|
+
typescript: {
|
|
104
|
+
hasTsconfig: false,
|
|
105
|
+
hasTypeScriptDependency: false,
|
|
106
|
+
detected: false,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
projectRootWritability: {
|
|
110
|
+
path: "",
|
|
111
|
+
exists: false,
|
|
112
|
+
writable: null,
|
|
113
|
+
},
|
|
114
|
+
appProvidersShim: {
|
|
115
|
+
path: "",
|
|
116
|
+
exists: false,
|
|
117
|
+
target: null,
|
|
118
|
+
targetExists: null,
|
|
119
|
+
targetMatchesRouter: null,
|
|
120
|
+
},
|
|
121
|
+
collisions: {
|
|
122
|
+
paths: [],
|
|
123
|
+
},
|
|
124
|
+
recordedInstallState: {
|
|
125
|
+
installedKits: [],
|
|
126
|
+
},
|
|
127
|
+
blocksFilePresence: [],
|
|
128
|
+
routerPatchability: {
|
|
129
|
+
appLayout: {
|
|
130
|
+
path: "",
|
|
131
|
+
exists: false,
|
|
132
|
+
writable: false,
|
|
133
|
+
writableInfo: { status: "init" },
|
|
134
|
+
hasSuppressHydrationWarning: { status: "init" },
|
|
135
|
+
},
|
|
136
|
+
pagesApp: {
|
|
137
|
+
path: "",
|
|
138
|
+
exists: false,
|
|
139
|
+
writable: false,
|
|
140
|
+
writableInfo: { status: "init" },
|
|
141
|
+
hasSuppressHydrationWarning: { status: "init" },
|
|
142
|
+
},
|
|
143
|
+
pagesDocument: {
|
|
144
|
+
path: "",
|
|
145
|
+
exists: false,
|
|
146
|
+
writable: false,
|
|
147
|
+
writableInfo: { status: "init" },
|
|
148
|
+
hasSuppressHydrationWarning: { status: "init" },
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
warnings: [],
|
|
152
|
+
errors: [],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function getPackageJsonPath(cwd) {
|
|
156
|
+
return path_1.default.join(cwd, "package.json");
|
|
157
|
+
}
|
|
158
|
+
async function readPackageJson(cwd) {
|
|
159
|
+
return fs_extra_1.default.readJson(getPackageJsonPath(cwd));
|
|
160
|
+
}
|
|
161
|
+
function getNodeVersionCheck() {
|
|
162
|
+
const rawVersion = process.version;
|
|
163
|
+
const nodeVersion = process.versions.node;
|
|
164
|
+
const major = Number(nodeVersion.split(".")[0]);
|
|
165
|
+
if (!Number.isFinite(major)) {
|
|
166
|
+
return {
|
|
167
|
+
status: "error",
|
|
168
|
+
message: `Unable to determine Node.js version (reported: ${rawVersion})`,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (major < MIN_MAJOR_NODE_VERSION) {
|
|
172
|
+
return {
|
|
173
|
+
status: "error",
|
|
174
|
+
message: `Node.js ${rawVersion} detected — nextworks requires Node.js >= ${MIN_MAJOR_NODE_VERSION}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
status: "ok",
|
|
179
|
+
message: `Node.js ${rawVersion} detected`,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function getProjectRootInfo(options) {
|
|
183
|
+
const { mode, hasAppRouter, hasPagesRouter } = options;
|
|
184
|
+
if (mode !== "src" && mode !== "root") {
|
|
185
|
+
return {
|
|
186
|
+
routerType: null,
|
|
187
|
+
projectRootMode: null,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
let routerType = null;
|
|
191
|
+
let routerTypeLabel = null;
|
|
192
|
+
if (hasAppRouter && hasPagesRouter) {
|
|
193
|
+
routerType = "hybrid";
|
|
194
|
+
routerTypeLabel = "Hybrid router";
|
|
195
|
+
}
|
|
196
|
+
else if (hasAppRouter) {
|
|
197
|
+
routerType = "app";
|
|
198
|
+
routerTypeLabel = "App router";
|
|
199
|
+
}
|
|
200
|
+
else if (hasPagesRouter) {
|
|
201
|
+
routerType = "pages";
|
|
202
|
+
routerTypeLabel = "Pages router";
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
return {
|
|
206
|
+
routerType: null,
|
|
207
|
+
projectRootMode: null,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const rootLabel = mode === "src" ? "with src folder" : "with no src folder";
|
|
211
|
+
return {
|
|
212
|
+
routerType,
|
|
213
|
+
projectRootMode: `${routerTypeLabel} ${rootLabel}`,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
async function fileHasSuppressHydrationWarning(filePath) {
|
|
217
|
+
try {
|
|
218
|
+
const fileContent = await fs_extra_1.default.readFile(filePath, "utf8");
|
|
219
|
+
return fileContent.includes("suppressHydrationWarning")
|
|
220
|
+
? { status: "found" }
|
|
221
|
+
: { status: "not-found" };
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
return { status: "unreadable", error };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function fileIsWritable(filePath) {
|
|
228
|
+
try {
|
|
229
|
+
await fs_extra_1.default.access(filePath, fs_extra_1.default.constants.W_OK);
|
|
230
|
+
return { status: "writable" };
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
const errorCode = typeof err === "object" &&
|
|
234
|
+
err !== null &&
|
|
235
|
+
"code" in err &&
|
|
236
|
+
typeof err.code === "string"
|
|
237
|
+
? err.code
|
|
238
|
+
: null;
|
|
239
|
+
if (errorCode === "EACCES" || errorCode === "EPERM") {
|
|
240
|
+
return { status: "not-writable" };
|
|
241
|
+
}
|
|
242
|
+
const parentDir = path_1.default.dirname(filePath);
|
|
243
|
+
try {
|
|
244
|
+
await fs_extra_1.default.access(parentDir, fs_extra_1.default.constants.W_OK);
|
|
245
|
+
return { status: "not-found-parent-writable" };
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
return { status: "not-found-parent-not-writable" };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async function directoryIsWritable(directoryPath) {
|
|
253
|
+
try {
|
|
254
|
+
const stats = await fs_extra_1.default.stat(directoryPath);
|
|
255
|
+
if (!stats.isDirectory()) {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
await fs_extra_1.default.access(directoryPath, fs_extra_1.default.constants.W_OK);
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
if (typeof error === "object" &&
|
|
263
|
+
error !== null &&
|
|
264
|
+
"code" in error &&
|
|
265
|
+
(error.code === "EACCES" || error.code === "EPERM")) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async function getProjectRootWritability(cwd) {
|
|
272
|
+
const exists = await (0, file_operations_1.fileExists)(cwd);
|
|
273
|
+
if (!exists) {
|
|
274
|
+
return {
|
|
275
|
+
path: cwd,
|
|
276
|
+
exists: false,
|
|
277
|
+
writable: null,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
path: cwd,
|
|
282
|
+
exists: true,
|
|
283
|
+
writable: await directoryIsWritable(cwd),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
async function getAppProvidersShimDiagnostics(cwd, routerType) {
|
|
287
|
+
const warnings = [];
|
|
288
|
+
const shimCandidates = [
|
|
289
|
+
path_1.default.join(cwd, "components", "app-providers.tsx"),
|
|
290
|
+
path_1.default.join(cwd, "src", "components", "app-providers.tsx"),
|
|
291
|
+
];
|
|
292
|
+
let shimPath = shimCandidates[0];
|
|
293
|
+
for (const candidate of shimCandidates) {
|
|
294
|
+
if (await (0, file_operations_1.fileExists)(candidate)) {
|
|
295
|
+
shimPath = candidate;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const exists = await (0, file_operations_1.fileExists)(shimPath);
|
|
300
|
+
const shim = {
|
|
301
|
+
path: shimPath,
|
|
302
|
+
exists,
|
|
303
|
+
target: null,
|
|
304
|
+
targetExists: null,
|
|
305
|
+
targetMatchesRouter: null,
|
|
306
|
+
};
|
|
307
|
+
if (!exists) {
|
|
308
|
+
return { shim, warnings };
|
|
309
|
+
}
|
|
310
|
+
const content = await fs_extra_1.default.readFile(shimPath, "utf8");
|
|
311
|
+
const match = content.match(/from\s+["']\.\/(app-providers\.(?:app|pages))["']/);
|
|
312
|
+
const target = match?.[1] ?? null;
|
|
313
|
+
shim.target = target;
|
|
314
|
+
if (!target) {
|
|
315
|
+
return { shim, warnings };
|
|
316
|
+
}
|
|
317
|
+
const targetPath = path_1.default.join(path_1.default.dirname(shimPath), `${target}.tsx`);
|
|
318
|
+
shim.targetExists = await (0, file_operations_1.fileExists)(targetPath);
|
|
319
|
+
if (shim.targetExists === false) {
|
|
320
|
+
warnings.push(`app-providers shim target file is missing: ${targetPath}`);
|
|
321
|
+
}
|
|
322
|
+
const expectedTarget = routerType === "app"
|
|
323
|
+
? "app-providers.app"
|
|
324
|
+
: routerType === "pages"
|
|
325
|
+
? "app-providers.pages"
|
|
326
|
+
: null;
|
|
327
|
+
shim.targetMatchesRouter = expectedTarget ? expectedTarget === target : null;
|
|
328
|
+
if (expectedTarget && expectedTarget !== target) {
|
|
329
|
+
warnings.push(`app-providers shim target does not match detected ${routerType} router mode: ${shimPath} -> ${target}`);
|
|
330
|
+
}
|
|
331
|
+
return { shim, warnings };
|
|
332
|
+
}
|
|
333
|
+
function getRouterPatchabilityDiagnostics(result) {
|
|
334
|
+
const warnings = [];
|
|
335
|
+
const errors = [];
|
|
336
|
+
const { routerType } = result.projectSanity;
|
|
337
|
+
if (routerType === "app" || routerType === "hybrid") {
|
|
338
|
+
const appLayout = result.routerPatchability.appLayout;
|
|
339
|
+
if (appLayout.exists && appLayout.writableInfo.status === "not-writable") {
|
|
340
|
+
errors.push(`App Router layout is not writable: ${appLayout.path}`);
|
|
341
|
+
}
|
|
342
|
+
if (appLayout.exists &&
|
|
343
|
+
appLayout.hasSuppressHydrationWarning.status === "not-found") {
|
|
344
|
+
warnings.push(`App Router layout is missing suppressHydrationWarning: ${appLayout.path}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (routerType === "pages" || routerType === "hybrid") {
|
|
348
|
+
const pagesApp = result.routerPatchability.pagesApp;
|
|
349
|
+
const pagesDocument = result.routerPatchability.pagesDocument;
|
|
350
|
+
if (pagesApp.exists && pagesApp.writableInfo.status === "not-writable") {
|
|
351
|
+
errors.push(`Pages Router _app.tsx is not writable: ${pagesApp.path}`);
|
|
352
|
+
}
|
|
353
|
+
if (pagesDocument.exists &&
|
|
354
|
+
pagesDocument.writableInfo.status === "not-writable") {
|
|
355
|
+
errors.push(`Pages Router _document.tsx is not writable: ${pagesDocument.path}`);
|
|
356
|
+
}
|
|
357
|
+
if (pagesDocument.exists &&
|
|
358
|
+
pagesDocument.hasSuppressHydrationWarning.status === "not-found") {
|
|
359
|
+
warnings.push(`Pages Router _document.tsx is missing suppressHydrationWarning: ${pagesDocument.path}`);
|
|
360
|
+
}
|
|
361
|
+
if (!pagesDocument.exists &&
|
|
362
|
+
pagesDocument.writableInfo.status === "not-found-parent-writable") {
|
|
363
|
+
warnings.push(`Pages Router _document.tsx does not exist and will need to be created during install: ${pagesDocument.path}`);
|
|
364
|
+
}
|
|
365
|
+
if (!pagesDocument.exists &&
|
|
366
|
+
pagesDocument.writableInfo.status === "not-found-parent-not-writable") {
|
|
367
|
+
errors.push(`Pages Router _document.tsx does not exist and its parent directory is not writable: ${pagesDocument.path}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return { warnings, errors };
|
|
371
|
+
}
|
|
372
|
+
function collectCollisionChecks(cwd, mode, routerType) {
|
|
373
|
+
const candidates = [...COLLISION_CANDIDATES[mode]];
|
|
374
|
+
for (const slug of TEMPLATE_SLUGS) {
|
|
375
|
+
if (routerType === "pages" || routerType === "hybrid") {
|
|
376
|
+
if (mode === "src") {
|
|
377
|
+
candidates.push(`src/pages/templates/${slug}/index.tsx`);
|
|
378
|
+
candidates.push(`src/components/templates/${slug}`);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
candidates.push(`pages/templates/${slug}/index.tsx`);
|
|
382
|
+
candidates.push(`components/templates/${slug}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (routerType === "app" || routerType === "hybrid") {
|
|
386
|
+
if (mode === "src") {
|
|
387
|
+
candidates.push(`src/app/templates/${slug}/page.tsx`);
|
|
388
|
+
candidates.push(`src/app/templates/${slug}`);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
candidates.push(`app/templates/${slug}/page.tsx`);
|
|
392
|
+
candidates.push(`app/templates/${slug}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return candidates.map((relativePath) => ({
|
|
397
|
+
path: path_1.default.join(cwd, relativePath),
|
|
398
|
+
exists: false,
|
|
399
|
+
}));
|
|
400
|
+
}
|
|
401
|
+
async function getCollisionDiagnostics(cwd, mode, routerType) {
|
|
402
|
+
const paths = collectCollisionChecks(cwd, mode, routerType);
|
|
403
|
+
for (const entry of paths) {
|
|
404
|
+
entry.exists = await (0, file_operations_1.fileExists)(entry.path);
|
|
405
|
+
}
|
|
406
|
+
return { paths };
|
|
407
|
+
}
|
|
408
|
+
async function getRecordedInstallState() {
|
|
409
|
+
const config = await (0, installation_tracker_1.getNextworksConfig)();
|
|
410
|
+
return {
|
|
411
|
+
installedKits: config.installedKits.map((kit) => ({
|
|
412
|
+
name: kit.name,
|
|
413
|
+
dependencies: [...kit.dependencies],
|
|
414
|
+
devDependencies: [...kit.devDependencies],
|
|
415
|
+
files: [...kit.files],
|
|
416
|
+
installedAt: kit.installedAt,
|
|
417
|
+
})),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function getBlocksInstalledFileChecks(cwd, manifest, recordedInstallState) {
|
|
421
|
+
const installedBlocksKit = recordedInstallState.installedKits.find((kit) => kit.name === manifest.name);
|
|
422
|
+
if (!installedBlocksKit) {
|
|
423
|
+
return [];
|
|
424
|
+
}
|
|
425
|
+
return installedBlocksKit.files.map((relativePath) => ({
|
|
426
|
+
path: path_1.default.join(cwd, relativePath),
|
|
427
|
+
exists: false,
|
|
428
|
+
required: true,
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
async function doctor(options = {}) {
|
|
432
|
+
const cwd = process.cwd();
|
|
433
|
+
const result = createInitialDoctorResult();
|
|
434
|
+
const manifestPath = (0, file_operations_1.resolveAssetPath)("cli_manifests", "blocks_manifest.json");
|
|
435
|
+
const packageJsonPath = getPackageJsonPath(cwd);
|
|
436
|
+
const hasPackageJson = await (0, file_operations_1.fileExists)(packageJsonPath);
|
|
437
|
+
result.projectSanity.hasPackageJson = hasPackageJson;
|
|
438
|
+
if (!hasPackageJson) {
|
|
439
|
+
result.errors.push("package.json not found. Run nextworks from a Next.js project root.");
|
|
440
|
+
}
|
|
441
|
+
let packageJson = null;
|
|
442
|
+
if (hasPackageJson) {
|
|
443
|
+
const pkg = (await readPackageJson(cwd));
|
|
444
|
+
packageJson = pkg;
|
|
445
|
+
result.projectSanity.hasNext = Boolean(pkg.dependencies?.next || pkg.devDependencies?.next);
|
|
446
|
+
if (!result.projectSanity.hasNext) {
|
|
447
|
+
result.errors.push('Next.js dependency "next" not found in dependencies or devDependencies.');
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
const manifest = (await (0, file_operations_1.readJsonFile)(manifestPath));
|
|
451
|
+
const mode = await (0, file_operations_1.detectProjectRootMode)(cwd);
|
|
452
|
+
result.projectSanity.projectRoot = mode;
|
|
453
|
+
const detectedLayoutPath = mode === "src" ? "src/app/layout.tsx" : "app/layout.tsx";
|
|
454
|
+
const detectedPagesAppPath = mode === "src" ? "src/pages/_app.tsx" : "pages/_app.tsx";
|
|
455
|
+
const appRouterLayoutExists = await (0, file_operations_1.fileExists)(detectedLayoutPath);
|
|
456
|
+
const pagesRouterAppExists = await (0, file_operations_1.fileExists)(detectedPagesAppPath);
|
|
457
|
+
const { routerType, projectRootMode } = getProjectRootInfo({
|
|
458
|
+
mode,
|
|
459
|
+
hasAppRouter: appRouterLayoutExists,
|
|
460
|
+
hasPagesRouter: pagesRouterAppExists,
|
|
461
|
+
});
|
|
462
|
+
if (routerType) {
|
|
463
|
+
result.projectSanity.routerType = routerType;
|
|
464
|
+
}
|
|
465
|
+
if (projectRootMode) {
|
|
466
|
+
result.projectSanity.projectRootMode = projectRootMode;
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
result.errors.push("No supported Next.js router entrypoint found. Expected app/layout.tsx, src/app/layout.tsx, pages/_app.tsx, or src/pages/_app.tsx.");
|
|
470
|
+
}
|
|
471
|
+
result.environmentChecks.nodeVersion = getNodeVersionCheck();
|
|
472
|
+
if (result.environmentChecks.nodeVersion.status === "error") {
|
|
473
|
+
result.errors.push(result.environmentChecks.nodeVersion.message);
|
|
474
|
+
}
|
|
475
|
+
const detectedPM = await (0, package_manager_1.detectPackageManager)(cwd);
|
|
476
|
+
const installCmd = (0, package_manager_1.getInstallCommand)(detectedPM);
|
|
477
|
+
result.environmentChecks.packageManager.pm = detectedPM;
|
|
478
|
+
result.environmentChecks.packageManager.installCommand = installCmd;
|
|
479
|
+
const isYarnPnP = await (0, yarn_pnp_1.isYarnPnPProject)(cwd);
|
|
480
|
+
result.environmentChecks.yarnPnPDetection.isPnP = isYarnPnP;
|
|
481
|
+
if (isYarnPnP) {
|
|
482
|
+
result.warnings.push(`Yarn Plug'n'Play detected. ${result.environmentChecks.yarnPnPDetection.message}`);
|
|
483
|
+
}
|
|
484
|
+
if (packageJson) {
|
|
485
|
+
result.environmentChecks.tailwind.hasTailwindDependency =
|
|
486
|
+
hasTailwindDependency(packageJson);
|
|
487
|
+
result.environmentChecks.typescript.hasTypeScriptDependency =
|
|
488
|
+
hasTypeScriptDependency(packageJson);
|
|
489
|
+
}
|
|
490
|
+
result.environmentChecks.tailwind.hasCssBasedTailwindUsage =
|
|
491
|
+
await hasCssBasedTailwindUsage(cwd);
|
|
492
|
+
result.environmentChecks.tailwind.detected =
|
|
493
|
+
result.environmentChecks.tailwind.hasTailwindDependency ||
|
|
494
|
+
result.environmentChecks.tailwind.hasCssBasedTailwindUsage;
|
|
495
|
+
if (!result.environmentChecks.tailwind.detected) {
|
|
496
|
+
result.warnings.push('Tailwind CSS was not detected. Blocks requires Tailwind CSS v4-style setup via a `tailwindcss` dependency or CSS imports such as `@import "tailwindcss"`.');
|
|
497
|
+
}
|
|
498
|
+
result.environmentChecks.typescript.hasTsconfig = await hasTsconfig(cwd);
|
|
499
|
+
result.environmentChecks.typescript.detected =
|
|
500
|
+
result.environmentChecks.typescript.hasTsconfig ||
|
|
501
|
+
result.environmentChecks.typescript.hasTypeScriptDependency;
|
|
502
|
+
if (!result.environmentChecks.typescript.detected) {
|
|
503
|
+
result.errors.push("TypeScript was not detected. Blocks requires a `tsconfig.json` file or a `typescript` dependency in dependencies or devDependencies.");
|
|
504
|
+
}
|
|
505
|
+
result.projectRootWritability = await getProjectRootWritability(cwd);
|
|
506
|
+
if (!result.projectRootWritability.exists) {
|
|
507
|
+
result.errors.push(`Project root does not exist: ${result.projectRootWritability.path}`);
|
|
508
|
+
}
|
|
509
|
+
else if (result.projectRootWritability.writable === false) {
|
|
510
|
+
result.errors.push(`Project root is not writable: ${result.projectRootWritability.path}`);
|
|
511
|
+
}
|
|
512
|
+
if (result.projectSanity.routerType === "app" ||
|
|
513
|
+
result.projectSanity.routerType === "hybrid") {
|
|
514
|
+
let layoutFilePath = "";
|
|
515
|
+
if (result.projectSanity.projectRoot === "src") {
|
|
516
|
+
layoutFilePath = path_1.default.join(process.cwd(), "src", "app", "layout.tsx");
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
layoutFilePath = path_1.default.join(process.cwd(), "app", "layout.tsx");
|
|
520
|
+
}
|
|
521
|
+
result.routerPatchability.appLayout.path = layoutFilePath;
|
|
522
|
+
const layoutExists = await (0, file_operations_1.fileExists)(layoutFilePath);
|
|
523
|
+
result.routerPatchability.appLayout.exists = layoutExists;
|
|
524
|
+
const writableInfo = await fileIsWritable(layoutFilePath);
|
|
525
|
+
result.routerPatchability.appLayout.writableInfo = writableInfo;
|
|
526
|
+
const writableStatus = writableInfo.status;
|
|
527
|
+
if (writableStatus === "writable") {
|
|
528
|
+
result.routerPatchability.appLayout.writable = true;
|
|
529
|
+
}
|
|
530
|
+
else if (writableStatus === "not-writable") {
|
|
531
|
+
result.routerPatchability.appLayout.writable = false;
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
result.routerPatchability.appLayout.writable = null;
|
|
535
|
+
}
|
|
536
|
+
const hasHydrationWarning = await fileHasSuppressHydrationWarning(layoutFilePath);
|
|
537
|
+
result.routerPatchability.appLayout.hasSuppressHydrationWarning =
|
|
538
|
+
hasHydrationWarning;
|
|
539
|
+
}
|
|
540
|
+
if (result.projectSanity.routerType === "pages" ||
|
|
541
|
+
result.projectSanity.routerType === "hybrid") {
|
|
542
|
+
let _appFilePath = "";
|
|
543
|
+
if (result.projectSanity.projectRoot === "src") {
|
|
544
|
+
_appFilePath = path_1.default.join(process.cwd(), "src", "pages", "_app.tsx");
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
_appFilePath = path_1.default.join(process.cwd(), "pages", "_app.tsx");
|
|
548
|
+
}
|
|
549
|
+
result.routerPatchability.pagesApp.path = _appFilePath;
|
|
550
|
+
const _appExists = await (0, file_operations_1.fileExists)(_appFilePath);
|
|
551
|
+
result.routerPatchability.pagesApp.exists = _appExists;
|
|
552
|
+
const appWritableInfo = await fileIsWritable(_appFilePath);
|
|
553
|
+
result.routerPatchability.pagesApp.writableInfo = appWritableInfo;
|
|
554
|
+
const appWritableStatus = appWritableInfo.status;
|
|
555
|
+
if (appWritableStatus === "writable") {
|
|
556
|
+
result.routerPatchability.pagesApp.writable = true;
|
|
557
|
+
}
|
|
558
|
+
else if (appWritableStatus === "not-writable") {
|
|
559
|
+
result.routerPatchability.pagesApp.writable = false;
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
result.routerPatchability.pagesApp.writable = null;
|
|
563
|
+
}
|
|
564
|
+
let _documentFilePath = "";
|
|
565
|
+
if (result.projectSanity.projectRoot === "src") {
|
|
566
|
+
_documentFilePath = path_1.default.join(process.cwd(), "src", "pages", "_document.tsx");
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
_documentFilePath = path_1.default.join(process.cwd(), "pages", "_document.tsx");
|
|
570
|
+
}
|
|
571
|
+
result.routerPatchability.pagesDocument.path = _documentFilePath;
|
|
572
|
+
const _documentExists = await (0, file_operations_1.fileExists)(_documentFilePath);
|
|
573
|
+
result.routerPatchability.pagesDocument.exists = _documentExists;
|
|
574
|
+
const documentWritableInfo = await fileIsWritable(_documentFilePath);
|
|
575
|
+
result.routerPatchability.pagesDocument.writableInfo = documentWritableInfo;
|
|
576
|
+
const documentWritableStatus = documentWritableInfo.status;
|
|
577
|
+
if (documentWritableStatus === "writable") {
|
|
578
|
+
result.routerPatchability.pagesDocument.writable = true;
|
|
579
|
+
}
|
|
580
|
+
else if (documentWritableStatus === "not-writable") {
|
|
581
|
+
result.routerPatchability.pagesDocument.writable = false;
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
result.routerPatchability.pagesDocument.writable = null;
|
|
585
|
+
}
|
|
586
|
+
const hasHydrationWarning = await fileHasSuppressHydrationWarning(_documentFilePath);
|
|
587
|
+
result.routerPatchability.pagesDocument.hasSuppressHydrationWarning =
|
|
588
|
+
hasHydrationWarning;
|
|
589
|
+
}
|
|
590
|
+
const shimDiagnostics = await getAppProvidersShimDiagnostics(cwd, result.projectSanity.routerType);
|
|
591
|
+
result.appProvidersShim = shimDiagnostics.shim;
|
|
592
|
+
result.warnings.push(...shimDiagnostics.warnings);
|
|
593
|
+
result.collisions = await getCollisionDiagnostics(cwd, mode ?? "root", result.projectSanity.routerType);
|
|
594
|
+
result.warnings.push(...result.collisions.paths
|
|
595
|
+
.filter((entry) => entry.exists)
|
|
596
|
+
.map((entry) => `Install collision detected: ${entry.path}`));
|
|
597
|
+
result.recordedInstallState = await getRecordedInstallState();
|
|
598
|
+
if (result.recordedInstallState.installedKits.length === 0) {
|
|
599
|
+
result.warnings.push("No recorded installed kits found in .nextworks/config.json.");
|
|
600
|
+
}
|
|
601
|
+
result.blocksFilePresence = getBlocksInstalledFileChecks(cwd, manifest, result.recordedInstallState);
|
|
602
|
+
for (const entry of result.blocksFilePresence) {
|
|
603
|
+
entry.exists = await (0, file_operations_1.fileExists)(entry.path);
|
|
604
|
+
if (!entry.exists) {
|
|
605
|
+
result.warnings.push(`Recorded Blocks install is missing expected file: ${entry.path}`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
const diagnostics = getRouterPatchabilityDiagnostics(result);
|
|
609
|
+
result.warnings.push(...diagnostics.warnings);
|
|
610
|
+
result.errors.push(...diagnostics.errors);
|
|
611
|
+
return result;
|
|
612
|
+
}
|
|
613
|
+
function formatDoctorResult(result) {
|
|
614
|
+
const lines = ["Doctor diagnostics"];
|
|
615
|
+
const iconFor = (status) => status === "ok" ? "✅" : status === "warning" ? "⚠️" : "❌";
|
|
616
|
+
lines.push("\nEnvironment");
|
|
617
|
+
lines.push(` ${iconFor(result.environmentChecks.nodeVersion.status)} ${result.environmentChecks.nodeVersion.message}`);
|
|
618
|
+
lines.push(` ✅ Package manager detected: ${result.environmentChecks.packageManager.pm} (${result.environmentChecks.packageManager.installCommand})`);
|
|
619
|
+
lines.push(` ${result.environmentChecks.yarnPnPDetection.isPnP ? "⚠️" : "✅"} Yarn Plug'n'Play ${result.environmentChecks.yarnPnPDetection.isPnP ? "detected" : "not detected"}`);
|
|
620
|
+
if (result.environmentChecks.yarnPnPDetection.isPnP)
|
|
621
|
+
lines.push(` ⚠️ ${result.environmentChecks.yarnPnPDetection.message}`);
|
|
622
|
+
lines.push("\nProject detection");
|
|
623
|
+
lines.push(` ${result.projectSanity.hasPackageJson ? "✅" : "❌"} package.json ${result.projectSanity.hasPackageJson ? "found" : "not found"}`);
|
|
624
|
+
lines.push(` ${result.projectSanity.hasNext ? "✅" : "❌"} Next.js dependency ${result.projectSanity.hasNext ? "found" : "not found"}`);
|
|
625
|
+
lines.push(` ${result.projectSanity.projectRoot ? "✅" : "❌"} Project root mode: ${result.projectSanity.projectRoot ?? "not detected"}`);
|
|
626
|
+
lines.push(` ${result.projectSanity.routerType ? "✅" : "❌"} Router type: ${result.projectSanity.routerType ?? "not detected"}`);
|
|
627
|
+
if (result.projectSanity.projectRootMode)
|
|
628
|
+
lines.push(` ✅ ${result.projectSanity.projectRootMode}`);
|
|
629
|
+
lines.push("\nRouter / patch targets");
|
|
630
|
+
if (result.projectSanity.routerType === "app" ||
|
|
631
|
+
result.projectSanity.routerType === "hybrid") {
|
|
632
|
+
lines.push(` ${result.routerPatchability.appLayout.exists ? "✅" : "⚠️"} app/layout.tsx: ${result.routerPatchability.appLayout.path}`);
|
|
633
|
+
lines.push(` ${result.routerPatchability.appLayout.exists ? (result.routerPatchability.appLayout.writableInfo.status === "not-writable" ? "❌" : "✅") : "⚠️"} Writable: ${String(result.routerPatchability.appLayout.writable)}`);
|
|
634
|
+
lines.push(` ${result.routerPatchability.appLayout.hasSuppressHydrationWarning.status === "found" ? "✅" : "⚠️"} suppressHydrationWarning: ${result.routerPatchability.appLayout.hasSuppressHydrationWarning.status}`);
|
|
635
|
+
}
|
|
636
|
+
if (result.projectSanity.routerType === "pages" ||
|
|
637
|
+
result.projectSanity.routerType === "hybrid") {
|
|
638
|
+
lines.push(` ${result.routerPatchability.pagesApp.exists ? "✅" : "⚠️"} pages/_app.tsx: ${result.routerPatchability.pagesApp.path}`);
|
|
639
|
+
lines.push(` ${result.routerPatchability.pagesApp.exists ? (result.routerPatchability.pagesApp.writableInfo.status === "not-writable" ? "❌" : "✅") : "⚠️"} Writable: ${String(result.routerPatchability.pagesApp.writable)}`);
|
|
640
|
+
lines.push(` ${result.routerPatchability.pagesDocument.exists ? "✅" : "⚠️"} pages/_document.tsx: ${result.routerPatchability.pagesDocument.path}`);
|
|
641
|
+
lines.push(` ${result.routerPatchability.pagesDocument.exists ? (result.routerPatchability.pagesDocument.writableInfo.status === "not-writable" || result.routerPatchability.pagesDocument.writableInfo.status === "not-found-parent-not-writable" ? "❌" : "✅") : "⚠️"} Writable: ${String(result.routerPatchability.pagesDocument.writable)}`);
|
|
642
|
+
lines.push(` ${result.routerPatchability.pagesDocument.hasSuppressHydrationWarning.status === "found" ? "✅" : "⚠️"} suppressHydrationWarning: ${result.routerPatchability.pagesDocument.hasSuppressHydrationWarning.status}`);
|
|
643
|
+
lines.push(` ${result.appProvidersShim.exists ? (result.appProvidersShim.targetMatchesRouter === false || result.appProvidersShim.targetExists === false ? "⚠️" : "✅") : "⚠️"} components/app-providers.tsx: ${result.appProvidersShim.path}`);
|
|
644
|
+
}
|
|
645
|
+
lines.push("\nKit prerequisites");
|
|
646
|
+
lines.push(` ${result.environmentChecks.tailwind.detected ? "✅" : "⚠️"} Tailwind CSS ${result.environmentChecks.tailwind.detected ? "detected" : "not detected"}`);
|
|
647
|
+
lines.push(` ${result.environmentChecks.typescript.detected ? "✅" : "❌"} TypeScript ${result.environmentChecks.typescript.detected ? "detected" : "not detected"}`);
|
|
648
|
+
lines.push("\nFilesystem / collisions");
|
|
649
|
+
lines.push(` ${result.projectRootWritability.writable === false ? "❌" : result.projectRootWritability.exists ? "✅" : "❌"} Project root writable: ${String(result.projectRootWritability.writable)}`);
|
|
650
|
+
const existingCollisions = result.collisions.paths.filter((collision) => collision.exists);
|
|
651
|
+
if (existingCollisions.length === 0) {
|
|
652
|
+
lines.push(" ✅ No install collisions detected");
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
for (const entry of existingCollisions) {
|
|
656
|
+
lines.push(` ⚠️ Collision: ${entry.path}`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
lines.push("\nInstalled state");
|
|
660
|
+
if (result.recordedInstallState.installedKits.length === 0) {
|
|
661
|
+
lines.push(" ⚠️ No recorded installed kits found");
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
for (const kit of result.recordedInstallState.installedKits) {
|
|
665
|
+
lines.push(` ✅ Recorded kit: ${kit.name}`);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
const missingRecordedFiles = result.blocksFilePresence.filter((file) => !file.exists);
|
|
669
|
+
if (missingRecordedFiles.length > 0) {
|
|
670
|
+
for (const entry of missingRecordedFiles) {
|
|
671
|
+
lines.push(` ⚠️ Missing recorded file: ${entry.path}`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
lines.push("\nRecommendation");
|
|
675
|
+
if (result.errors.length === 0) {
|
|
676
|
+
lines.push(" ✅ Recommended next step: nextworks add blocks");
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
const priorityError = result.errors[0];
|
|
680
|
+
lines.push(` ❌ Fix blocking issues before install: ${priorityError}`);
|
|
681
|
+
}
|
|
682
|
+
if (result.warnings.length) {
|
|
683
|
+
lines.push("\nWarnings");
|
|
684
|
+
for (const warning of result.warnings) {
|
|
685
|
+
lines.push(` ⚠️ ${warning}`);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
if (result.errors.length) {
|
|
689
|
+
lines.push("\nErrors");
|
|
690
|
+
for (const error of result.errors) {
|
|
691
|
+
lines.push(` ❌ ${error}`);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return lines;
|
|
695
|
+
}
|
|
696
|
+
//# sourceMappingURL=doctor.js.map
|