Skip to content

Commit 10da2ee

Browse files
feat: move posthog cli call to core (#2419)
Co-authored-by: Hugues Pouillot <[email protected]>
1 parent 5811e12 commit 10da2ee

File tree

10 files changed

+123
-81
lines changed

10 files changed

+123
-81
lines changed

.changeset/fresh-needles-draw.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@posthog/nextjs-config': patch
3+
'@posthog/core': patch
4+
---
5+
6+
move binary calling logic to core package

examples/example-nextjs/pnpm-lock.yaml

Lines changed: 10 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@
4949
"types": "./dist/utils/index.d.ts",
5050
"require": "./dist/utils/index.js",
5151
"import": "./dist/utils/index.mjs"
52+
},
53+
"./process": {
54+
"types": "./dist/process/index.d.ts",
55+
"require": "./dist/process/index.js",
56+
"import": "./dist/process/index.mjs"
5257
}
5358
},
5459
"devDependencies": {

packages/core/src/process/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './spawn-local'
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { spawn } from 'node:child_process'
2+
import { resolveBinaryPath } from './utils'
3+
4+
export async function spawnLocal(
5+
binaryName: string,
6+
args: string[],
7+
options: {
8+
env: NodeJS.ProcessEnv
9+
stdio: 'inherit' | 'ignore'
10+
// We start traversing the file system tree from this directory and we go up until we find the binary
11+
resolveFrom: string
12+
cwd: string
13+
onBinaryFound: (binaryLocation: string) => void
14+
}
15+
): Promise<void> {
16+
let binaryLocation
17+
try {
18+
binaryLocation = resolveBinaryPath(options.env.PATH ?? '', options.resolveFrom, binaryName)
19+
options.onBinaryFound(binaryLocation)
20+
} catch (e) {
21+
console.error(e)
22+
throw new Error(
23+
`Binary ${binaryName} not found. Make sure postinstall script was allowed if it installs the binary`
24+
)
25+
}
26+
27+
const child = spawn(binaryLocation, [...args], {
28+
shell: true,
29+
stdio: options?.stdio ?? 'inherit',
30+
env: options.env,
31+
cwd: options.cwd,
32+
})
33+
34+
await new Promise<void>((resolve, reject) => {
35+
child.on('close', (code) => {
36+
if (code === 0) {
37+
resolve()
38+
} else {
39+
reject(new Error(`Command failed with code ${code}`))
40+
}
41+
})
42+
43+
child.on('error', (error) => {
44+
reject(error)
45+
})
46+
})
47+
}
File renamed without changes.

packages/core/src/process/utils.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import path from 'node:path'
2+
import fs from 'node:fs'
3+
4+
const getLocalPaths = (startPath: string): string[] => {
5+
const paths: string[] = []
6+
let currentPath = startPath
7+
8+
while (true) {
9+
paths.push(currentPath)
10+
const parentPath = path.resolve(currentPath, '..')
11+
12+
// If we've reached the root directory, stop
13+
if (parentPath === currentPath) {
14+
break
15+
}
16+
17+
currentPath = parentPath
18+
}
19+
20+
return paths
21+
}
22+
23+
export const buildLocalBinaryPaths = (cwd: string): string[] => {
24+
const localPaths = getLocalPaths(path.resolve(cwd)).map((localPath: string) =>
25+
path.join(localPath, 'node_modules/.bin')
26+
)
27+
return localPaths
28+
}
29+
30+
export function resolveBinaryPath(envPath: string, cwd: string, binName: string): string {
31+
const envLocations = envPath.split(path.delimiter)
32+
const localLocations = buildLocalBinaryPaths(cwd)
33+
const directories = [...new Set([...localLocations, ...envLocations])]
34+
for (const directory of directories) {
35+
const binaryPath = path.join(directory, binName)
36+
if (fs.existsSync(binaryPath)) {
37+
return binaryPath
38+
}
39+
}
40+
throw new Error(`Binary ${binName} not found`)
41+
}

packages/nextjs-config/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"lint": "eslint src",
2222
"lint:fix": "eslint src --fix",
2323
"build": "rslib build",
24-
"test:unit": "jest",
24+
"test:unit": "jest --passWithNoTests",
2525
"dev": "rslib build --watch",
2626
"package": "pnpm pack --out $PACKAGE_DEST/%s.tgz"
2727
},
@@ -43,7 +43,8 @@
4343
"license": "MIT",
4444
"dependencies": {
4545
"@posthog/cli": "^0.4.7",
46-
"semver": "^7.7.2"
46+
"semver": "^7.7.2",
47+
"@posthog/core": "workspace:*"
4748
},
4849
"keywords": [
4950
"posthog",

packages/nextjs-config/src/utils.ts

Lines changed: 7 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,7 @@
1-
import path from 'path'
2-
import fs from 'fs'
3-
import { spawn } from 'child_process'
41
import nextPackage from 'next/package.json' with { type: 'json' }
52
import semver from 'semver'
63
import { PostHogNextConfigComplete } from './config'
7-
8-
export function resolveBinaryPath(envPath: string, cwd: string, binName: string): string {
9-
const envLocations = envPath.split(path.delimiter)
10-
const localLocations = buildLocalBinaryPaths(cwd)
11-
const directories = [...new Set([...localLocations, ...envLocations])]
12-
for (const directory of directories) {
13-
const binaryPath = path.join(directory, binName)
14-
if (fs.existsSync(binaryPath)) {
15-
return binaryPath
16-
}
17-
}
18-
throw new Error(`Binary ${binName} not found`)
19-
}
20-
21-
export const buildLocalBinaryPaths = (cwd: string): string[] => {
22-
const localPaths = getLocalPaths(path.resolve(cwd)).map((localPath: string) =>
23-
path.join(localPath, 'node_modules/.bin')
24-
)
25-
return localPaths
26-
}
27-
28-
const getLocalPaths = (startPath: string): string[] => {
29-
const paths: string[] = []
30-
let currentPath = startPath
31-
32-
while (true) {
33-
paths.push(currentPath)
34-
const parentPath = path.resolve(currentPath, '..')
35-
36-
// If we've reached the root directory, stop
37-
if (parentPath === currentPath) {
38-
break
39-
}
40-
41-
currentPath = parentPath
42-
}
43-
44-
return paths
45-
}
4+
import { spawnLocal } from '@posthog/core/process'
465

476
export function getNextJsVersion(): string {
487
return nextPackage.version
@@ -79,37 +38,15 @@ export async function processSourceMaps(posthogOptions: PostHogNextConfigComplet
7938
}
8039

8140
async function callPosthogCli(args: string[], env: NodeJS.ProcessEnv, verbose: boolean): Promise<void> {
82-
let binaryLocation
83-
try {
84-
binaryLocation = resolveBinaryPath(process.env.PATH ?? '', __dirname, 'posthog-cli')
85-
} catch (e) {
86-
throw new Error(`Binary ${e} not found. Make sure postinstall script has been allowed for @posthog/cli`)
87-
}
88-
89-
if (verbose) {
90-
console.log('running posthog-cli from ', binaryLocation)
91-
}
92-
93-
const child = spawn(binaryLocation, [...args], {
94-
shell: true,
95-
stdio: verbose ? 'inherit' : 'ignore',
41+
await spawnLocal('posthog-cli', args, {
9642
env,
43+
stdio: verbose ? 'inherit' : 'ignore',
44+
onBinaryFound: (binaryPath) => {
45+
console.log(`running posthog-cli binary from ${binaryPath}`)
46+
},
47+
resolveFrom: __dirname,
9748
cwd: process.cwd(),
9849
})
99-
100-
await new Promise<void>((resolve, reject) => {
101-
child.on('close', (code) => {
102-
if (code === 0) {
103-
resolve()
104-
} else {
105-
reject(new Error(`Command failed with code ${code}`))
106-
}
107-
})
108-
109-
child.on('error', (error) => {
110-
reject(error)
111-
})
112-
})
11350
}
11451

11552
// Helper to detect if Turbopack is enabled

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)