cognite-create 0.1.7 → 0.1.8
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/bin/index.js +89 -63
- package/package.json +1 -1
- package/templates/.cursor/rules/general.mdc +1 -1
package/bin/index.js
CHANGED
|
@@ -1,37 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
4
|
-
const { spawn } = require(
|
|
4
|
+
const { spawn } = require("node:child_process");
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
6
|
-
const fs = require(
|
|
6
|
+
const fs = require("node:fs/promises");
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
8
|
-
const path = require(
|
|
8
|
+
const path = require("node:path");
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
|
|
10
|
+
const REQUIRED_DEPENDENCIES = [
|
|
11
|
+
{ name: "tw-animate-css", version: "^1.3.8" },
|
|
12
|
+
{ name: "clsx", version: "^2.1.1" },
|
|
13
|
+
];
|
|
12
14
|
|
|
13
15
|
async function main() {
|
|
14
16
|
const args = process.argv.slice(2);
|
|
15
17
|
|
|
16
|
-
if (args.length === 0 || args[0].startsWith(
|
|
17
|
-
console.error(
|
|
18
|
+
if (args.length === 0 || args[0].startsWith("-")) {
|
|
19
|
+
console.error(
|
|
20
|
+
"Usage: cognite-create <project-name> [create-next-app options]"
|
|
21
|
+
);
|
|
18
22
|
process.exit(1);
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
const projectDir = args[0];
|
|
22
|
-
const createArgs = [
|
|
26
|
+
const createArgs = ["create-next-app@latest", ...args];
|
|
23
27
|
await runCreateNextApp(createArgs);
|
|
24
28
|
await addCogniteTemplates(projectDir);
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
function runCreateNextApp(cliArgs) {
|
|
28
|
-
const command = process.platform ===
|
|
32
|
+
const command = process.platform === "win32" ? "npx.cmd" : "npx";
|
|
29
33
|
|
|
30
34
|
return new Promise((resolve, reject) => {
|
|
31
|
-
const child = spawn(command, cliArgs, { stdio:
|
|
35
|
+
const child = spawn(command, cliArgs, { stdio: "inherit" });
|
|
32
36
|
|
|
33
|
-
child.on(
|
|
34
|
-
child.on(
|
|
37
|
+
child.on("error", reject);
|
|
38
|
+
child.on("close", (code) => {
|
|
35
39
|
if (code !== 0) {
|
|
36
40
|
const error = new Error(`create-next-app exited with code ${code}`);
|
|
37
41
|
error.exitCode = code;
|
|
@@ -45,24 +49,24 @@ function runCreateNextApp(cliArgs) {
|
|
|
45
49
|
|
|
46
50
|
async function addCogniteTemplates(projectDir) {
|
|
47
51
|
const targetRoot = path.resolve(process.cwd(), projectDir);
|
|
48
|
-
const templateRoot = path.resolve(__dirname,
|
|
52
|
+
const templateRoot = path.resolve(__dirname, "..", "templates");
|
|
49
53
|
|
|
50
54
|
try {
|
|
51
55
|
await fs.access(targetRoot);
|
|
52
56
|
} catch (error) {
|
|
53
|
-
if (error.code ===
|
|
57
|
+
if (error.code === "ENOENT") {
|
|
54
58
|
throw new Error(
|
|
55
59
|
`Expected to find the newly created project at "${projectDir}", but it was not found. ` +
|
|
56
|
-
|
|
60
|
+
"Check the create-next-app output for more details."
|
|
57
61
|
);
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
throw error;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
await
|
|
67
|
+
await ensureDependenciesInstalled(targetRoot);
|
|
64
68
|
|
|
65
|
-
const srcDirectory = path.join(targetRoot,
|
|
69
|
+
const srcDirectory = path.join(targetRoot, "src");
|
|
66
70
|
const templateFiles = await collectTemplateFiles(templateRoot);
|
|
67
71
|
|
|
68
72
|
await fs.mkdir(srcDirectory, { recursive: true });
|
|
@@ -71,12 +75,14 @@ async function addCogniteTemplates(projectDir) {
|
|
|
71
75
|
const normalizedPath = normalizeRelativePath(relativePath);
|
|
72
76
|
const source = path.join(templateRoot, relativePath);
|
|
73
77
|
|
|
74
|
-
const pathSegments = normalizedPath.split(
|
|
78
|
+
const pathSegments = normalizedPath.split("/");
|
|
75
79
|
|
|
76
|
-
if (pathSegments[0] ===
|
|
80
|
+
if (pathSegments[0] === "app" || pathSegments[0] === "lib") {
|
|
77
81
|
const target = path.join(srcDirectory, ...pathSegments);
|
|
78
82
|
const isGlobalsCss =
|
|
79
|
-
pathSegments[0] ===
|
|
83
|
+
pathSegments[0] === "app" &&
|
|
84
|
+
pathSegments.length === 2 &&
|
|
85
|
+
pathSegments[1] === "globals.css";
|
|
80
86
|
|
|
81
87
|
if (isGlobalsCss) {
|
|
82
88
|
await copyFileWithOverwrite(source, target);
|
|
@@ -91,7 +97,7 @@ async function addCogniteTemplates(projectDir) {
|
|
|
91
97
|
await copyFileIfMissing(source, target);
|
|
92
98
|
}
|
|
93
99
|
|
|
94
|
-
console.log(
|
|
100
|
+
console.log("\nCognite templates copied successfully.");
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
async function copyFileIfMissing(source, target) {
|
|
@@ -101,7 +107,7 @@ async function copyFileIfMissing(source, target) {
|
|
|
101
107
|
await fs.access(target);
|
|
102
108
|
console.warn(`Skipped existing ${path.relative(process.cwd(), target)}`);
|
|
103
109
|
} catch (error) {
|
|
104
|
-
if (error.code !==
|
|
110
|
+
if (error.code !== "ENOENT") {
|
|
105
111
|
throw error;
|
|
106
112
|
}
|
|
107
113
|
|
|
@@ -142,30 +148,43 @@ async function collectTemplateFiles(rootDir) {
|
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
function normalizeRelativePath(relativePath) {
|
|
145
|
-
return relativePath.split(path.sep).join(
|
|
151
|
+
return relativePath.split(path.sep).join("/");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function formatDependencySummary(dependencies) {
|
|
155
|
+
return dependencies
|
|
156
|
+
.map((dependency) =>
|
|
157
|
+
dependency.version ? `${dependency.name}@${dependency.version}` : dependency.name
|
|
158
|
+
)
|
|
159
|
+
.join(", ");
|
|
146
160
|
}
|
|
147
161
|
|
|
148
|
-
async function
|
|
149
|
-
const packageJsonPath = path.join(targetRoot,
|
|
162
|
+
async function ensureDependenciesInstalled(targetRoot) {
|
|
163
|
+
const packageJsonPath = path.join(targetRoot, "package.json");
|
|
150
164
|
let packageJson;
|
|
151
165
|
|
|
152
166
|
try {
|
|
153
|
-
const packageJsonContent = await fs.readFile(packageJsonPath,
|
|
167
|
+
const packageJsonContent = await fs.readFile(packageJsonPath, "utf8");
|
|
154
168
|
packageJson = JSON.parse(packageJsonContent);
|
|
155
|
-
} catch
|
|
169
|
+
} catch {
|
|
156
170
|
console.warn(
|
|
157
|
-
`\nUnable to read or parse ${path.relative(
|
|
158
|
-
|
|
171
|
+
`\nUnable to read or parse ${path.relative(
|
|
172
|
+
process.cwd(),
|
|
173
|
+
packageJsonPath
|
|
174
|
+
)}. Install ${formatDependencySummary(REQUIRED_DEPENDENCIES)} manually.`
|
|
159
175
|
);
|
|
160
176
|
return false;
|
|
161
177
|
}
|
|
162
178
|
|
|
163
|
-
const
|
|
164
|
-
(
|
|
165
|
-
(
|
|
179
|
+
const missingDependencies = REQUIRED_DEPENDENCIES.filter(
|
|
180
|
+
(dependency) =>
|
|
181
|
+
!(
|
|
182
|
+
(packageJson.dependencies && packageJson.dependencies[dependency.name]) ||
|
|
183
|
+
(packageJson.devDependencies && packageJson.devDependencies[dependency.name])
|
|
184
|
+
)
|
|
166
185
|
);
|
|
167
186
|
|
|
168
|
-
if (
|
|
187
|
+
if (missingDependencies.length === 0) {
|
|
169
188
|
return false;
|
|
170
189
|
}
|
|
171
190
|
|
|
@@ -173,23 +192,27 @@ async function ensureTwAnimateCssInstalled(targetRoot) {
|
|
|
173
192
|
|
|
174
193
|
if (!packageManager) {
|
|
175
194
|
console.warn(
|
|
176
|
-
`\nCould not determine package manager for ${path.relative(
|
|
177
|
-
|
|
195
|
+
`\nCould not determine package manager for ${path.relative(
|
|
196
|
+
process.cwd(),
|
|
197
|
+
targetRoot
|
|
198
|
+
)}. Install ${formatDependencySummary(missingDependencies)} manually.`
|
|
178
199
|
);
|
|
179
200
|
return false;
|
|
180
201
|
}
|
|
181
202
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
);
|
|
185
|
-
await installDependency(packageManager, targetRoot, `${TW_ANIMATE_PACKAGE}@${TW_ANIMATE_VERSION}`);
|
|
203
|
+
const dependencySummary = formatDependencySummary(missingDependencies);
|
|
204
|
+
console.log(`\nInstalling ${dependencySummary} using ${packageManager}...`);
|
|
205
|
+
await installDependencies(packageManager, targetRoot, missingDependencies);
|
|
186
206
|
|
|
187
207
|
return true;
|
|
188
208
|
}
|
|
189
209
|
|
|
190
210
|
async function detectPackageManager(packageJson, targetRoot) {
|
|
191
|
-
if (
|
|
192
|
-
|
|
211
|
+
if (
|
|
212
|
+
packageJson.packageManager &&
|
|
213
|
+
typeof packageJson.packageManager === "string"
|
|
214
|
+
) {
|
|
215
|
+
const [name] = packageJson.packageManager.split("@");
|
|
193
216
|
|
|
194
217
|
if (name) {
|
|
195
218
|
return name;
|
|
@@ -197,10 +220,10 @@ async function detectPackageManager(packageJson, targetRoot) {
|
|
|
197
220
|
}
|
|
198
221
|
|
|
199
222
|
const candidates = [
|
|
200
|
-
{ name:
|
|
201
|
-
{ name:
|
|
202
|
-
{ name:
|
|
203
|
-
{ name:
|
|
223
|
+
{ name: "pnpm", lockFile: "pnpm-lock.yaml" },
|
|
224
|
+
{ name: "yarn", lockFile: "yarn.lock" },
|
|
225
|
+
{ name: "bun", lockFile: "bun.lockb" },
|
|
226
|
+
{ name: "npm", lockFile: "package-lock.json" },
|
|
204
227
|
];
|
|
205
228
|
|
|
206
229
|
for (const candidate of candidates) {
|
|
@@ -214,21 +237,24 @@ async function detectPackageManager(packageJson, targetRoot) {
|
|
|
214
237
|
return null;
|
|
215
238
|
}
|
|
216
239
|
|
|
217
|
-
async function
|
|
218
|
-
const
|
|
240
|
+
async function installDependencies(packageManager, cwd, dependencies) {
|
|
241
|
+
const dependencySpecs = dependencies.map((dependency) =>
|
|
242
|
+
dependency.version ? `${dependency.name}@${dependency.version}` : dependency.name
|
|
243
|
+
);
|
|
244
|
+
const { command, args } = getInstallCommand(packageManager, dependencySpecs);
|
|
219
245
|
|
|
220
246
|
if (!command) {
|
|
221
247
|
throw new Error(`Unsupported package manager: ${packageManager}`);
|
|
222
248
|
}
|
|
223
249
|
|
|
224
250
|
return new Promise((resolve, reject) => {
|
|
225
|
-
const child = spawn(command, args, { stdio:
|
|
251
|
+
const child = spawn(command, args, { stdio: "inherit", cwd });
|
|
226
252
|
|
|
227
|
-
child.on(
|
|
228
|
-
child.on(
|
|
253
|
+
child.on("error", reject);
|
|
254
|
+
child.on("close", (code) => {
|
|
229
255
|
if (code !== 0) {
|
|
230
256
|
const error = new Error(
|
|
231
|
-
`${packageManager} exited with code ${code} while installing ${
|
|
257
|
+
`${packageManager} exited with code ${code} while installing ${dependencySpecs.join(", ")}`
|
|
232
258
|
);
|
|
233
259
|
error.exitCode = code;
|
|
234
260
|
return reject(error);
|
|
@@ -239,25 +265,25 @@ async function installDependency(packageManager, cwd, dependencySpec) {
|
|
|
239
265
|
});
|
|
240
266
|
}
|
|
241
267
|
|
|
242
|
-
function getInstallCommand(packageManager,
|
|
268
|
+
function getInstallCommand(packageManager, dependencySpecs) {
|
|
243
269
|
const normalized = normalizeCommand(packageManager);
|
|
244
270
|
|
|
245
271
|
switch (packageManager) {
|
|
246
|
-
case
|
|
247
|
-
return { command: normalized, args: [
|
|
248
|
-
case
|
|
249
|
-
return { command: normalized, args: [
|
|
250
|
-
case
|
|
251
|
-
return { command: normalized, args: [
|
|
252
|
-
case
|
|
253
|
-
return { command: normalized, args: [
|
|
272
|
+
case "npm":
|
|
273
|
+
return { command: normalized, args: ["install", ...dependencySpecs] };
|
|
274
|
+
case "pnpm":
|
|
275
|
+
return { command: normalized, args: ["add", ...dependencySpecs] };
|
|
276
|
+
case "yarn":
|
|
277
|
+
return { command: normalized, args: ["add", ...dependencySpecs] };
|
|
278
|
+
case "bun":
|
|
279
|
+
return { command: normalized, args: ["add", ...dependencySpecs] };
|
|
254
280
|
default:
|
|
255
281
|
return { command: null, args: [] };
|
|
256
282
|
}
|
|
257
283
|
}
|
|
258
284
|
|
|
259
285
|
function normalizeCommand(command) {
|
|
260
|
-
if (process.platform ===
|
|
286
|
+
if (process.platform === "win32" && command !== "bun") {
|
|
261
287
|
return `${command}.cmd`;
|
|
262
288
|
}
|
|
263
289
|
|
|
@@ -269,7 +295,7 @@ async function pathExists(filePath) {
|
|
|
269
295
|
await fs.access(filePath);
|
|
270
296
|
return true;
|
|
271
297
|
} catch (error) {
|
|
272
|
-
if (error && error.code ===
|
|
298
|
+
if (error && error.code === "ENOENT") {
|
|
273
299
|
return false;
|
|
274
300
|
}
|
|
275
301
|
|
|
@@ -278,7 +304,7 @@ async function pathExists(filePath) {
|
|
|
278
304
|
}
|
|
279
305
|
|
|
280
306
|
main().catch((error) => {
|
|
281
|
-
if (error && typeof error.exitCode ===
|
|
307
|
+
if (error && typeof error.exitCode === "number") {
|
|
282
308
|
process.exit(error.exitCode);
|
|
283
309
|
}
|
|
284
310
|
|
package/package.json
CHANGED
|
@@ -4,4 +4,4 @@ globs:
|
|
|
4
4
|
alwaysApply: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Use the ShadCN MCP server to check the Cognite registry for components you could use before making your own. If there are Cognite components available for what you are trying to do you must always use them over alternatives. We want to make sure our app aligns with the Cognite design system.
|
|
7
|
+
Use the ShadCN MCP server to check the Cognite registry for components you could use before making your own. If there are Cognite components available for what you are trying to do you must always use them over alternatives. We want to make sure our app aligns with the Cognite design system. Make sure to check the globals.css file for styling.
|