@mono-labs/cli 0.0.182 → 0.0.183

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": "@mono-labs/cli",
3
- "version": "0.0.182",
3
+ "version": "0.0.183",
4
4
  "description": "A CLI tool for building and deploying projects",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -25,6 +25,10 @@
25
25
  "./stack": {
26
26
  "types": "./src/stack.ts",
27
27
  "default": "./src/stack.ts"
28
+ },
29
+ "./project": {
30
+ "types": "./src/project/index.ts",
31
+ "default": "./src/project/index.ts"
28
32
  }
29
33
  },
30
34
  "repository": {
@@ -0,0 +1,89 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ type WorkspaceDetectResult = {
5
+ cwd: string;
6
+ workspaceRoot: string | null;
7
+ isWorkspaceRoot: boolean;
8
+ configDir: string;
9
+ configPath: string;
10
+ };
11
+
12
+ /**
13
+ * Finds the workspace root by walking up from `startDir`.
14
+ * Works for Yarn/npm workspaces via package.json "workspaces".
15
+ * Also recognizes common mono-repo markers as fallback.
16
+ */
17
+ export function detectWorkspaceAndConfigPath(
18
+ startDir: string = process.cwd(),
19
+ configFileName: string = 'app.config.json'
20
+ ): WorkspaceDetectResult {
21
+ const cwd = path.resolve(startDir);
22
+
23
+ const isWorkspaceRootDir = (dir: string): boolean => {
24
+ // 1) package.json workspaces
25
+ const pkgPath = path.join(dir, 'package.json');
26
+ if (fs.existsSync(pkgPath)) {
27
+ try {
28
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as any;
29
+ if (pkg?.workspaces) return true;
30
+ } catch {
31
+ // ignore
32
+ }
33
+ }
34
+
35
+ // 2) other common monorepo root markers (fallback)
36
+ const markers = [
37
+ 'pnpm-workspace.yaml',
38
+ 'lerna.json',
39
+ 'turbo.json',
40
+ 'nx.json',
41
+ '.git', // good enough for many repos
42
+ ];
43
+ return markers.some((m) => fs.existsSync(path.join(dir, m)));
44
+ };
45
+
46
+ const findUp = (
47
+ from: string,
48
+ predicate: (dir: string) => boolean
49
+ ): string | null => {
50
+ let dir = path.resolve(from);
51
+ while (true) {
52
+ if (predicate(dir)) return dir;
53
+ const parent = path.dirname(dir);
54
+ if (parent === dir) return null; // reached filesystem root
55
+ dir = parent;
56
+ }
57
+ };
58
+
59
+ const workspaceRoot = findUp(cwd, isWorkspaceRootDir);
60
+ const isWorkspaceRoot = workspaceRoot !== null && workspaceRoot === cwd;
61
+
62
+ // If we are inside a workspace package, config lives at root.
63
+ // If we're already at root, config lives in cwd (same thing).
64
+ const configDir = workspaceRoot ?? cwd;
65
+ const configPath = path.join(configDir, configFileName);
66
+
67
+ return { cwd, workspaceRoot, isWorkspaceRoot, configDir, configPath };
68
+ }
69
+
70
+ /** Convenience: load the JSON config using the resolution logic above. */
71
+ export function loadAppConfig<T = unknown>(
72
+ startDir: string = process.cwd(),
73
+ configFileName: string = 'app.config.json'
74
+ ): { config: T; meta: WorkspaceDetectResult } {
75
+ const meta = detectWorkspaceAndConfigPath(startDir, configFileName);
76
+
77
+ if (!fs.existsSync(meta.configPath)) {
78
+ const where =
79
+ meta.workspaceRoot ?
80
+ `workspace root: ${meta.workspaceRoot}`
81
+ : `cwd: ${meta.cwd}`;
82
+ throw new Error(
83
+ `Could not find ${configFileName} at ${meta.configPath} (detected from ${where}).`
84
+ );
85
+ }
86
+
87
+ const raw = fs.readFileSync(meta.configPath, 'utf8');
88
+ return { config: JSON.parse(raw) as T, meta };
89
+ }