@nuasite/cli 0.51.0 → 0.52.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuasite/cli",
3
- "version": "0.51.0",
3
+ "version": "0.52.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "files": [
@@ -23,8 +23,8 @@
23
23
  "prepack": "bun run ../../scripts/workspace-deps/resolve-deps.ts"
24
24
  },
25
25
  "dependencies": {
26
- "@nuasite/cms": "0.51.0",
27
- "@nuasite/cms-core": "0.51.0"
26
+ "@nuasite/cms": "0.52.0",
27
+ "@nuasite/cms-core": "0.52.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/bun": "1.3.11"
package/src/check.ts CHANGED
@@ -1,4 +1,6 @@
1
- import { checkContent, createNodeFs, formatCheckReport } from '@nuasite/cms-core'
1
+ import { checkContent, type CheckReport, createNodeFs, formatCheckReport } from '@nuasite/cms-core'
2
+ import { existsSync, readdirSync } from 'node:fs'
3
+ import path from 'node:path'
2
4
 
3
5
  export interface CheckOptions {
4
6
  cwd: string
@@ -7,22 +9,70 @@ export interface CheckOptions {
7
9
  strict: boolean
8
10
  }
9
11
 
12
+ const ASTRO_CONFIG_NAMES = ['astro.config.ts', 'astro.config.mts', 'astro.config.mjs', 'astro.config.js']
13
+
14
+ const hasAstroConfig = (dir: string): boolean => ASTRO_CONFIG_NAMES.some(name => existsSync(path.join(dir, name)))
15
+
16
+ /**
17
+ * The Astro apps to check, relative to `cwd`.
18
+ *
19
+ * Running this at a monorepo root has to work: that is where an agent's workspace and a
20
+ * developer's shell both start, and `bun run build` there builds something else entirely
21
+ * (admin, api, worker). Every `packages/*` app is checked, not just the first — a repo with
22
+ * two sites must not have one of them silently skipped.
23
+ */
24
+ export function astroRoots(cwd: string): string[] {
25
+ if (hasAstroConfig(cwd)) return ['.']
26
+
27
+ const packagesDir = path.join(cwd, 'packages')
28
+ if (!existsSync(packagesDir)) return []
29
+
30
+ return readdirSync(packagesDir, { withFileTypes: true })
31
+ .filter(entry => entry.isDirectory())
32
+ .map(entry => entry.name)
33
+ .sort()
34
+ .filter(name => hasAstroConfig(path.join(packagesDir, name)))
35
+ .map(name => path.join('packages', name))
36
+ }
37
+
38
+ /** Re-root a sub-project's findings on the directory the command was run from. */
39
+ function prefixed(report: CheckReport, root: string): CheckReport {
40
+ if (root === '.') return report
41
+ return {
42
+ ...report,
43
+ findings: report.findings.map(finding => ({ ...finding, file: path.join(root, finding.file) })),
44
+ }
45
+ }
46
+
10
47
  /** Validate the content collections and return the process exit code. */
11
48
  export async function check(options: CheckOptions): Promise<number> {
12
- const report = await checkContent(createNodeFs(options.cwd))
49
+ const roots = astroRoots(options.cwd)
13
50
 
14
- if (options.json) {
15
- console.log(JSON.stringify(report, null, 2))
16
- } else {
17
- const formatted = formatCheckReport(report)
18
- if (formatted) console.log(formatted + '\n')
51
+ if (roots.length === 0) {
52
+ console.error(`No astro.config.* found in ${options.cwd} or its packages/*. Run this in an Astro project.`)
53
+ return 1
54
+ }
55
+
56
+ const reports = await Promise.all(
57
+ roots.map(async root => prefixed(await checkContent(createNodeFs(path.join(options.cwd, root))), root)),
58
+ )
59
+
60
+ const report: CheckReport = {
61
+ findings: reports.flatMap(one => one.findings),
62
+ collections: reports.reduce((total, one) => total + one.collections, 0),
63
+ entries: reports.reduce((total, one) => total + one.entries, 0),
19
64
  }
20
65
 
21
66
  const errors = report.findings.filter(finding => finding.severity === 'error').length
22
67
  const warnings = report.findings.length - errors
23
68
 
24
- if (!options.json) {
25
- const counts = `${report.collections} collection(s), ${report.entries} entries`
69
+ if (options.json) {
70
+ console.log(JSON.stringify({ ...report, roots }, null, 2))
71
+ } else {
72
+ const formatted = formatCheckReport(report)
73
+ if (formatted) console.log(formatted + '\n')
74
+ const where = roots.length === 1 && roots[0] === '.' ? '' : ` in ${roots.join(', ')}`
75
+ const counts = `${report.collections} collection(s), ${report.entries} entries${where}`
26
76
  console.log(errors === 0 && warnings === 0 ? `${counts} — no problems found` : `${counts} — ${errors} error(s), ${warnings} warning(s)`)
27
77
  }
28
78