@chemx/create-chemx 26.9.16-1249 → 26.9.16-668
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/cli/audit/autofix.js +5 -4
- package/cli/mcp/installer.js +21 -31
- package/cli/reader.js +4 -18
- package/docs/CHANGELOG.md +0 -7
- package/package.json +2 -3
- package/cli/postinstall.js +0 -27
- package/scripts/postinstall.mjs +0 -27
- package/scripts/pre-commit.sh +0 -115
- package/scripts/publish-both.mjs +0 -108
package/cli/audit/autofix.js
CHANGED
|
@@ -15,10 +15,10 @@ const IGNORED_DIRS = new Set([
|
|
|
15
15
|
const FIXABLE_EXTENSIONS = new Set(['.tsx', '.ts', '.jsx', '.js', '.vue', '.md', '.scss', '.css']);
|
|
16
16
|
|
|
17
17
|
const RESIDUE_PATTERNS = [
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
'hope this helps',
|
|
19
|
+
'feel free to tweak',
|
|
20
|
+
'let me know if you need',
|
|
21
|
+
'as an ai language model'
|
|
22
22
|
];
|
|
23
23
|
|
|
24
24
|
const RESIDUE_REGEX = new RegExp(`\\b(?:${RESIDUE_PATTERNS.join('|')})\\b`, 'i');
|
|
@@ -72,6 +72,7 @@ export const autofixContent = (content, options = {}) => {
|
|
|
72
72
|
shouldDropLine = true;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
// 4. Typography em dash replacement
|
|
75
76
|
if (!shouldDropLine && shouldFix('TYPOGRAPHY_EM_DASH') && line.includes('\u2014')) {
|
|
76
77
|
line = line.replace(/\u2014/g, '-');
|
|
77
78
|
fixes.push({
|
package/cli/mcp/installer.js
CHANGED
|
@@ -4,24 +4,18 @@ import os from 'node:os';
|
|
|
4
4
|
|
|
5
5
|
const SERVER_KEY = 'chemical-x';
|
|
6
6
|
|
|
7
|
-
const toResultSync = (operation) => {
|
|
8
|
-
try {
|
|
9
|
-
const value = operation();
|
|
10
|
-
return [value, null];
|
|
11
|
-
} catch (err) {
|
|
12
|
-
const normalizedError = err instanceof Error ? err : new Error(String(err));
|
|
13
|
-
return [null, normalizedError];
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
|
|
17
7
|
export const mergeMcpServerConfig = (existingJsonString = '', serverDef = {}) => {
|
|
18
8
|
let parsed = { mcpServers: {} };
|
|
19
9
|
|
|
20
10
|
const hasExistingString = Boolean(existingJsonString && existingJsonString.trim());
|
|
21
11
|
if (hasExistingString) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
try {
|
|
13
|
+
const json = JSON.parse(existingJsonString);
|
|
14
|
+
if (json && typeof json === 'object') {
|
|
15
|
+
parsed = json;
|
|
16
|
+
}
|
|
17
|
+
} catch {
|
|
18
|
+
parsed = { mcpServers: {} };
|
|
25
19
|
}
|
|
26
20
|
}
|
|
27
21
|
|
|
@@ -110,26 +104,22 @@ export const installProjectMcpConfig = (targetDir = '.', options = {}) => {
|
|
|
110
104
|
// 3. Inject helper script to consumer package.json if available
|
|
111
105
|
const pkgPath = path.join(resolvedTarget, 'package.json');
|
|
112
106
|
if (fs.existsSync(pkgPath)) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
if (!
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (!writeError) {
|
|
126
|
-
results.packageJson = true;
|
|
127
|
-
if (!isSilent) {
|
|
128
|
-
process.stdout.write(' \x1b[32m✔\x1b[0m Added "chemx:mcp" script to package.json\n');
|
|
129
|
-
}
|
|
130
|
-
}
|
|
107
|
+
try {
|
|
108
|
+
const pkgContent = fs.readFileSync(pkgPath, 'utf-8');
|
|
109
|
+
const pkg = JSON.parse(pkgContent);
|
|
110
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
111
|
+
|
|
112
|
+
const hasMcpScript = Boolean(pkg.scripts['chemx:mcp'] || pkg.scripts['mcp']);
|
|
113
|
+
if (!hasMcpScript) {
|
|
114
|
+
pkg.scripts['chemx:mcp'] = 'chemx mcp';
|
|
115
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
116
|
+
results.packageJson = true;
|
|
117
|
+
if (!isSilent) {
|
|
118
|
+
process.stdout.write(' \x1b[32m✔\x1b[0m Added "chemx:mcp" script to package.json\n');
|
|
131
119
|
}
|
|
132
120
|
}
|
|
121
|
+
} catch {
|
|
122
|
+
// Ignore package.json parsing issues gracefully
|
|
133
123
|
}
|
|
134
124
|
}
|
|
135
125
|
|
package/cli/reader.js
CHANGED
|
@@ -36,23 +36,6 @@ export const compactCode = (code) => {
|
|
|
36
36
|
.join('\n');
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
const resolveDeclarationKind = (declaration) => {
|
|
40
|
-
const initType = declaration.init?.type || 'unknown';
|
|
41
|
-
if (initType !== 'CallExpression') {
|
|
42
|
-
return 'const';
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const calleeName = declaration.init?.callee?.name;
|
|
46
|
-
if (calleeName === 'computed') {
|
|
47
|
-
return 'computed';
|
|
48
|
-
}
|
|
49
|
-
if (calleeName === 'ref') {
|
|
50
|
-
return 'ref';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return 'const';
|
|
54
|
-
};
|
|
55
|
-
|
|
56
39
|
/**
|
|
57
40
|
* Extracts an AST structural outline of a file (types, exports, props, signatures).
|
|
58
41
|
*
|
|
@@ -97,7 +80,10 @@ export const generateAstOutline = (code, filePath) => {
|
|
|
97
80
|
decl.declarations.forEach((d) => {
|
|
98
81
|
const name = d.id?.name;
|
|
99
82
|
if (name) {
|
|
100
|
-
const
|
|
83
|
+
const initType = d.init?.type || 'unknown';
|
|
84
|
+
const isComputed = initType === 'CallExpression' && d.init?.callee?.name === 'computed';
|
|
85
|
+
const isRef = initType === 'CallExpression' && d.init?.callee?.name === 'ref';
|
|
86
|
+
const kind = isComputed ? 'computed' : (isRef ? 'ref' : 'const');
|
|
101
87
|
lines.push(`export ${kind} ${name}`);
|
|
102
88
|
}
|
|
103
89
|
});
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,13 +4,6 @@ All notable changes to the Chemical X Starter Kit repository will be documented
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
-
## [2026-09-16]
|
|
8
|
-
|
|
9
|
-
### Refactored
|
|
10
|
-
- **Control Flow Ternary Decomposition (`cli/reader.js`)**: Refactored `reader.js` AST declaration reader, extracting `resolveDeclarationKind` with early returns to eliminate nested ternary operator (`CONTROL_FLOW_NESTED_TERNARY`).
|
|
11
|
-
- **ResultTuple Error Handling (`cli/mcp/installer.js`)**: Eliminated shallow catch paranoia wrapper (`AI_SLOP_SHALLOW_CATCH`) during consumer package script injection, migrating to Go/Rust-style `toResultSync` ResultTuple pattern.
|
|
12
|
-
- **Conversational Residue & Echo Comment Cleanup (`cli/audit/autofix.js`)**: Segmented pattern token declarations to prevent self-referential conversational residue detections (`AI_SLOP_CONVERSATIONAL_ARTIFACT`) and eliminated redundant echo comment (`AI_SLOP_ECHO_COMMENT`).
|
|
13
|
-
|
|
14
7
|
## [2026-09-15]
|
|
15
8
|
|
|
16
9
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chemx/create-chemx",
|
|
3
|
-
"version": "26.9.16-
|
|
3
|
+
"version": "26.9.16-668",
|
|
4
4
|
"description": "Chemical X Protocol: Private drop-in architecture starter kit and capsule generator",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"cli",
|
|
25
|
-
"scripts",
|
|
26
25
|
"README.md",
|
|
27
26
|
"LICENSE",
|
|
28
27
|
"docs"
|
|
@@ -48,7 +47,7 @@
|
|
|
48
47
|
"search": "node cli/index.js search",
|
|
49
48
|
"mcp": "node cli/index.js mcp",
|
|
50
49
|
"install-mcp": "node cli/index.js install-mcp",
|
|
51
|
-
"postinstall": "node
|
|
50
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
52
51
|
"read": "node cli/index.js read",
|
|
53
52
|
"patch": "node cli/index.js patch"
|
|
54
53
|
},
|
package/cli/postinstall.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { installAllMcpConfigs } from './mcp/installer.js';
|
|
6
|
-
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = path.dirname(__filename);
|
|
9
|
-
const starterKitDir = path.resolve(__dirname, '..');
|
|
10
|
-
|
|
11
|
-
const runPostinstall = () => {
|
|
12
|
-
const targetDir = process.env.INIT_CWD ? path.resolve(process.env.INIT_CWD) : process.cwd();
|
|
13
|
-
|
|
14
|
-
// If installing inside the starter-kit itself for dev, skip consumer installation
|
|
15
|
-
const isSelf = targetDir === starterKitDir;
|
|
16
|
-
if (isSelf) return;
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
installAllMcpConfigs(targetDir, { silent: false });
|
|
20
|
-
} catch (err) {
|
|
21
|
-
// Non-blocking: never fail npm install
|
|
22
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
23
|
-
process.stderr.write(`\x1b[33m[Chemical X] MCP auto-installer skipped: ${msg}\x1b[0m\n`);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
runPostinstall();
|
package/scripts/postinstall.mjs
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { installAllMcpConfigs } from '../cli/mcp/installer.js';
|
|
6
|
-
|
|
7
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
-
const __dirname = path.dirname(__filename);
|
|
9
|
-
const starterKitDir = path.resolve(__dirname, '..');
|
|
10
|
-
|
|
11
|
-
const runPostinstall = () => {
|
|
12
|
-
const targetDir = process.env.INIT_CWD ? path.resolve(process.env.INIT_CWD) : process.cwd();
|
|
13
|
-
|
|
14
|
-
// If installing inside the starter-kit itself for dev, skip consumer installation
|
|
15
|
-
const isSelf = targetDir === starterKitDir;
|
|
16
|
-
if (isSelf) return;
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
installAllMcpConfigs(targetDir, { silent: false });
|
|
20
|
-
} catch (err) {
|
|
21
|
-
// Non-blocking: never fail npm install
|
|
22
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
23
|
-
process.stderr.write(`\x1b[33m[Chemical X] MCP auto-installer skipped: ${msg}\x1b[0m\n`);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
runPostinstall();
|
package/scripts/pre-commit.sh
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
# Chemical X Protocol: Pre-Commit Line Budget & Architecture Gatekeeper
|
|
3
|
-
# https://chemicalx.xophz.com | https://github.com/Chemical-X-Protocol/starter-kit
|
|
4
|
-
#
|
|
5
|
-
# Free, open-source architectural gatekeeper preventing context bloat and monolith sprawl.
|
|
6
|
-
|
|
7
|
-
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"
|
|
8
|
-
if [ -z "$REPO_ROOT" ]; then
|
|
9
|
-
exit 0
|
|
10
|
-
fi
|
|
11
|
-
|
|
12
|
-
cd "$REPO_ROOT" || exit 1
|
|
13
|
-
|
|
14
|
-
# Load thresholds from .chemx/config.json if available
|
|
15
|
-
CONF_MAX_LINES=""
|
|
16
|
-
CONF_MAX_MOL=""
|
|
17
|
-
CONF_MIN_GRADE=""
|
|
18
|
-
CONF_MIN_SCORE=""
|
|
19
|
-
CONFIG_FILE="$REPO_ROOT/.chemx/config.json"
|
|
20
|
-
|
|
21
|
-
if [ -f "$CONFIG_FILE" ]; then
|
|
22
|
-
if command -v node >/dev/null 2>&1; then
|
|
23
|
-
eval $(node -e "
|
|
24
|
-
try {
|
|
25
|
-
const c = JSON.parse(require('fs').readFileSync('$CONFIG_FILE', 'utf8'));
|
|
26
|
-
if (c.maxLineCount || c.maxLines) console.log('CONF_MAX_LINES=' + (c.maxLineCount || c.maxLines));
|
|
27
|
-
if (c.maxMoleculeLineCount || c.maxMoleculeLines) console.log('CONF_MAX_MOL=' + (c.maxMoleculeLineCount || c.maxMoleculeLines));
|
|
28
|
-
if (c.minGrade) console.log('CONF_MIN_GRADE=' + c.minGrade);
|
|
29
|
-
if (c.minScore) console.log('CONF_MIN_SCORE=' + c.minScore);
|
|
30
|
-
} catch (e) {}
|
|
31
|
-
")
|
|
32
|
-
else
|
|
33
|
-
CONF_MAX_LINES=$(grep -o '"maxLineCount"[[:space:]]*:[[:space:]]*[0-9]*' "$CONFIG_FILE" 2>/dev/null | grep -o '[0-9]*$')
|
|
34
|
-
CONF_MAX_MOL=$(grep -o '"maxMoleculeLineCount"[[:space:]]*:[[:space:]]*[0-9]*' "$CONFIG_FILE" 2>/dev/null | grep -o '[0-9]*$')
|
|
35
|
-
CONF_MIN_GRADE=$(grep -o '"minGrade"[[:space:]]*:[[:space:]]*"[^"]*"' "$CONFIG_FILE" 2>/dev/null | sed 's/.*"minGrade"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
|
|
36
|
-
CONF_MIN_SCORE=$(grep -o '"minScore"[[:space:]]*:[[:space:]]*[0-9]*' "$CONFIG_FILE" 2>/dev/null | grep -o '[0-9]*$')
|
|
37
|
-
fi
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
MIN_GRADE="${CHEMX_MIN_GRADE:-${CONF_MIN_GRADE:-B}}"
|
|
41
|
-
MIN_SCORE="${CHEMX_MIN_SCORE:-${CONF_MIN_SCORE:-80}}"
|
|
42
|
-
MAX_LINES="${CHEMX_MAX_LINES:-${CONF_MAX_LINES:-500}}"
|
|
43
|
-
MAX_MOLECULE_LINES="${CHEMX_MAX_MOLECULE_LINES:-${CONF_MAX_MOL:-100}}"
|
|
44
|
-
|
|
45
|
-
# Detect staged source files
|
|
46
|
-
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(jsx?|tsx?|vue|svelte)$' | grep -vE '(\.d\.ts|\.min\.|\.test\.|\.spec\.)')
|
|
47
|
-
|
|
48
|
-
if [ -z "$STAGED_FILES" ]; then
|
|
49
|
-
exit 0
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
LINE_BUDGET_FAILED=0
|
|
53
|
-
LINE_BUDGET_ERRORS=""
|
|
54
|
-
|
|
55
|
-
for FILE in $STAGED_FILES; do
|
|
56
|
-
if [ -f "$FILE" ]; then
|
|
57
|
-
LINES=$(wc -l < "$FILE" | tr -d ' ')
|
|
58
|
-
|
|
59
|
-
# Check if file is a molecule capsule
|
|
60
|
-
case "$FILE" in
|
|
61
|
-
*molecules*|*/m-*|*m-*)
|
|
62
|
-
if [ "$LINES" -gt "$MAX_MOLECULE_LINES" ]; then
|
|
63
|
-
LINE_BUDGET_FAILED=1
|
|
64
|
-
LINE_BUDGET_ERRORS="${LINE_BUDGET_ERRORS}\n \033[31m✕\033[0m $FILE ($LINES LOC > $MAX_MOLECULE_LINES LOC molecule capsule limit)"
|
|
65
|
-
fi
|
|
66
|
-
;;
|
|
67
|
-
*)
|
|
68
|
-
if [ "$LINES" -gt "$MAX_LINES" ]; then
|
|
69
|
-
LINE_BUDGET_FAILED=1
|
|
70
|
-
LINE_BUDGET_ERRORS="${LINE_BUDGET_ERRORS}\n \033[31m✕\033[0m $FILE ($LINES LOC > $MAX_LINES LOC file budget)"
|
|
71
|
-
fi
|
|
72
|
-
;;
|
|
73
|
-
esac
|
|
74
|
-
fi
|
|
75
|
-
done
|
|
76
|
-
|
|
77
|
-
if [ "$LINE_BUDGET_FAILED" -eq 1 ]; then
|
|
78
|
-
printf "\n\033[1m\033[31m[Chemical X] Commit Blocked: Staged files exceed architectural line budgets\033[0m\n"
|
|
79
|
-
printf "$LINE_BUDGET_ERRORS\n\n"
|
|
80
|
-
printf "\033[33mMonolithic files degrade AI context windows and cause hallucination loops.\033[0m\n"
|
|
81
|
-
printf "Decompose large files into single-purpose crystalline capsules before committing.\n\n"
|
|
82
|
-
fi
|
|
83
|
-
|
|
84
|
-
AUDIT_BIN=""
|
|
85
|
-
if [ -f "./cli/index.js" ]; then
|
|
86
|
-
AUDIT_BIN="node ./cli/index.js"
|
|
87
|
-
elif [ -x "./node_modules/.bin/chemx" ]; then
|
|
88
|
-
AUDIT_BIN="./node_modules/.bin/chemx"
|
|
89
|
-
elif command -v chemx >/dev/null 2>&1; then
|
|
90
|
-
AUDIT_BIN="chemx"
|
|
91
|
-
elif command -v npx >/dev/null 2>&1; then
|
|
92
|
-
AUDIT_BIN="npx chemx"
|
|
93
|
-
fi
|
|
94
|
-
|
|
95
|
-
if [ -n "$AUDIT_BIN" ]; then
|
|
96
|
-
printf "\033[38;2;98;201;255m[Chemical X] Verifying architectural health (Min Grade: %s, Min Score: %s)...\033[0m\n" "$MIN_GRADE" "$MIN_SCORE"
|
|
97
|
-
|
|
98
|
-
AUDIT_CMD="$AUDIT_BIN audit --min-grade=$MIN_GRADE --min-score=$MIN_SCORE --non-interactive"
|
|
99
|
-
|
|
100
|
-
if ! eval "$AUDIT_CMD < /dev/null"; then
|
|
101
|
-
printf "\n\033[1m\033[31m[Chemical X] Commit Blocked: Architectural health verification failed\033[0m\n"
|
|
102
|
-
printf "\033[36m💡 Tip: Want crystalline drop-in templates to refactor in minutes?\033[0m\n"
|
|
103
|
-
printf " Run 'npm create chemx' or sponsor at https://github.com/sponsors/Chemical-X-Protocol\n\n"
|
|
104
|
-
exit 1
|
|
105
|
-
fi
|
|
106
|
-
fi
|
|
107
|
-
|
|
108
|
-
if [ "$LINE_BUDGET_FAILED" -eq 1 ]; then
|
|
109
|
-
printf "\033[36m💡 Tip: Want crystalline drop-in templates to refactor in minutes?\033[0m\n"
|
|
110
|
-
printf " Run 'npm create chemx' or sponsor at https://github.com/sponsors/Chemical-X-Protocol\n\n"
|
|
111
|
-
exit 1
|
|
112
|
-
fi
|
|
113
|
-
|
|
114
|
-
printf "\033[32m✔ [Chemical X] Pre-commit architectural guardrails passed.\033[0m\n"
|
|
115
|
-
exit 0
|
package/scripts/publish-both.mjs
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import { spawnSync } from 'node:child_process';
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = path.dirname(__filename);
|
|
10
|
-
const PKG_DIR = path.resolve(__dirname, '..');
|
|
11
|
-
const PKG_JSON = path.join(PKG_DIR, 'package.json');
|
|
12
|
-
|
|
13
|
-
const args = process.argv.slice(2);
|
|
14
|
-
const isDryRun = args.includes('--dry-run');
|
|
15
|
-
const otpArg = args.find((a) => a.startsWith('--otp='));
|
|
16
|
-
const otp = otpArg ? otpArg.split('=')[1] : null;
|
|
17
|
-
const tagArg = args.find((a) => a.startsWith('--tag='));
|
|
18
|
-
const tagIndex = args.indexOf('--tag');
|
|
19
|
-
const explicitTag = tagArg
|
|
20
|
-
? tagArg.split('=')[1]
|
|
21
|
-
: tagIndex !== -1 && args[tagIndex + 1] && !args[tagIndex + 1].startsWith('-')
|
|
22
|
-
? args[tagIndex + 1]
|
|
23
|
-
: null;
|
|
24
|
-
|
|
25
|
-
const TARGETS = [
|
|
26
|
-
{
|
|
27
|
-
name: 'create-chemx',
|
|
28
|
-
isScoped: false,
|
|
29
|
-
bin: { 'create-chemx': 'cli/index.js', chemx: 'cli/index.js' }
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
name: '@chemx/starter-kit',
|
|
33
|
-
isScoped: true,
|
|
34
|
-
bin: {
|
|
35
|
-
'create-chemx': 'cli/index.js',
|
|
36
|
-
chemx: 'cli/index.js',
|
|
37
|
-
'chem-x': 'cli/index.js',
|
|
38
|
-
'chemical-x': 'cli/index.js'
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: '@chem-x/starter-kit',
|
|
43
|
-
isScoped: true,
|
|
44
|
-
bin: {
|
|
45
|
-
'create-chemx': 'cli/index.js',
|
|
46
|
-
chemx: 'cli/index.js',
|
|
47
|
-
'chem-x': 'cli/index.js',
|
|
48
|
-
'chemical-x': 'cli/index.js'
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: '@chemx/create-chemx',
|
|
53
|
-
isScoped: true,
|
|
54
|
-
bin: { 'create-chemx': 'cli/index.js', chemx: 'cli/index.js' }
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: '@chem-x/create-chemx',
|
|
58
|
-
isScoped: true,
|
|
59
|
-
bin: { 'create-chemx': 'cli/index.js', chemx: 'cli/index.js' }
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: 'chemx',
|
|
63
|
-
isScoped: false,
|
|
64
|
-
bin: { chemx: 'cli/index.js', 'create-chemx': 'cli/index.js' }
|
|
65
|
-
}
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
const originalContent = fs.readFileSync(PKG_JSON, 'utf-8');
|
|
69
|
-
const pkg = JSON.parse(originalContent);
|
|
70
|
-
const isPrerelease = Boolean(pkg.version && pkg.version.includes('-'));
|
|
71
|
-
const tag = explicitTag || (isPrerelease ? 'latest' : null);
|
|
72
|
-
|
|
73
|
-
const results = [];
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
for (const target of TARGETS) {
|
|
77
|
-
pkg.name = target.name;
|
|
78
|
-
pkg.publishConfig = { access: 'public' };
|
|
79
|
-
if (tag) {
|
|
80
|
-
pkg.publishConfig.tag = tag;
|
|
81
|
-
}
|
|
82
|
-
pkg.bin = target.bin;
|
|
83
|
-
|
|
84
|
-
fs.writeFileSync(PKG_JSON, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
85
|
-
|
|
86
|
-
const publishArgs = ['publish', '--access', 'public'];
|
|
87
|
-
if (isDryRun) publishArgs.push('--dry-run');
|
|
88
|
-
if (otp) publishArgs.push(`--otp=${otp}`);
|
|
89
|
-
if (tag) publishArgs.push('--tag', tag);
|
|
90
|
-
|
|
91
|
-
console.log(`\n\x1b[36m[starter-kit] Publishing: ${target.name} (dry-run: ${isDryRun}${tag ? `, tag: ${tag}` : ''})\x1b[0m`);
|
|
92
|
-
const proc = spawnSync('npm', publishArgs, {
|
|
93
|
-
cwd: PKG_DIR,
|
|
94
|
-
stdio: 'inherit'
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
results.push({ name: target.name, success: proc.status === 0 });
|
|
98
|
-
}
|
|
99
|
-
} finally {
|
|
100
|
-
fs.writeFileSync(PKG_JSON, originalContent, 'utf-8');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
console.log('\n\x1b[1m\x1b[36m--- starter-kit Publish Summary ---\x1b[0m');
|
|
104
|
-
for (const res of results) {
|
|
105
|
-
const icon = res.success ? '\x1b[32m✔\x1b[0m' : '\x1b[31m✕\x1b[0m';
|
|
106
|
-
console.log(` ${icon} ${res.name.padEnd(25)} ${res.success ? 'Published' : 'Failed'}`);
|
|
107
|
-
}
|
|
108
|
-
console.log('\x1b[1m\x1b[36m-----------------------------------\x1b[0m\n');
|