Skip to content

Commit 1b52ed8

Browse files
committed
feat: Patch the launcher script to handle simple tasks so that the NodeJS startup delay is less noticeable.
1 parent baf0b0f commit 1b52ed8

5 files changed

Lines changed: 92 additions & 10 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
},
128128
"repository": "codifycli/codify",
129129
"scripts": {
130+
"postinstall": "[ -f node_modules/oclif/lib/tarballs/bin.js ] && tsx scripts/patch-oclif.ts || true",
130131
"build": "shx rm -rf dist && tsc -b",
131132
"build:release": "npm run pkg && ./scripts/notarize.sh",
132133
"lint": "tsc",
@@ -144,7 +145,7 @@
144145
"deploy": "npm run pkg && npm run notarize && npm run upload",
145146
"prepublishOnly": "npm run build"
146147
},
147-
"version": "1.1.0-beta6",
148+
"version": "1.1.0-beta7",
148149
"bugs": "https://github.com/codifycli/codify/issues",
149150
"keywords": [
150151
"oclif",

scripts/patch-oclif.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Patches node_modules/oclif/lib/tarballs/bin.js to inject bash logic into the shell script
2+
// that oclif generates during `oclif pack tarballs`. This runs via the `postinstall` npm script
3+
// so it re-applies automatically after any `npm install` that updates oclif.
4+
//
5+
// Why: Node.js takes 500ms–1s to start. By handling simple cases in the shell script we can
6+
// give instant feedback before Node launches.
7+
//
8+
// What the injected bash does (inside the else block, before the "$NODE ... $DIR/run" line):
9+
// - codify --help / -h → cats dist/static/help.txt and exits (no Node startup)
10+
// - codify --version / -v → cats dist/static/version.txt and exits
11+
// - codify apply/destroy/plan → prints "Running Codify <cmd>..." immediately
12+
// (suppressed when --output json or -o json is passed)
13+
// - everything else → falls through to normal Node.js launch
14+
//
15+
// Static files (dist/static/help.txt, dist/static/version.txt) are generated in scripts/pkg.ts
16+
// after the esbuild step by running ./bin/dev.js --help and ./bin/dev.js --version.
17+
// Missing static files are guarded by [ -f ] so all cases fall back to Node gracefully.
18+
//
19+
// Note: console.log('Running Codify apply/destroy...') was removed from src/commands/apply.ts
20+
// and src/commands/destroy.ts to prevent double-printing (shell prints first, Node would repeat it).
21+
//
22+
// If oclif upgrades and changes bin.js structure, this script exits with code 1 so the breakage
23+
// is immediately visible.
24+
import { existsSync } from 'node:fs';
25+
import fs from 'node:fs/promises';
26+
import path from 'node:path';
27+
import { fileURLToPath } from 'node:url';
28+
29+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
30+
const BIN_JS = path.join(__dirname, '../node_modules/oclif/lib/tarballs/bin.js');
31+
32+
if (!existsSync(BIN_JS)) {
33+
console.log('oclif bin.js not found (likely production install). Skipping.');
34+
process.exit(0);
35+
}
36+
37+
const content = await fs.readFile(BIN_JS, 'utf8');
38+
39+
if (content.includes('CODIFY_PATCH_START')) {
40+
console.log('oclif bin.js already patched. Skipping.');
41+
process.exit(0);
42+
}
43+
44+
const SEARCH = ' if [ "\\$DEBUG" == "*" ]; then\n echoerr';
45+
const idx = content.lastIndexOf(SEARCH);
46+
if (idx === -1) {
47+
console.error('ERROR: Could not find insertion point in oclif bin.js. The oclif version may have changed.');
48+
process.exit(1);
49+
}
50+
51+
// Patch uses \\$ so that it survives the JS string — in the generated shell script each \\$ becomes \$
52+
// which Bash then interprets as a literal $ (not a template substitution in the JS template literal).
53+
const PATCH = ` # CODIFY_PATCH_START — do not remove this marker
54+
_first_arg="\${1:-}"
55+
if [ "\\$_first_arg" = "--help" ] || [ "\\$_first_arg" = "-h" ]; then
56+
_help_file="\\$DIR/../dist/static/help.txt"
57+
if [ -f "\\$_help_file" ]; then cat "\\$_help_file"; exit 0; fi
58+
fi
59+
if [ "\\$_first_arg" = "--version" ] || [ "\\$_first_arg" = "-v" ] || [ "\\$_first_arg" = "version" ]; then
60+
_version_file="\\$DIR/../dist/static/version.txt"
61+
if [ -f "\\$_version_file" ]; then cat "\\$_version_file"; exit 0; fi
62+
fi
63+
_cmd="\\$_first_arg"
64+
if [ "\\$_cmd" = "apply" ] || [ "\\$_cmd" = "destroy" ] || [ "\\$_cmd" = "plan" ]; then
65+
_json_output=0
66+
_prev=""
67+
for _a in "\\$@"; do
68+
if [ "\\$_a" = "--output=json" ] || [ "\\$_a" = "-o=json" ]; then _json_output=1; break; fi
69+
if [ "\\$_prev" = "--output" ] || [ "\\$_prev" = "-o" ]; then
70+
if [ "\\$_a" = "json" ]; then _json_output=1; break; fi
71+
fi
72+
_prev="\\$_a"
73+
done
74+
if [ "\\$_json_output" -eq 0 ]; then echo "Running Codify \\$_cmd..."; fi
75+
fi
76+
# CODIFY_PATCH_END — do not remove this marker
77+
`;
78+
79+
await fs.writeFile(BIN_JS, content.slice(0, idx) + PATCH + content.slice(idx), 'utf8');
80+
console.log('Successfully patched oclif bin.js');

scripts/pkg.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ await Promise.all([
3030
console.log(chalk.magenta('Esbuild src'))
3131
execSync('tsx esbuild.ts', { shell: 'zsh' })
3232

33+
console.log(chalk.magenta('Generating static help/version files'))
34+
await fs.mkdir('./.build/dist/static', { recursive: true });
35+
const helpOutput = execSync('./bin/dev.js --help', {
36+
shell: 'zsh',
37+
env: { ...process.env, FORCE_COLOR: '1' },
38+
}).toString();
39+
const versionOutput = execSync('./bin/dev.js --version', { shell: 'zsh' }).toString().trim();
40+
await fs.writeFile('./.build/dist/static/help.txt', helpOutput, 'utf8');
41+
await fs.writeFile('./.build/dist/static/version.txt', versionOutput + '\n', 'utf8');
42+
3343
console.log(chalk.magenta('Install production dependencies'))
3444
execSync('npm install --production', { cwd: './.build', shell: 'zsh' })
3545

src/commands/apply.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ For more information, visit: https://codifycli.com/docs/commands/apply
5050
public async run(): Promise<void> {
5151
const { flags, args } = await this.parse(Apply)
5252

53-
54-
if (flags.output !== 'json') {
55-
console.log('Running Codify apply...')
56-
}
57-
5853
if (flags.path && args.pathArgs) {
5954
throw new Error('Cannot specify both --path and path argument');
6055
}

src/commands/destroy.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ For more information, visit: https://codifycli.com/docs/commands/destory`
4747
public async run(): Promise<void> {
4848
const { flags, raw } = await this.parse(Destroy)
4949

50-
if (flags.output !== 'json') {
51-
console.log('Running Codify destroy...')
52-
}
53-
5450
const args = raw
5551
.filter((r) => r.type === 'arg')
5652
.map((r) => r.input);

0 commit comments

Comments
 (0)