@erudit-js/cli 3.0.0-dev.10

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 ADDED
@@ -0,0 +1,12 @@
1
+ # 📟 Erudit CLI
2
+
3
+ Command Line Interface for [Erudit](https://github.com/erudit-js/erudit).
4
+
5
+ CLI is accessible via `erudit` or `erudit-cli` commands.
6
+
7
+ ## Commands
8
+
9
+ - `init`
10
+ - `dev`
11
+ - `build`
12
+ - `preview`
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { run } from '../dist/index.mjs';
4
+
5
+ run();
@@ -0,0 +1,3 @@
1
+ declare function run(): void;
2
+
3
+ export { run };
@@ -0,0 +1,3 @@
1
+ declare function run(): void;
2
+
3
+ export { run };
package/dist/index.mjs ADDED
@@ -0,0 +1,438 @@
1
+ import { defineCommand, runMain } from 'citty';
2
+ import { brandColorLogotype } from '@erudit-js/cog/utils/brandNode';
3
+ import consola$1, { consola } from 'consola';
4
+ import chalk from 'chalk';
5
+ import { existsSync, lstatSync, readdirSync, rmSync, mkdirSync, writeFileSync } from 'node:fs';
6
+ import { resolvePaths } from '@erudit-js/cog/kit';
7
+ import * as fs from 'node:fs/promises';
8
+ import * as path from 'node:path';
9
+ import { spawn } from 'node:child_process';
10
+
11
+ const version = "3.0.0-dev.10";
12
+
13
+ function resolvePath(path) {
14
+ path = resolvePaths(path);
15
+ path = path.endsWith("/") ? path.slice(0, -1) : path;
16
+ if (existsSync(path) && !lstatSync(path).isDirectory())
17
+ throw new Error(
18
+ `Path "${chalk.yellowBright(path)}" is not a directory!`
19
+ );
20
+ return path;
21
+ }
22
+
23
+ const init = defineCommand({
24
+ meta: {
25
+ name: "Init",
26
+ description: "Creates a new Erudit project at specified path"
27
+ },
28
+ args: {
29
+ path: {
30
+ type: "positional",
31
+ description: "Path for the new Erudit project",
32
+ required: true,
33
+ valueHint: chalk.gray(
34
+ `"${chalk.greenBright(".")}" OR "${chalk.greenBright("path/to/project")}"`
35
+ )
36
+ }
37
+ },
38
+ async run({ args }) {
39
+ consola.start("Resolving project path...");
40
+ const projectPath = resolvePath(args.path);
41
+ if (projectPath === void 0) return;
42
+ if (existsSync(projectPath) && readdirSync(projectPath).length > 0)
43
+ throw new Error(
44
+ `Directory "${chalk.yellowBright(projectPath)}" is not empty!`
45
+ );
46
+ consola.success(
47
+ "Resolved project path:",
48
+ chalk.greenBright(projectPath)
49
+ );
50
+ consola.start("Creating project directory...");
51
+ try {
52
+ try {
53
+ rmSync(projectPath, { recursive: true });
54
+ } catch (error) {
55
+ if (error?.code !== "ENOENT") {
56
+ throw error;
57
+ }
58
+ }
59
+ mkdirSync(projectPath, { recursive: true });
60
+ } catch (error) {
61
+ throw new Error(
62
+ `Failed to prepare project directory "${chalk.yellowBright(projectPath)}"!
63
+
64
+ ${error}`
65
+ );
66
+ }
67
+ consola.success("Project directory created!");
68
+ consola.start("Creating project files...");
69
+ consola.success("Project files created!");
70
+ }
71
+ });
72
+
73
+ function logCommand(command) {
74
+ consola.info(`Running command: ${chalk.cyanBright(command)}`);
75
+ console.log();
76
+ }
77
+
78
+ async function alias2Relative(baseDir, toReplaceDir) {
79
+ baseDir = resolvePaths(baseDir);
80
+ toReplaceDir = resolvePaths(toReplaceDir);
81
+ if (!existsSync(baseDir)) {
82
+ console.log(`Base directory ${baseDir} does not exist. Skipping...`);
83
+ return;
84
+ }
85
+ if (!existsSync(toReplaceDir)) {
86
+ console.log(
87
+ `Target directory ${toReplaceDir} does not exist. Skipping...`
88
+ );
89
+ return;
90
+ }
91
+ const ALIASES_RESOLVED_FILE = path.join(toReplaceDir, "ALIASES_RESOLVED");
92
+ if (existsSync(ALIASES_RESOLVED_FILE)) {
93
+ console.log(`Aliases already resolved in ${toReplaceDir}. Skipping...`);
94
+ return;
95
+ }
96
+ const replaceMap = {
97
+ "@erudit": "./",
98
+ "@module": "./module",
99
+ "@server": "./server/plugin",
100
+ "@shared": "./shared",
101
+ "@app": "./app"
102
+ };
103
+ const allFiles = await findAllFiles(toReplaceDir);
104
+ for (const filePath of allFiles) {
105
+ await processFile(filePath, baseDir, replaceMap);
106
+ }
107
+ await fs.writeFile(ALIASES_RESOLVED_FILE, (/* @__PURE__ */ new Date()).toISOString());
108
+ console.log(`All aliases in ${toReplaceDir} resolved successfully!`);
109
+ }
110
+ async function findAllFiles(dir) {
111
+ const results = [];
112
+ try {
113
+ const entries = await fs.readdir(dir, { withFileTypes: true });
114
+ for (const entry of entries) {
115
+ const fullPath = path.join(dir, entry.name);
116
+ const ignore = [];
117
+ if (entry.isDirectory()) {
118
+ if (!ignore.includes(entry.name)) {
119
+ results.push(...await findAllFiles(fullPath));
120
+ }
121
+ } else if (entry.isFile() && /\.(js|ts|vue)$/.test(entry.name)) {
122
+ results.push(fullPath);
123
+ }
124
+ }
125
+ } catch (error) {
126
+ console.error(`Error reading directory ${dir}:`, error);
127
+ }
128
+ return results;
129
+ }
130
+ async function processFile(filePath, rootDir, replaceMap) {
131
+ try {
132
+ let content = await fs.readFile(filePath, "utf8");
133
+ let modified = false;
134
+ for (const [alias, targetBasePath] of Object.entries(replaceMap)) {
135
+ const staticAliasPattern = new RegExp(
136
+ `(import|from)\\s+(['"])${alias}/([^'"]+)(['"])`,
137
+ "g"
138
+ );
139
+ const dynamicAliasPattern = new RegExp(
140
+ `(import\\s*\\()\\s*(['"])${alias}/([^'"]+)(['"])\\s*\\)`,
141
+ "g"
142
+ );
143
+ const calculateRelativePath = (importPath) => {
144
+ const currentFileDir = path.dirname(filePath);
145
+ const targetAbsoluteDir = path.join(
146
+ rootDir,
147
+ targetBasePath.replace(/^\.\//, "")
148
+ );
149
+ const targetAbsolutePath = path.join(
150
+ targetAbsoluteDir,
151
+ importPath
152
+ );
153
+ let relativePath = path.relative(
154
+ currentFileDir,
155
+ targetAbsolutePath
156
+ );
157
+ if (!relativePath.startsWith(".")) {
158
+ relativePath = "./" + relativePath;
159
+ }
160
+ return relativePath.replace(/\\/g, "/");
161
+ };
162
+ content = content.replace(
163
+ staticAliasPattern,
164
+ (match, statement, openQuote, importPath, closeQuote) => {
165
+ const relativePath = calculateRelativePath(importPath);
166
+ modified = true;
167
+ return `${statement} ${openQuote}${relativePath}${closeQuote}`;
168
+ }
169
+ );
170
+ content = content.replace(
171
+ dynamicAliasPattern,
172
+ (match, importStatement, openQuote, importPath, closeQuote) => {
173
+ const relativePath = calculateRelativePath(importPath);
174
+ modified = true;
175
+ return `${importStatement}${openQuote}${relativePath}${closeQuote})`;
176
+ }
177
+ );
178
+ }
179
+ if (modified) {
180
+ await fs.writeFile(filePath, content, "utf8");
181
+ console.log(`Updated aliases in: ${filePath}`);
182
+ }
183
+ } catch (error) {
184
+ console.error(`Error processing file ${filePath}:`, error);
185
+ }
186
+ }
187
+
188
+ async function prepare$1(projectPath, eruditPath) {
189
+ const eruditBuildDir = `${projectPath}/.erudit`;
190
+ const distDir = `${projectPath}/dist`;
191
+ const nodeModules = `${projectPath}/node_modules`;
192
+ const nodeModulesErudit = `${nodeModules}/erudit`;
193
+ if (existsSync(nodeModulesErudit)) {
194
+ consola.start("Resolving aliases in dependencies...");
195
+ await alias2Relative(nodeModulesErudit, nodeModulesErudit);
196
+ await alias2Relative(
197
+ nodeModulesErudit,
198
+ nodeModules + "/@erudit-js/bitran-elements"
199
+ );
200
+ consola.success("Resolved aliases in dependencies!");
201
+ }
202
+ consola.start("Cleaning up...");
203
+ if (existsSync(distDir)) rmSync(distDir, { recursive: true });
204
+ if (existsSync(eruditBuildDir)) rmSync(eruditBuildDir, { recursive: true });
205
+ consola.success("Cleaned up!");
206
+ consola.start("Generating Erudit build files...");
207
+ mkdirSync(eruditBuildDir, { recursive: true });
208
+ mkdirSync(eruditBuildDir + "/nuxt", { recursive: true });
209
+ writeFileSync(
210
+ `${eruditBuildDir}/nuxt/nuxt.config.ts`,
211
+ `
212
+ export default {
213
+ compatibilityDate: '2025-01-01',
214
+ extends: ['${eruditPath}'],
215
+ future: {
216
+ compatibilityVersion: 4,
217
+ },
218
+ }
219
+ `
220
+ );
221
+ writeFileSync(
222
+ `${eruditBuildDir}/tsconfig.json`,
223
+ JSON.stringify(
224
+ {
225
+ extends: "./nuxt/.nuxt/tsconfig.json"
226
+ },
227
+ null,
228
+ 4
229
+ )
230
+ );
231
+ consola.success("Erudit build files ready!");
232
+ }
233
+
234
+ async function spawnNuxt(command, projectPath) {
235
+ return new Promise((resolve) => {
236
+ const onClose = (exitCode) => {
237
+ if (exitCode === 1337) _spawnNuxt();
238
+ else if (exitCode !== 0)
239
+ throw new Error(`Nuxt exited with code ${exitCode}!`);
240
+ else resolve();
241
+ };
242
+ const _spawnNuxt = () => {
243
+ const nuxtProcess = spawn(
244
+ `nuxt ${command} ${projectPath}/.erudit/nuxt`,
245
+ {
246
+ shell: true,
247
+ stdio: "inherit",
248
+ env: {
249
+ ...process.env,
250
+ ERUDIT_PROJECT_DIR: projectPath
251
+ }
252
+ }
253
+ );
254
+ nuxtProcess.on("close", onClose);
255
+ };
256
+ _spawnNuxt();
257
+ });
258
+ }
259
+
260
+ const eruditPathArg = {
261
+ eruditPath: {
262
+ type: "string",
263
+ description: "Custom Erudit Nuxt Layer location",
264
+ required: false,
265
+ default: "erudit"
266
+ // Let `nuxi` find erudit in project dependencies
267
+ }
268
+ };
269
+ const projectPathArg = {
270
+ projectPath: {
271
+ type: "positional",
272
+ description: "Erudit project location",
273
+ required: false,
274
+ default: "."
275
+ }
276
+ };
277
+ function resolveArgPaths(projectPath, eruditPath) {
278
+ consola.start("Resolving project path...");
279
+ projectPath = resolvePath(projectPath);
280
+ consola.success("Resolved project path:", chalk.greenBright(projectPath));
281
+ consola.start("Resolving Erudit Nuxt Layer path...");
282
+ if (eruditPath === "erudit") {
283
+ consola.success(`'nuxi' will find Erudit in your dependencies!`);
284
+ } else {
285
+ eruditPath = resolvePath(eruditPath);
286
+ consola.warn(
287
+ "Custom Erudit Nuxt Layer path will be used: " + chalk.yellowBright(eruditPath)
288
+ );
289
+ }
290
+ return {
291
+ projectPath,
292
+ eruditPath
293
+ };
294
+ }
295
+
296
+ const prepare = defineCommand({
297
+ meta: {
298
+ name: "Prepare",
299
+ description: "Creates a .erudit directory in your project and generates build files"
300
+ },
301
+ args: {
302
+ ...projectPathArg,
303
+ ...eruditPathArg
304
+ },
305
+ async run({ args }) {
306
+ logCommand("prepare");
307
+ const { projectPath, eruditPath } = resolveArgPaths(
308
+ args.projectPath,
309
+ args.eruditPath
310
+ );
311
+ await prepare$1(projectPath, eruditPath);
312
+ consola.start("Generating Nuxt build files...");
313
+ await spawnNuxt("prepare", projectPath);
314
+ consola.success("Nuxt is prepared!");
315
+ }
316
+ });
317
+
318
+ const dev = defineCommand({
319
+ meta: {
320
+ name: "Dev",
321
+ description: "Runs Erudit project in development mode"
322
+ },
323
+ args: {
324
+ ...projectPathArg,
325
+ ...eruditPathArg
326
+ },
327
+ async run({ args }) {
328
+ logCommand("dev");
329
+ const { projectPath, eruditPath } = resolveArgPaths(
330
+ args.projectPath,
331
+ args.eruditPath
332
+ );
333
+ await prepare$1(projectPath, eruditPath);
334
+ consola.start("Starting Nuxt dev...");
335
+ await spawnNuxt("dev", projectPath);
336
+ }
337
+ });
338
+
339
+ const generate = defineCommand({
340
+ meta: {
341
+ name: "Generate",
342
+ description: "Generates fully static production ready Erudit site"
343
+ },
344
+ args: {
345
+ ...projectPathArg,
346
+ ...eruditPathArg
347
+ },
348
+ async run({ args }) {
349
+ logCommand("generate");
350
+ const { projectPath, eruditPath } = resolveArgPaths(
351
+ args.projectPath,
352
+ args.eruditPath
353
+ );
354
+ await prepare$1(projectPath, eruditPath);
355
+ consola.start("Starting Nuxt generate...");
356
+ await spawnNuxt("generate", projectPath);
357
+ }
358
+ });
359
+
360
+ const preview = defineCommand({
361
+ meta: {
362
+ name: "Preview",
363
+ description: "Preview created static Erudit site"
364
+ },
365
+ args: {
366
+ project: {
367
+ type: "positional",
368
+ description: "Project path",
369
+ required: false,
370
+ default: "."
371
+ }
372
+ },
373
+ async run({ args }) {
374
+ consola.start("Resolving project path...");
375
+ const projectPath = resolvePath(args.project);
376
+ consola.success(
377
+ "Resolved project path:",
378
+ chalk.greenBright(projectPath)
379
+ );
380
+ const distPath = `${projectPath}/dist`;
381
+ if (!existsSync(distPath))
382
+ throw new Error(
383
+ `No 'dist' folder found! Did you run 'erudit build'?`
384
+ );
385
+ spawn("npx http-server . -p 3000", {
386
+ shell: true,
387
+ stdio: "inherit",
388
+ env: process.env,
389
+ cwd: distPath
390
+ });
391
+ }
392
+ });
393
+
394
+ const build = defineCommand({
395
+ meta: {
396
+ name: "Build",
397
+ description: "Builds Erudit project for fast and convenient content writing"
398
+ },
399
+ args: {
400
+ ...projectPathArg,
401
+ ...eruditPathArg
402
+ },
403
+ async run({ args }) {
404
+ logCommand("build");
405
+ const { projectPath, eruditPath } = resolveArgPaths(
406
+ args.projectPath,
407
+ args.eruditPath
408
+ );
409
+ await prepare$1(projectPath, eruditPath);
410
+ consola$1.start("Starting Nuxt build...");
411
+ await spawnNuxt("build", projectPath);
412
+ }
413
+ });
414
+
415
+ const main = defineCommand({
416
+ meta: {
417
+ name: "Erudit CLI",
418
+ description: "Command Line Interface for Erudit!",
419
+ version
420
+ },
421
+ subCommands: {
422
+ init,
423
+ prepare,
424
+ dev,
425
+ build,
426
+ generate,
427
+ preview
428
+ },
429
+ setup() {
430
+ console.log(brandColorLogotype);
431
+ }
432
+ });
433
+
434
+ function run() {
435
+ runMain(main);
436
+ }
437
+
438
+ export { run };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@erudit-js/cli",
3
+ "version": "3.0.0-dev.10",
4
+ "type": "module",
5
+ "description": "📟 Command Line Interface for Erudit",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/erudit-js/erudit.git",
10
+ "directory": "packages/cli"
11
+ },
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": "./dist/index.mjs",
15
+ "./cli": "./bin/erudit-cli.mjs"
16
+ },
17
+ "bin": {
18
+ "erudit-cli": "bin/erudit-cli.mjs",
19
+ "erudit": "bin/erudit-cli.mjs"
20
+ },
21
+ "scripts": {
22
+ "dev": "bun unbuild --stub",
23
+ "build": "bun run prepack",
24
+ "prepack": "bun unbuild"
25
+ },
26
+ "files": [
27
+ "bin",
28
+ "dist"
29
+ ],
30
+ "dependencies": {
31
+ "@erudit-js/cog": "3.0.0-dev.10",
32
+ "chalk": "^5.4.1",
33
+ "citty": "^0.1.6",
34
+ "consola": "^3.4.0"
35
+ },
36
+ "devDependencies": {
37
+ "unbuild": "^3.3.1"
38
+ }
39
+ }