@mono-labs/cli 0.0.244 → 0.0.248
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/dist/{types/index.d.ts → index.d.ts} +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/{types/lib → lib}/app.d.ts +1 -0
- package/dist/lib/app.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/boot.d.ts +1 -0
- package/dist/lib/commands/build-process/boot.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/cliFactory.d.ts +1 -0
- package/dist/lib/commands/build-process/cliFactory.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/dataLayer.d.ts +1 -0
- package/dist/lib/commands/build-process/dataLayer.d.ts.map +1 -0
- package/dist/lib/commands/build-process/index.d.ts +2 -0
- package/dist/lib/commands/build-process/index.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/readEnv.d.ts +1 -0
- package/dist/lib/commands/build-process/readEnv.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/runMonoCommand.d.ts +1 -0
- package/dist/lib/commands/build-process/runMonoCommand.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/runners/processManager.d.ts +1 -0
- package/dist/lib/commands/build-process/runners/processManager.d.ts.map +1 -0
- package/dist/lib/commands/build-process/runners/processManager.js +15 -0
- package/dist/{types/lib → lib}/commands/build-process/runners/runBackground.d.ts +1 -0
- package/dist/lib/commands/build-process/runners/runBackground.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/runners/runForeground.d.ts +1 -0
- package/dist/lib/commands/build-process/runners/runForeground.d.ts.map +1 -0
- package/dist/lib/commands/build-process/runners/runForeground.js +1 -1
- package/dist/{types/lib → lib}/commands/build-process/test.d.ts +1 -0
- package/dist/lib/commands/build-process/test.d.ts.map +1 -0
- package/dist/lib/commands/build-process/testflag.d.ts +2 -0
- package/dist/lib/commands/build-process/testflag.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/build-process/validators.d.ts +1 -0
- package/dist/lib/commands/build-process/validators.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/loadFromRoot.d.ts +1 -0
- package/dist/lib/commands/loadFromRoot.d.ts.map +1 -0
- package/dist/lib/commands/prune/index.d.ts +2 -0
- package/dist/lib/commands/prune/index.d.ts.map +1 -0
- package/dist/{types/lib → lib}/commands/prune/prune.d.ts +1 -0
- package/dist/lib/commands/prune/prune.d.ts.map +1 -0
- package/dist/{types/lib → lib}/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/{types/lib → lib}/filterUnwantedEnvVars.d.ts +1 -0
- package/dist/lib/filterUnwantedEnvVars.d.ts.map +1 -0
- package/dist/{types/lib → lib}/generateNewEnvList.d.ts +1 -0
- package/dist/lib/generateNewEnvList.d.ts.map +1 -0
- package/dist/{types/lib → lib}/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +2 -2
- package/dist/src/cdk.d.ts +2 -0
- package/dist/src/cdk.d.ts.map +1 -0
- package/dist/src/{cdk/cdk.js → cdk.js} +4 -3
- package/dist/src/expo.d.ts +2 -0
- package/dist/src/expo.d.ts.map +1 -0
- package/dist/src/expo.js +6 -111
- package/dist/{types/src → src}/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +7 -7
- package/dist/src/project.d.ts +3 -0
- package/dist/src/project.d.ts.map +1 -0
- package/dist/src/project.js +14 -0
- package/dist/{types/src → src}/stack.d.ts +1 -0
- package/dist/src/stack.d.ts.map +1 -0
- package/dist/src/stack.js +4 -4
- package/dist/src/tools.d.ts +2 -0
- package/dist/src/tools.d.ts.map +1 -0
- package/dist/src/tools.js +5 -36
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/lib/commands/build-process/runners/processManager.ts +18 -0
- package/lib/commands/build-process/runners/runForeground.ts +1 -1
- package/lib/index.ts +1 -1
- package/package.json +40 -24
- package/src/cdk.ts +2 -0
- package/src/expo.ts +2 -116
- package/src/index.ts +2 -2
- package/src/project.ts +19 -0
- package/src/stack.ts +3 -3
- package/src/tools.ts +2 -39
- package/README.md +0 -123
- package/dist/src/cdk/index.js +0 -17
- package/dist/src/expo-files/filterUnwantedEnvVars.js +0 -147
- package/dist/src/loadFromRoot.js +0 -115
- package/dist/src/merge-env.js +0 -25
- package/dist/src/project/build-mono-readme.js +0 -456
- package/dist/src/project/build-readme.js +0 -4
- package/dist/src/project/generate-docs.js +0 -73
- package/dist/src/project/generate-readme.js +0 -309
- package/dist/src/project/index.js +0 -120
- package/dist/src/project/merge-env.js +0 -31
- package/dist/types/lib/commands/build-process/index.d.ts +0 -1
- package/dist/types/lib/commands/build-process/testflag.d.ts +0 -1
- package/dist/types/lib/commands/prune/index.d.ts +0 -1
- package/dist/types/src/cdk/cdk.d.ts +0 -1
- package/dist/types/src/cdk/index.d.ts +0 -1
- package/dist/types/src/expo-files/filterUnwantedEnvVars.d.ts +0 -3
- package/dist/types/src/expo.d.ts +0 -4
- package/dist/types/src/loadFromRoot.d.ts +0 -32
- package/dist/types/src/merge-env.d.ts +0 -1
- package/dist/types/src/project/build-mono-readme.d.ts +0 -1
- package/dist/types/src/project/build-readme.d.ts +0 -2
- package/dist/types/src/project/generate-docs.d.ts +0 -11
- package/dist/types/src/project/generate-readme.d.ts +0 -1
- package/dist/types/src/project/index.d.ts +0 -40
- package/dist/types/src/project/merge-env.d.ts +0 -1
- package/dist/types/src/tools.d.ts +0 -3
- package/src/cdk/cdk.ts +0 -1
- package/src/cdk/index.ts +0 -1
- package/src/expo-files/filterUnwantedEnvVars.ts +0 -155
- package/src/loadFromRoot.ts +0 -145
- package/src/merge-env.ts +0 -24
- package/src/project/build-mono-readme.ts +0 -545
- package/src/project/build-readme.ts +0 -2
- package/src/project/generate-docs.ts +0 -83
- package/src/project/generate-readme.ts +0 -351
- package/src/project/index.ts +0 -187
- package/src/project/merge-env.ts +0 -32
package/dist/src/loadFromRoot.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
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.findProjectRoot = findProjectRoot;
|
|
7
|
-
exports.getRootDirectory = getRootDirectory;
|
|
8
|
-
exports.getRootJson = getRootJson;
|
|
9
|
-
exports.resolveMonoDirectory = resolveMonoDirectory;
|
|
10
|
-
exports.getMonoFiles = getMonoFiles;
|
|
11
|
-
exports.getMonoConfig = getMonoConfig;
|
|
12
|
-
const fs_1 = __importDefault(require("fs"));
|
|
13
|
-
const path_1 = __importDefault(require("path"));
|
|
14
|
-
/* ------------------------------------------------------------------
|
|
15
|
-
* Helpers
|
|
16
|
-
* ------------------------------------------------------------------ */
|
|
17
|
-
/**
|
|
18
|
-
* Walk up from cwd until we find a directory containing package.json.
|
|
19
|
-
* This is treated as the project root.
|
|
20
|
-
*/
|
|
21
|
-
function findProjectRoot(startDir = process.cwd()) {
|
|
22
|
-
let current = startDir;
|
|
23
|
-
while (true) {
|
|
24
|
-
const pkg = path_1.default.join(current, 'package.json');
|
|
25
|
-
if (fs_1.default.existsSync(pkg))
|
|
26
|
-
return current;
|
|
27
|
-
const parent = path_1.default.dirname(current);
|
|
28
|
-
if (parent === current)
|
|
29
|
-
break;
|
|
30
|
-
current = parent;
|
|
31
|
-
}
|
|
32
|
-
// Fallback: use cwd
|
|
33
|
-
return startDir;
|
|
34
|
-
}
|
|
35
|
-
function getRootDirectory() {
|
|
36
|
-
return findProjectRoot();
|
|
37
|
-
}
|
|
38
|
-
function getRootJson() {
|
|
39
|
-
const root = getRootDirectory();
|
|
40
|
-
const jsonPath = path_1.default.join(root, 'package.json');
|
|
41
|
-
if (!fs_1.default.existsSync(jsonPath)) {
|
|
42
|
-
throw new Error(`package.json not found in ${root}`);
|
|
43
|
-
}
|
|
44
|
-
return JSON.parse(fs_1.default.readFileSync(jsonPath, 'utf-8'));
|
|
45
|
-
}
|
|
46
|
-
/* ------------------------------------------------------------------
|
|
47
|
-
* Mono (.mono) handling
|
|
48
|
-
* ------------------------------------------------------------------ */
|
|
49
|
-
const DISALLOWED_FILES = new Set(['tools']);
|
|
50
|
-
function readJsonFile(filePath) {
|
|
51
|
-
return JSON.parse(fs_1.default.readFileSync(filePath, 'utf-8'));
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Resolve the .mono directory.
|
|
55
|
-
* Priority:
|
|
56
|
-
* 1. project root/.mono
|
|
57
|
-
* 2. cwd/.mono
|
|
58
|
-
*/
|
|
59
|
-
function resolveMonoDirectory() {
|
|
60
|
-
const root = getRootDirectory();
|
|
61
|
-
const rootMono = path_1.default.join(root, '.mono');
|
|
62
|
-
if (fs_1.default.existsSync(rootMono))
|
|
63
|
-
return rootMono;
|
|
64
|
-
const cwdMono = path_1.default.join(process.cwd(), '.mono');
|
|
65
|
-
if (fs_1.default.existsSync(cwdMono))
|
|
66
|
-
return cwdMono;
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
function getMonoFiles() {
|
|
70
|
-
const dir = resolveMonoDirectory();
|
|
71
|
-
if (!dir)
|
|
72
|
-
return [];
|
|
73
|
-
return fs_1.default
|
|
74
|
-
.readdirSync(dir)
|
|
75
|
-
.filter((f) => f.endsWith('.json'))
|
|
76
|
-
.map((f) => path_1.default.join(dir, f));
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Load and validate mono configuration.
|
|
80
|
-
*/
|
|
81
|
-
function getMonoConfig() {
|
|
82
|
-
const monoDir = resolveMonoDirectory();
|
|
83
|
-
if (!monoDir) {
|
|
84
|
-
return {
|
|
85
|
-
files: {},
|
|
86
|
-
config: {
|
|
87
|
-
envMap: [],
|
|
88
|
-
workspace: { packageMaps: {} },
|
|
89
|
-
prodFlag: 'live',
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
const files = {};
|
|
94
|
-
let config = {
|
|
95
|
-
envMap: [],
|
|
96
|
-
workspace: { packageMaps: {} },
|
|
97
|
-
prodFlag: 'live',
|
|
98
|
-
};
|
|
99
|
-
for (const filePath of getMonoFiles()) {
|
|
100
|
-
const fileName = path_1.default.basename(filePath, '.json');
|
|
101
|
-
if (DISALLOWED_FILES.has(fileName)) {
|
|
102
|
-
throw new Error(`Disallowed file name in .mono directory: ${fileName}`);
|
|
103
|
-
}
|
|
104
|
-
const data = readJsonFile(filePath);
|
|
105
|
-
if (fileName === 'config') {
|
|
106
|
-
if (typeof data === 'object' && data !== null) {
|
|
107
|
-
config = data;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
files[fileName] = data;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return { files, config };
|
|
115
|
-
}
|
package/dist/src/merge-env.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
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.loadMergedEnv = loadMergedEnv;
|
|
7
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const dotenv_1 = __importDefault(require("dotenv"));
|
|
10
|
-
function loadMergedEnv() {
|
|
11
|
-
const ENV_PATH = node_path_1.default.resolve(process.cwd(), '.env');
|
|
12
|
-
const ENV_LOCAL_PATH = node_path_1.default.resolve(process.cwd(), '.env.local');
|
|
13
|
-
const base = node_fs_1.default.existsSync(ENV_PATH) ? dotenv_1.default.parse(node_fs_1.default.readFileSync(ENV_PATH)) : {};
|
|
14
|
-
const local = node_fs_1.default.existsSync(ENV_LOCAL_PATH) ? dotenv_1.default.parse(node_fs_1.default.readFileSync(ENV_LOCAL_PATH)) : {};
|
|
15
|
-
const merged = {
|
|
16
|
-
...base,
|
|
17
|
-
...local,
|
|
18
|
-
};
|
|
19
|
-
for (const [key, value] of Object.entries(merged)) {
|
|
20
|
-
if (process.env[key] === undefined) {
|
|
21
|
-
process.env[key] = value;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return process.env;
|
|
25
|
-
}
|
|
@@ -1,456 +0,0 @@
|
|
|
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
|
-
// scripts/generate-readme.mjs
|
|
7
|
-
// Node >= 18 recommended
|
|
8
|
-
const node_fs_1 = require("node:fs");
|
|
9
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
-
const generate_docs_1 = require("./generate-docs");
|
|
11
|
-
const REPO_ROOT = node_path_1.default.resolve(process.cwd());
|
|
12
|
-
const MONO_DIR = node_path_1.default.join(REPO_ROOT, '.mono');
|
|
13
|
-
const ROOT_PKG_JSON = node_path_1.default.join(REPO_ROOT, 'package.json');
|
|
14
|
-
const OUTPUT_PATH = node_path_1.default.join(REPO_ROOT, 'docs');
|
|
15
|
-
const OUTPUT_README = node_path_1.default.join(OUTPUT_PATH, 'command-line.md');
|
|
16
|
-
async function ensureParentDir(filePath) {
|
|
17
|
-
const dir = node_path_1.default.dirname(filePath);
|
|
18
|
-
await node_fs_1.promises.mkdir(dir, { recursive: true });
|
|
19
|
-
}
|
|
20
|
-
// ---------- utils ----------
|
|
21
|
-
async function exists(p) {
|
|
22
|
-
try {
|
|
23
|
-
await node_fs_1.promises.access(p);
|
|
24
|
-
// Log existence check
|
|
25
|
-
return true;
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function isObject(v) {
|
|
32
|
-
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
33
|
-
}
|
|
34
|
-
function toPosix(p) {
|
|
35
|
-
return p.split(node_path_1.default.sep).join('/');
|
|
36
|
-
}
|
|
37
|
-
async function readJson(filePath) {
|
|
38
|
-
const raw = await node_fs_1.promises.readFile(filePath, 'utf8');
|
|
39
|
-
try {
|
|
40
|
-
const parsed = JSON.parse(raw);
|
|
41
|
-
return parsed;
|
|
42
|
-
}
|
|
43
|
-
catch (err) {
|
|
44
|
-
throw err;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
async function listDir(dir) {
|
|
48
|
-
const entries = await node_fs_1.promises.readdir(dir, { withFileTypes: true });
|
|
49
|
-
return entries;
|
|
50
|
-
}
|
|
51
|
-
function normalizeWorkspacePatterns(workspacesField) {
|
|
52
|
-
if (Array.isArray(workspacesField))
|
|
53
|
-
return workspacesField;
|
|
54
|
-
if (isObject(workspacesField) && Array.isArray(workspacesField.packages))
|
|
55
|
-
return workspacesField.packages;
|
|
56
|
-
return [];
|
|
57
|
-
}
|
|
58
|
-
function mdEscapeInline(s) {
|
|
59
|
-
return String(s ?? '').replaceAll('`', '\`');
|
|
60
|
-
}
|
|
61
|
-
function indentLines(s, spaces = 2) {
|
|
62
|
-
const pad = ' '.repeat(spaces);
|
|
63
|
-
return String(s ?? '')
|
|
64
|
-
.split('\n')
|
|
65
|
-
.map((l) => pad + l)
|
|
66
|
-
.join('\n');
|
|
67
|
-
}
|
|
68
|
-
// ---------- workspace glob matching (supports *, **, and plain segments) ----------
|
|
69
|
-
function matchSegment(patternSeg, name) {
|
|
70
|
-
if (patternSeg === '*')
|
|
71
|
-
return true;
|
|
72
|
-
if (!patternSeg.includes('*'))
|
|
73
|
-
return patternSeg === name;
|
|
74
|
-
const escaped = patternSeg.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
75
|
-
const regex = new RegExp('^' + escaped.replaceAll('*', '.*') + '$');
|
|
76
|
-
return regex.test(name);
|
|
77
|
-
}
|
|
78
|
-
async function expandWorkspacePattern(root, pattern) {
|
|
79
|
-
const segs = toPosix(pattern).split('/').filter(Boolean);
|
|
80
|
-
async function expandFrom(dir, segIndex) {
|
|
81
|
-
if (segIndex >= segs.length)
|
|
82
|
-
return [dir];
|
|
83
|
-
const seg = segs[segIndex];
|
|
84
|
-
if (seg === '**') {
|
|
85
|
-
const results = [];
|
|
86
|
-
results.push(...(await expandFrom(dir, segIndex + 1)));
|
|
87
|
-
const entries = await node_fs_1.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
88
|
-
for (const e of entries) {
|
|
89
|
-
if (!e.isDirectory())
|
|
90
|
-
continue;
|
|
91
|
-
results.push(...(await expandFrom(node_path_1.default.join(dir, e.name), segIndex)));
|
|
92
|
-
}
|
|
93
|
-
return results;
|
|
94
|
-
}
|
|
95
|
-
const entries = await node_fs_1.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
96
|
-
const results = [];
|
|
97
|
-
for (const e of entries) {
|
|
98
|
-
if (!e.isDirectory())
|
|
99
|
-
continue;
|
|
100
|
-
if (!matchSegment(seg, e.name))
|
|
101
|
-
continue;
|
|
102
|
-
results.push(...(await expandFrom(node_path_1.default.join(dir, e.name), segIndex + 1)));
|
|
103
|
-
}
|
|
104
|
-
return results;
|
|
105
|
-
}
|
|
106
|
-
const dirs = await expandFrom(root, 0);
|
|
107
|
-
const pkgDirs = [];
|
|
108
|
-
for (const d of dirs) {
|
|
109
|
-
const pkgPath = node_path_1.default.join(d, 'package.json');
|
|
110
|
-
if (await exists(pkgPath)) {
|
|
111
|
-
pkgDirs.push(d);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return [...new Set(pkgDirs)];
|
|
115
|
-
}
|
|
116
|
-
async function findWorkspacePackageDirs(repoRoot, workspacePatterns) {
|
|
117
|
-
const dirs = [];
|
|
118
|
-
for (const pat of workspacePatterns) {
|
|
119
|
-
const expanded = await expandWorkspacePattern(repoRoot, pat);
|
|
120
|
-
dirs.push(...expanded);
|
|
121
|
-
dirs.push(...expanded);
|
|
122
|
-
}
|
|
123
|
-
const uniqueDirs = [...new Set(dirs)];
|
|
124
|
-
return uniqueDirs;
|
|
125
|
-
}
|
|
126
|
-
// ---------- .mono parsing ----------
|
|
127
|
-
async function readMonoConfig() {
|
|
128
|
-
const configPath = node_path_1.default.join(MONO_DIR, 'config.json');
|
|
129
|
-
console.log(`[readMonoConfig] Looking for mono config at:`, configPath);
|
|
130
|
-
if (!(await exists(configPath))) {
|
|
131
|
-
console.log(`[readMonoConfig] No mono config found.`);
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
try {
|
|
135
|
-
const config = await readJson(configPath);
|
|
136
|
-
return { path: configPath, config };
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function commandNameFromFile(filePath) {
|
|
143
|
-
return node_path_1.default.basename(filePath).replace(/\.json$/i, '');
|
|
144
|
-
}
|
|
145
|
-
async function readMonoCommands() {
|
|
146
|
-
if (!(await exists(MONO_DIR))) {
|
|
147
|
-
return [];
|
|
148
|
-
}
|
|
149
|
-
const entries = await listDir(MONO_DIR);
|
|
150
|
-
const jsonFiles = entries
|
|
151
|
-
.filter((e) => e.isFile() && e.name.toLowerCase().endsWith('.json'))
|
|
152
|
-
.map((e) => node_path_1.default.join(MONO_DIR, e.name))
|
|
153
|
-
.filter((p) => node_path_1.default.basename(p).toLowerCase() !== 'config.json');
|
|
154
|
-
const commands = [];
|
|
155
|
-
for (const file of jsonFiles) {
|
|
156
|
-
try {
|
|
157
|
-
const j = await readJson(file);
|
|
158
|
-
commands.push({
|
|
159
|
-
name: commandNameFromFile(file),
|
|
160
|
-
file,
|
|
161
|
-
json: j,
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
catch (err) {
|
|
165
|
-
console.error(`[readMonoCommands] Failed to load command file:`, file, err);
|
|
166
|
-
// skip invalid json
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
commands.sort((a, b) => a.name.localeCompare(b.name));
|
|
170
|
-
return commands;
|
|
171
|
-
}
|
|
172
|
-
function parseOptionsSchema(optionsObj) {
|
|
173
|
-
// New structure supports:
|
|
174
|
-
// - optionKey: { type: "string", default, options: [], allowAll, shortcut, description }
|
|
175
|
-
// - boolean toggle: { shortcut, description } (no type)
|
|
176
|
-
if (!isObject(optionsObj))
|
|
177
|
-
return [];
|
|
178
|
-
const entries = Object.entries(optionsObj).map(([key, raw]) => {
|
|
179
|
-
const o = isObject(raw) ? raw : {};
|
|
180
|
-
const hasType = typeof o.type === 'string' && o.type.trim().length > 0;
|
|
181
|
-
const isBoolToggle = !hasType; // in your examples, booleans omit `type`
|
|
182
|
-
return {
|
|
183
|
-
key,
|
|
184
|
-
kind: isBoolToggle ? 'boolean' : 'value',
|
|
185
|
-
type: hasType ? String(o.type) : 'boolean',
|
|
186
|
-
description: typeof o.description === 'string' ? o.description : '',
|
|
187
|
-
shortcut: typeof o.shortcut === 'string' ? o.shortcut : '',
|
|
188
|
-
default: o.default,
|
|
189
|
-
allowed: Array.isArray(o.options) ? o.options : null,
|
|
190
|
-
allowAll: o.allowAll === true,
|
|
191
|
-
};
|
|
192
|
-
});
|
|
193
|
-
entries.sort((a, b) => a.key.localeCompare(b.key));
|
|
194
|
-
return entries;
|
|
195
|
-
}
|
|
196
|
-
function buildUsageExample(commandName, cmdJson, options) {
|
|
197
|
-
const arg = cmdJson?.argument;
|
|
198
|
-
const hasArg = isObject(arg);
|
|
199
|
-
const argToken = hasArg ? `<${commandName}-arg>` : '';
|
|
200
|
-
// choose a representative value option to show
|
|
201
|
-
const valueOpts = options.filter((o) => o.kind === 'value');
|
|
202
|
-
const boolOpts = options.filter((o) => o.kind === 'boolean');
|
|
203
|
-
const exampleParts = [`yarn mono ${commandName}`];
|
|
204
|
-
if (argToken)
|
|
205
|
-
exampleParts.push(argToken);
|
|
206
|
-
// include at most 2 value options and 1 boolean in the example for readability
|
|
207
|
-
for (const o of valueOpts.slice(0, 2)) {
|
|
208
|
-
const flag = `--${o.key}`;
|
|
209
|
-
const val = o.default !== undefined ? o.default : (o.allowed?.[0] ?? '<value>');
|
|
210
|
-
exampleParts.push(`${flag} ${val}`);
|
|
211
|
-
}
|
|
212
|
-
if (boolOpts.length) {
|
|
213
|
-
exampleParts.push(`--${boolOpts[0].key}`);
|
|
214
|
-
}
|
|
215
|
-
return exampleParts.join(' ');
|
|
216
|
-
}
|
|
217
|
-
function formatMonoConfigSection(monoConfig) {
|
|
218
|
-
const lines = [];
|
|
219
|
-
lines.push('## Mono configuration');
|
|
220
|
-
lines.push('');
|
|
221
|
-
if (!monoConfig) {
|
|
222
|
-
lines.push('_No `.mono/config.json` found._');
|
|
223
|
-
return lines.join('\n');
|
|
224
|
-
}
|
|
225
|
-
const c = monoConfig.config;
|
|
226
|
-
lines.push(`Source: \`${toPosix(node_path_1.default.relative(REPO_ROOT, monoConfig.path))}\``);
|
|
227
|
-
lines.push('');
|
|
228
|
-
if (Array.isArray(c.envMap) && c.envMap.length) {
|
|
229
|
-
lines.push('### envMap');
|
|
230
|
-
lines.push('');
|
|
231
|
-
lines.push('- ' + c.envMap.map((x) => `\`${mdEscapeInline(x)}\``).join(', '));
|
|
232
|
-
lines.push('');
|
|
233
|
-
}
|
|
234
|
-
const pkgMaps = c?.workspace?.packageMaps;
|
|
235
|
-
if (pkgMaps && isObject(pkgMaps) && Object.keys(pkgMaps).length) {
|
|
236
|
-
lines.push('### Workspace aliases (packageMaps)');
|
|
237
|
-
lines.push('');
|
|
238
|
-
const entries = Object.entries(pkgMaps).sort(([a], [b]) => a.localeCompare(b));
|
|
239
|
-
for (const [alias, target] of entries) {
|
|
240
|
-
lines.push(`- \`${mdEscapeInline(alias)}\` → \`${mdEscapeInline(String(target))}\``);
|
|
241
|
-
}
|
|
242
|
-
lines.push('');
|
|
243
|
-
}
|
|
244
|
-
const pre = c?.workspace?.preactions;
|
|
245
|
-
if (Array.isArray(pre) && pre.length) {
|
|
246
|
-
lines.push('### Global preactions');
|
|
247
|
-
lines.push('');
|
|
248
|
-
lines.push('```bash');
|
|
249
|
-
for (const p of pre)
|
|
250
|
-
lines.push(String(p));
|
|
251
|
-
lines.push('```');
|
|
252
|
-
lines.push('');
|
|
253
|
-
}
|
|
254
|
-
if (typeof c.prodFlag === 'string' && c.prodFlag.trim()) {
|
|
255
|
-
lines.push('### prodFlag');
|
|
256
|
-
lines.push('');
|
|
257
|
-
lines.push(`Production flag keyword: \`${mdEscapeInline(c.prodFlag.trim())}\``);
|
|
258
|
-
lines.push('');
|
|
259
|
-
}
|
|
260
|
-
return lines.join('\n');
|
|
261
|
-
}
|
|
262
|
-
function formatMonoCommandsSection(commands) {
|
|
263
|
-
const lines = [];
|
|
264
|
-
lines.push('## Mono commands');
|
|
265
|
-
lines.push('');
|
|
266
|
-
lines.push('Generated from `.mono/*.json` (excluding `config.json`). Each filename becomes a command:');
|
|
267
|
-
lines.push('');
|
|
268
|
-
lines.push('```bash');
|
|
269
|
-
lines.push('yarn mono <command> [argument] [--options]');
|
|
270
|
-
lines.push('```');
|
|
271
|
-
lines.push('');
|
|
272
|
-
if (!commands.length) {
|
|
273
|
-
lines.push('_No mono command JSON files found._');
|
|
274
|
-
return lines.join('\n');
|
|
275
|
-
}
|
|
276
|
-
// Index
|
|
277
|
-
lines.push('### Command index');
|
|
278
|
-
lines.push('');
|
|
279
|
-
for (const c of commands) {
|
|
280
|
-
const desc = typeof c.json?.description === 'string' ? c.json.description.trim() : '';
|
|
281
|
-
const suffix = desc ? ` — ${desc}` : '';
|
|
282
|
-
lines.push(`- [\`${mdEscapeInline(c.name)}\`](#mono-command-${mdEscapeInline(c.name).toLowerCase()})${suffix}`);
|
|
283
|
-
}
|
|
284
|
-
lines.push('');
|
|
285
|
-
for (const c of commands) {
|
|
286
|
-
const j = c.json || {};
|
|
287
|
-
const rel = toPosix(node_path_1.default.relative(REPO_ROOT, c.file));
|
|
288
|
-
const anchor = `mono-command-${c.name.toLowerCase()}`;
|
|
289
|
-
const desc = typeof j.description === 'string' ? j.description.trim() : '';
|
|
290
|
-
const arg = j.argument;
|
|
291
|
-
const options = parseOptionsSchema(j.options);
|
|
292
|
-
lines.push('---');
|
|
293
|
-
lines.push(`### Mono command: ${c.name}`);
|
|
294
|
-
lines.push(`<a id="${anchor}"></a>`);
|
|
295
|
-
lines.push('');
|
|
296
|
-
lines.push(`Source: \`${rel}\``);
|
|
297
|
-
lines.push('');
|
|
298
|
-
if (desc) {
|
|
299
|
-
lines.push(`**Description:** ${mdEscapeInline(desc)}`);
|
|
300
|
-
lines.push('');
|
|
301
|
-
}
|
|
302
|
-
// Usage
|
|
303
|
-
lines.push('**Usage**');
|
|
304
|
-
lines.push('');
|
|
305
|
-
lines.push('```bash');
|
|
306
|
-
lines.push(`yarn mono ${c.name}${isObject(arg) ? ` <${c.name}-arg>` : ''} [--options]`);
|
|
307
|
-
lines.push('```');
|
|
308
|
-
lines.push('');
|
|
309
|
-
lines.push('Example:');
|
|
310
|
-
lines.push('');
|
|
311
|
-
lines.push('```bash');
|
|
312
|
-
lines.push(buildUsageExample(c.name, j, options));
|
|
313
|
-
lines.push('```');
|
|
314
|
-
lines.push('');
|
|
315
|
-
// Argument
|
|
316
|
-
if (isObject(arg)) {
|
|
317
|
-
lines.push('**Argument**');
|
|
318
|
-
lines.push('');
|
|
319
|
-
const bits = [];
|
|
320
|
-
if (typeof arg.type === 'string')
|
|
321
|
-
bits.push(`type: \`${mdEscapeInline(arg.type)}\``);
|
|
322
|
-
if (arg.default !== undefined)
|
|
323
|
-
bits.push(`default: \`${mdEscapeInline(String(arg.default))}\``);
|
|
324
|
-
if (typeof arg.description === 'string')
|
|
325
|
-
bits.push(mdEscapeInline(arg.description));
|
|
326
|
-
lines.push(`- ${bits.join(' • ') || '_(no details)_'} `);
|
|
327
|
-
lines.push('');
|
|
328
|
-
}
|
|
329
|
-
// Options
|
|
330
|
-
if (options.length) {
|
|
331
|
-
lines.push('**Options**');
|
|
332
|
-
lines.push('');
|
|
333
|
-
lines.push('| Option | Type | Shortcut | Default | Allowed | Notes |');
|
|
334
|
-
lines.push('|---|---:|:---:|---:|---|---|');
|
|
335
|
-
for (const o of options) {
|
|
336
|
-
const optCol = o.kind === 'boolean'
|
|
337
|
-
? `\`--${mdEscapeInline(o.key)}\``
|
|
338
|
-
: `\`--${mdEscapeInline(o.key)} <${mdEscapeInline(o.key)}>\``;
|
|
339
|
-
const typeCol = `\`${mdEscapeInline(o.type)}\``;
|
|
340
|
-
const shortCol = o.shortcut ? `\`-${mdEscapeInline(o.shortcut)}\`` : '';
|
|
341
|
-
const defCol = o.default !== undefined ? `\`${mdEscapeInline(o.default)}\`` : '';
|
|
342
|
-
const allowedCol = o.allowed
|
|
343
|
-
? o.allowed.map((x) => `\`${mdEscapeInline(x)}\``).join(', ')
|
|
344
|
-
: '';
|
|
345
|
-
const notes = [
|
|
346
|
-
o.allowAll ? 'allowAll' : '',
|
|
347
|
-
o.description ? mdEscapeInline(o.description) : '',
|
|
348
|
-
]
|
|
349
|
-
.filter(Boolean)
|
|
350
|
-
.join(' • ');
|
|
351
|
-
lines.push(`| ${optCol} | ${typeCol} | ${shortCol} | ${defCol} | ${allowedCol} | ${notes} |`);
|
|
352
|
-
}
|
|
353
|
-
lines.push('');
|
|
354
|
-
}
|
|
355
|
-
// Environments
|
|
356
|
-
if (j.environments && isObject(j.environments) && Object.keys(j.environments).length) {
|
|
357
|
-
lines.push('**Environment Variables**');
|
|
358
|
-
lines.push('');
|
|
359
|
-
const envs = Object.entries(j.environments).sort(([a], [b]) => a.localeCompare(b));
|
|
360
|
-
for (const [envName, envObj] of envs) {
|
|
361
|
-
lines.push(`- \`${mdEscapeInline(envName)}\``);
|
|
362
|
-
if (isObject(envObj) && Object.keys(envObj).length) {
|
|
363
|
-
const kv = Object.entries(envObj).sort(([a], [b]) => a.localeCompare(b));
|
|
364
|
-
lines.push(indentLines(kv
|
|
365
|
-
.map(([k, v]) => `- \`${mdEscapeInline(k)}\` = \`${mdEscapeInline(String(v))}\``)
|
|
366
|
-
.join('\n'), 2));
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
lines.push('');
|
|
370
|
-
}
|
|
371
|
-
// preactions/actions
|
|
372
|
-
if (Array.isArray(j.preactions) && j.preactions.length) {
|
|
373
|
-
lines.push('**Preactions**');
|
|
374
|
-
lines.push('');
|
|
375
|
-
lines.push('```bash');
|
|
376
|
-
for (const p of j.preactions)
|
|
377
|
-
lines.push(String(p));
|
|
378
|
-
lines.push('```');
|
|
379
|
-
lines.push('');
|
|
380
|
-
}
|
|
381
|
-
if (Array.isArray(j.actions) && j.actions.length) {
|
|
382
|
-
lines.push('**Actions**');
|
|
383
|
-
lines.push('');
|
|
384
|
-
lines.push('```bash');
|
|
385
|
-
for (const a of j.actions)
|
|
386
|
-
lines.push(String(a));
|
|
387
|
-
lines.push('```');
|
|
388
|
-
lines.push('');
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
return lines.join('\n');
|
|
392
|
-
}
|
|
393
|
-
function collectScripts(packages) {
|
|
394
|
-
const scriptToPackages = new Map();
|
|
395
|
-
for (const p of packages) {
|
|
396
|
-
for (const scriptName of Object.keys(p.scripts || {})) {
|
|
397
|
-
if (!scriptToPackages.has(scriptName))
|
|
398
|
-
scriptToPackages.set(scriptName, []);
|
|
399
|
-
scriptToPackages.get(scriptName).push(p.name);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
return scriptToPackages;
|
|
403
|
-
}
|
|
404
|
-
// ---------- main ----------
|
|
405
|
-
async function main() {
|
|
406
|
-
if (!(await exists(ROOT_PKG_JSON)))
|
|
407
|
-
throw new Error(`Missing: ${ROOT_PKG_JSON}`);
|
|
408
|
-
await ensureParentDir(OUTPUT_PATH);
|
|
409
|
-
const rootPkg = await readJson(ROOT_PKG_JSON);
|
|
410
|
-
const workspacePatterns = normalizeWorkspacePatterns(rootPkg.workspaces);
|
|
411
|
-
const monoConfig = await readMonoConfig();
|
|
412
|
-
const monoCommands = await readMonoCommands();
|
|
413
|
-
const pkgDirs = await findWorkspacePackageDirs(REPO_ROOT, workspacePatterns);
|
|
414
|
-
const packages = [];
|
|
415
|
-
for (const dir of pkgDirs) {
|
|
416
|
-
try {
|
|
417
|
-
const pkgPath = node_path_1.default.join(dir, 'package.json');
|
|
418
|
-
const pj = await readJson(pkgPath);
|
|
419
|
-
packages.push({
|
|
420
|
-
name: pj.name || toPosix(node_path_1.default.relative(REPO_ROOT, dir)) || node_path_1.default.basename(dir),
|
|
421
|
-
dir,
|
|
422
|
-
scripts: pj.scripts || {},
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
catch (err) {
|
|
426
|
-
console.error(`[main] Failed to load package.json for:`, dir, err);
|
|
427
|
-
// skip
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
const parts = [];
|
|
431
|
-
parts.push(`# ⚙️ Command Line Reference
|
|
432
|
-
|
|
433
|
-
> Generated by \`scripts/generate-readme.mjs\`.
|
|
434
|
-
> Update \`.mono/config.json\`, \`.mono/*.json\`, and workspace package scripts to change this output.
|
|
435
|
-
|
|
436
|
-
`);
|
|
437
|
-
parts.push(formatMonoConfigSection(monoConfig));
|
|
438
|
-
parts.push('');
|
|
439
|
-
parts.push(formatMonoCommandsSection(monoCommands));
|
|
440
|
-
parts.push('');
|
|
441
|
-
const val = await (0, generate_docs_1.generateDocsIndex)({
|
|
442
|
-
docsDir: node_path_1.default.join(REPO_ROOT, 'docs'),
|
|
443
|
-
excludeFile: 'command-line.md',
|
|
444
|
-
});
|
|
445
|
-
val.split('\n').forEach((line) => parts.push(line));
|
|
446
|
-
await ensureParentDir(OUTPUT_README);
|
|
447
|
-
await node_fs_1.promises.writeFile(OUTPUT_README, parts.join('\n'), 'utf8');
|
|
448
|
-
console.log(`[main] Generated: ${OUTPUT_README}`);
|
|
449
|
-
console.log(`[main] mono config: ${monoConfig ? 'yes' : 'no'}`);
|
|
450
|
-
console.log(`[main] mono commands: ${monoCommands.length}`);
|
|
451
|
-
console.log(`[main] workspace packages: ${packages.length}`);
|
|
452
|
-
}
|
|
453
|
-
main().catch((err) => {
|
|
454
|
-
console.error(err?.stack || String(err));
|
|
455
|
-
process.exitCode = 1;
|
|
456
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// scripts/generate-repo-help.mjs
|
|
3
|
-
// Generates a developer-friendly workspace command reference.
|
|
4
|
-
//
|
|
5
|
-
// Output: docs/workspaces.md
|
|
6
|
-
//
|
|
7
|
-
// Run (from repo root):
|
|
8
|
-
// node ./scripts/generate-repo-help.mjs
|
|
9
|
-
//
|
|
10
|
-
// Philosophy:
|
|
11
|
-
// - Optimize for onboarding and day-to-day use
|
|
12
|
-
// - Keep raw yarn workspace commands for reference
|
|
13
|
-
// - Emphasize `yarn mono` as the primary interface
|
|
14
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
-
};
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.generateDocsIndex = generateDocsIndex;
|
|
19
|
-
const node_fs_1 = require("node:fs");
|
|
20
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
21
|
-
function createSpacer() {
|
|
22
|
-
return '\n\n';
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Generate a docs index from markdown files.
|
|
26
|
-
*
|
|
27
|
-
* @param options - Options for docs index generation
|
|
28
|
-
* @returns Markdown-formatted index
|
|
29
|
-
*/
|
|
30
|
-
async function generateDocsIndex({ docsDir, excludeFile, }) {
|
|
31
|
-
// Always resolve docsDir relative to the working directory
|
|
32
|
-
const dirPath = node_path_1.default.resolve(process.cwd(), docsDir);
|
|
33
|
-
const entries = await node_fs_1.promises.readdir(dirPath, { withFileTypes: true });
|
|
34
|
-
const links = [];
|
|
35
|
-
for (const entry of entries) {
|
|
36
|
-
if (!entry.isFile())
|
|
37
|
-
continue;
|
|
38
|
-
if (!entry.name.endsWith('.md'))
|
|
39
|
-
continue;
|
|
40
|
-
// Always ignore docs/readme.md (case-insensitive)
|
|
41
|
-
if (entry.name.toLowerCase() === 'readme.md')
|
|
42
|
-
continue;
|
|
43
|
-
// Optionally ignore a caller-specified file
|
|
44
|
-
if (excludeFile && entry.name === excludeFile)
|
|
45
|
-
continue;
|
|
46
|
-
const filePath = node_path_1.default.join(dirPath, entry.name);
|
|
47
|
-
const contents = await node_fs_1.promises.readFile(filePath, 'utf8');
|
|
48
|
-
// Find first markdown H1
|
|
49
|
-
const match = contents.match(/^#\s+(.+)$/m);
|
|
50
|
-
if (!match)
|
|
51
|
-
continue;
|
|
52
|
-
const rawTitle = match[1].trim();
|
|
53
|
-
const relativeLink = `./${entry.name}`;
|
|
54
|
-
/**
|
|
55
|
-
* Detect leading non-alphanumeric characters (emoji / symbols).
|
|
56
|
-
* This matches one or more Unicode characters that are NOT letters or numbers.
|
|
57
|
-
*/
|
|
58
|
-
const leadingSymbolMatch = rawTitle.match(/^([^\p{L}\p{N}]+)\s*(.+)$/u);
|
|
59
|
-
if (leadingSymbolMatch) {
|
|
60
|
-
const [, symbol, title] = leadingSymbolMatch;
|
|
61
|
-
links.push(`- ${symbol.trim()} [${title.trim()}](${relativeLink})`);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
links.push(`- [${rawTitle.trim()}](${relativeLink})`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
// Sort alphabetically by rendered text (stable output)
|
|
68
|
-
links.sort((a, b) => a.localeCompare(b));
|
|
69
|
-
// Append Back to Readme
|
|
70
|
-
links.push('');
|
|
71
|
-
links.push('🏠 ← [Back to README](../README.md)');
|
|
72
|
-
return ['', '---', '', ...links].join('\n');
|
|
73
|
-
}
|