@contember/cli-common 1.3.0-alpha.7 → 1.3.0-beta.1
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/src/application/Argument.d.ts +1 -1
- package/dist/src/application/Argument.d.ts.map +1 -1
- package/dist/src/application/CommandManager.d.ts +1 -1
- package/dist/src/application/CommandManager.d.ts.map +1 -1
- package/dist/src/application/Input.d.ts +2 -2
- package/dist/src/application/Input.d.ts.map +1 -1
- package/dist/src/application/Option.d.ts +1 -1
- package/dist/src/application/Option.d.ts.map +1 -1
- package/dist/src/application/Option.js +1 -1
- package/dist/src/application/Option.js.map +1 -1
- package/dist/src/application/UsageFormatter.d.ts +2 -2
- package/dist/src/application/UsageFormatter.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/npm/FsManager.d.ts +9 -0
- package/dist/src/npm/FsManager.d.ts.map +1 -0
- package/dist/src/npm/FsManager.js +41 -0
- package/dist/src/npm/FsManager.js.map +1 -0
- package/dist/src/npm/Package.d.ts +8 -0
- package/dist/src/npm/Package.d.ts.map +1 -0
- package/dist/src/npm/Package.js +12 -0
- package/dist/src/npm/Package.js.map +1 -0
- package/dist/src/npm/PackageJson.d.ts +13 -0
- package/dist/src/npm/PackageJson.d.ts.map +1 -0
- package/dist/src/npm/PackageJson.js +3 -0
- package/dist/src/npm/PackageJson.js.map +1 -0
- package/dist/src/npm/PackageWorkspace.d.ts +32 -0
- package/dist/src/npm/PackageWorkspace.d.ts.map +1 -0
- package/dist/src/npm/PackageWorkspace.js +110 -0
- package/dist/src/npm/PackageWorkspace.js.map +1 -0
- package/dist/src/npm/index.d.ts +2 -0
- package/dist/src/npm/index.d.ts.map +1 -0
- package/dist/src/npm/index.js +18 -0
- package/dist/src/npm/index.js.map +1 -0
- package/dist/src/npm/packageManagers/Npm.d.ts +22 -0
- package/dist/src/npm/packageManagers/Npm.d.ts.map +1 -0
- package/dist/src/npm/packageManagers/Npm.js +35 -0
- package/dist/src/npm/packageManagers/Npm.js.map +1 -0
- package/dist/src/npm/packageManagers/PackageManager.d.ts +18 -0
- package/dist/src/npm/packageManagers/PackageManager.d.ts.map +1 -0
- package/dist/src/npm/packageManagers/PackageManager.js +3 -0
- package/dist/src/npm/packageManagers/PackageManager.js.map +1 -0
- package/dist/src/npm/packageManagers/PackageManagerHelpers.d.ts +15 -0
- package/dist/src/npm/packageManagers/PackageManagerHelpers.d.ts.map +1 -0
- package/dist/src/npm/packageManagers/PackageManagerHelpers.js +30 -0
- package/dist/src/npm/packageManagers/PackageManagerHelpers.js.map +1 -0
- package/dist/src/npm/packageManagers/Pnpm.d.ts +22 -0
- package/dist/src/npm/packageManagers/Pnpm.d.ts.map +1 -0
- package/dist/src/npm/packageManagers/Pnpm.js +37 -0
- package/dist/src/npm/packageManagers/Pnpm.js.map +1 -0
- package/dist/src/npm/packageManagers/Yarn.d.ts +22 -0
- package/dist/src/npm/packageManagers/Yarn.d.ts.map +1 -0
- package/dist/src/npm/packageManagers/Yarn.js +36 -0
- package/dist/src/npm/packageManagers/Yarn.js.map +1 -0
- package/dist/src/npm/packageManagers/YarnClassic.d.ts +22 -0
- package/dist/src/npm/packageManagers/YarnClassic.d.ts.map +1 -0
- package/dist/src/npm/packageManagers/YarnClassic.js +36 -0
- package/dist/src/npm/packageManagers/YarnClassic.js.map +1 -0
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/utils/PathMapping.d.ts +1 -1
- package/dist/src/utils/PathMapping.d.ts.map +1 -1
- package/dist/src/utils/Workspace.d.ts +5 -4
- package/dist/src/utils/Workspace.d.ts.map +1 -1
- package/dist/src/utils/Workspace.js +19 -6
- package/dist/src/utils/Workspace.js.map +1 -1
- package/dist/src/utils/commands.d.ts +21 -0
- package/dist/src/utils/commands.d.ts.map +1 -0
- package/dist/src/utils/commands.js +57 -0
- package/dist/src/utils/commands.js.map +1 -0
- package/dist/src/utils/json.d.ts +4 -4
- package/dist/src/utils/json.d.ts.map +1 -1
- package/dist/src/utils/version.d.ts +1 -1
- package/dist/src/utils/version.d.ts.map +1 -1
- package/dist/src/utils/version.js.map +1 -1
- package/package.json +3 -2
- package/src/.eslintrc.js +5 -0
- package/src/index.ts +1 -0
- package/src/npm/FsManager.ts +38 -0
- package/src/npm/Package.ts +10 -0
- package/src/npm/PackageJson.ts +11 -0
- package/src/npm/PackageWorkspace.ts +126 -0
- package/src/npm/index.ts +1 -0
- package/src/npm/packageManagers/Npm.ts +39 -0
- package/src/npm/packageManagers/PackageManager.ts +11 -0
- package/src/npm/packageManagers/PackageManagerHelpers.ts +35 -0
- package/src/npm/packageManagers/Pnpm.ts +42 -0
- package/src/npm/packageManagers/Yarn.ts +40 -0
- package/src/npm/packageManagers/YarnClassic.ts +40 -0
- package/src/utils/Workspace.ts +20 -7
- package/src/utils/commands.ts +65 -0
- package/src/utils/version.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/utils/version.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../src/utils/version.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,QAAO,MAGpC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/utils/version.ts"],"names":[],"mappings":";;;AAAA,yCAAgC;AAChC,4CAA0C;AAEnC,MAAM,iBAAiB,GAAG,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/utils/version.ts"],"names":[],"mappings":";;;AAAA,yCAAgC;AAChC,4CAA0C;AAEnC,MAAM,iBAAiB,GAAG,GAAW,EAAE;IAC7C,8DAA8D;IAC9D,OAAO,OAAO,CAAC,IAAA,gBAAI,EAAC,uBAAW,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAA;AAC1D,CAAC,CAAA;AAHY,QAAA,iBAAiB,qBAG7B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contember/cli-common",
|
|
3
|
-
"version": "1.3.0-
|
|
3
|
+
"version": "1.3.0-beta.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"typings": "dist/src/index.d.ts",
|
|
@@ -19,10 +19,11 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"chalk": "^4.1.2",
|
|
21
21
|
"download-tarball": "^2.0.0",
|
|
22
|
+
"fast-glob": "^3.2.12",
|
|
22
23
|
"fs-extra": "^10.0.0",
|
|
23
24
|
"get-package-json-from-registry": "^2.2.2",
|
|
24
25
|
"js-yaml": "^4.1.0",
|
|
25
26
|
"npm-package-arg": "^9.0.2",
|
|
26
27
|
"registry-info": "^1.0.0"
|
|
27
28
|
}
|
|
28
|
-
}
|
|
29
|
+
}
|
package/src/.eslintrc.js
ADDED
package/src/index.ts
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import jsyaml from 'js-yaml'
|
|
2
|
+
import fs from 'node:fs/promises'
|
|
3
|
+
import glob from 'fast-glob'
|
|
4
|
+
import { pathExists } from '../utils'
|
|
5
|
+
|
|
6
|
+
export class FsManager {
|
|
7
|
+
constructor() {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public async exists(filename: string): Promise<boolean> {
|
|
11
|
+
return await pathExists(filename)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public async tryReadJson<T = any>(filename: string): Promise<T | null> {
|
|
15
|
+
const content = await this.tryReadFile(filename)
|
|
16
|
+
return content !== null ? JSON.parse(content) : null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public async tryReadYaml<T = any>(filename: string): Promise<T | null> {
|
|
20
|
+
const content = await this.tryReadFile(filename)
|
|
21
|
+
return content !== null ? jsyaml.load(content) as T : null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public async tryReadFile(filename: string): Promise<string | null> {
|
|
25
|
+
try {
|
|
26
|
+
return await fs.readFile(filename, 'utf8')
|
|
27
|
+
} catch (error: any) {
|
|
28
|
+
if (error.code === 'ENOENT') {
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
throw error
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public async listDirectories(dir: string, patterns: string[]): Promise<string[]> {
|
|
36
|
+
return await glob(patterns, { onlyDirectories: true, cwd: dir })
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type PackageJson =
|
|
2
|
+
& {
|
|
3
|
+
name: string
|
|
4
|
+
version: string
|
|
5
|
+
dependencies?: Record<string, string>
|
|
6
|
+
devDependencies?: Record<string, string>
|
|
7
|
+
workspaces?: string[] | { packages?: string[]; nohoist?: string[] }
|
|
8
|
+
}
|
|
9
|
+
& {
|
|
10
|
+
[prop: string]: undefined
|
|
11
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { PackageManager } from './packageManagers/PackageManager'
|
|
2
|
+
import { Package } from './Package'
|
|
3
|
+
import { FsManager } from './FsManager'
|
|
4
|
+
import { dirname, join } from 'node:path'
|
|
5
|
+
import { PackageJson } from './PackageJson'
|
|
6
|
+
import { pathExists } from '../utils'
|
|
7
|
+
|
|
8
|
+
export type Dependency = {
|
|
9
|
+
pckg: Package
|
|
10
|
+
isDev: boolean
|
|
11
|
+
version: string
|
|
12
|
+
name: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export class PackageWorkspace {
|
|
17
|
+
constructor(
|
|
18
|
+
private readonly packageManager: PackageManager,
|
|
19
|
+
private readonly fsManager: FsManager,
|
|
20
|
+
public readonly rootPackage: Package,
|
|
21
|
+
public readonly packages: Package[],
|
|
22
|
+
) {
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get allPackages() {
|
|
26
|
+
return [this.rootPackage, ...this.packages]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public findDefinedDependencies(packageName: string): Dependency[] {
|
|
30
|
+
return this.allPackages.flatMap<Dependency>(it => {
|
|
31
|
+
for (const type of ['dependencies', 'devDependencies'] as const) {
|
|
32
|
+
const version = it.packageJson[type]?.[packageName]
|
|
33
|
+
if (version) {
|
|
34
|
+
return [{ pckg: it, isDev: type === 'devDependencies', version: version, name: packageName }]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return []
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public async findInstalledDependencies(packageName: string): Promise<{ installed?: Dependency; defined: Dependency }[]> {
|
|
42
|
+
const definedDependencies = this.findDefinedDependencies(packageName)
|
|
43
|
+
|
|
44
|
+
const deps: { installed?: Dependency; defined: Dependency }[] = []
|
|
45
|
+
for (const defined of definedDependencies) {
|
|
46
|
+
const packageJsonPath = await this.resolvePackageJson(defined.pckg.dir, packageName)
|
|
47
|
+
if (!packageJsonPath) {
|
|
48
|
+
deps.push({ defined })
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
const packageJson = await this.fsManager.tryReadJson<PackageJson>(packageJsonPath)
|
|
52
|
+
deps.push({ defined, installed: { ...defined, version: packageJson?.version ?? '' } })
|
|
53
|
+
}
|
|
54
|
+
return deps
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private async resolvePackageJson(dir: string, packageName: string) {
|
|
58
|
+
while (true) {
|
|
59
|
+
const fullPath = join(dir, 'node_modules', packageName, 'package.json')
|
|
60
|
+
if (await pathExists(fullPath)) {
|
|
61
|
+
return fullPath
|
|
62
|
+
}
|
|
63
|
+
if (dir === '/') {
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
dir = dirname(dir)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async updateEverywhere(updates: Record<string, string>): Promise<Dependency[]> {
|
|
71
|
+
const defined = Object.keys(updates).flatMap(it => this.findDefinedDependencies(it))
|
|
72
|
+
const byPckg = new Map<Package, Dependency[]>()
|
|
73
|
+
for (const it of defined) {
|
|
74
|
+
const arr = byPckg.get(it.pckg) ?? []
|
|
75
|
+
byPckg.set(it.pckg, arr)
|
|
76
|
+
arr.push(it)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const updated: Dependency[] = []
|
|
80
|
+
for (const [pckg, deps] of byPckg.entries()) {
|
|
81
|
+
const prod = deps.filter(it => !it.isDev)
|
|
82
|
+
const dev = deps.filter(it => it.isDev)
|
|
83
|
+
for (const [isDev, deps] of [[false, prod], [true, dev]] as const) {
|
|
84
|
+
if (deps.length === 0) {
|
|
85
|
+
continue
|
|
86
|
+
}
|
|
87
|
+
await this.packageManager.install({
|
|
88
|
+
pckg,
|
|
89
|
+
isDev,
|
|
90
|
+
dependencies: Object.fromEntries(deps.map(it => [it.name, updates[it.name]])),
|
|
91
|
+
})
|
|
92
|
+
updated.push(...deps)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return updated
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export class PackageWorkspaceResolver {
|
|
100
|
+
constructor(
|
|
101
|
+
private fsManager: FsManager,
|
|
102
|
+
private packageManagers: PackageManager[],
|
|
103
|
+
) {
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public async resolve(dir: string): Promise<PackageWorkspace> {
|
|
107
|
+
const packageJson = await this.fsManager.tryReadJson<PackageJson>(join(dir, 'package.json'))
|
|
108
|
+
if (!packageJson) {
|
|
109
|
+
throw `package.json not found.`
|
|
110
|
+
}
|
|
111
|
+
const pm = await this.resolvePackageManager({ dir, packageJson })
|
|
112
|
+
const rootPackage = new Package(dir, true, packageJson)
|
|
113
|
+
const workspacePackages = await pm.readWorkspacePackages({ dir, packageJson })
|
|
114
|
+
|
|
115
|
+
return new PackageWorkspace(pm, this.fsManager, rootPackage, workspacePackages)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private async resolvePackageManager(args: { dir: string; packageJson: PackageJson }): Promise<PackageManager> {
|
|
119
|
+
for (const pm of this.packageManagers) {
|
|
120
|
+
if (await pm.isActive(args)) {
|
|
121
|
+
return pm
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
throw `No lockfile found. Please install dependencies using package manager of your choice.`
|
|
125
|
+
}
|
|
126
|
+
}
|
package/src/npm/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PackageWorkspace'
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PackageManager } from './PackageManager'
|
|
2
|
+
import { FsManager } from '../FsManager'
|
|
3
|
+
import { Package } from '../Package'
|
|
4
|
+
import { PackageJson } from '../PackageJson'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
import { PackageManagerHelpers } from './PackageManagerHelpers'
|
|
7
|
+
import { runCommand } from '../../utils/commands'
|
|
8
|
+
|
|
9
|
+
export class Npm implements PackageManager {
|
|
10
|
+
constructor(
|
|
11
|
+
private readonly fsManager: FsManager,
|
|
12
|
+
) {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async install({ pckg, dependencies, isDev }: { pckg: Package; isDev: boolean; dependencies: Record<string, string> }): Promise<void> {
|
|
16
|
+
const { output } = runCommand('npm', [
|
|
17
|
+
'install',
|
|
18
|
+
isDev ? '--save-dev' : '--save',
|
|
19
|
+
...PackageManagerHelpers.formatPackagesToInstall(dependencies),
|
|
20
|
+
], {
|
|
21
|
+
cwd: pckg.dir,
|
|
22
|
+
stderr: process.stderr,
|
|
23
|
+
stdout: process.stdout,
|
|
24
|
+
})
|
|
25
|
+
await output
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async isActive({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<boolean> {
|
|
29
|
+
return await this.fsManager.exists(join(dir, 'package-lock.json'))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async readWorkspacePackages({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<Package[]> {
|
|
33
|
+
return await PackageManagerHelpers.readWorkspacePackages({
|
|
34
|
+
fsManager: this.fsManager,
|
|
35
|
+
dir,
|
|
36
|
+
workspaces: PackageManagerHelpers.getWorkspacesFromPackageJson({ packageJson }),
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PackageJson } from '../PackageJson'
|
|
2
|
+
|
|
3
|
+
import { Package } from '../Package'
|
|
4
|
+
|
|
5
|
+
export interface PackageManager {
|
|
6
|
+
isActive(args: { dir: string; packageJson: PackageJson }): Promise<boolean>
|
|
7
|
+
|
|
8
|
+
readWorkspacePackages(args: { dir: string; packageJson: PackageJson }): Promise<Package[]>
|
|
9
|
+
|
|
10
|
+
install(args: { pckg: Package; isDev: boolean; dependencies: Record<string, string> }): Promise<void>
|
|
11
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { FsManager } from '../FsManager'
|
|
2
|
+
import { Package } from '../Package'
|
|
3
|
+
import { PackageJson } from '../PackageJson'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
|
|
6
|
+
export class PackageManagerHelpers {
|
|
7
|
+
static async readWorkspacePackages({ fsManager, dir, workspaces }: {
|
|
8
|
+
fsManager: FsManager
|
|
9
|
+
dir: string
|
|
10
|
+
workspaces: string[]
|
|
11
|
+
}): Promise<Package[]> {
|
|
12
|
+
const dirs = await fsManager.listDirectories(dir, workspaces)
|
|
13
|
+
|
|
14
|
+
const packageJson = await Promise.all(dirs.map(async it => {
|
|
15
|
+
const packageJson = await fsManager.tryReadJson<PackageJson>(join(it, 'package.json'))
|
|
16
|
+
return packageJson ? [packageJson, it] as const : null
|
|
17
|
+
}))
|
|
18
|
+
|
|
19
|
+
return packageJson.filter(<T>(it: T | null): it is T => it !== null).map(([packageJson, dir]) => new Package(dir, false, packageJson))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static getWorkspacesFromPackageJson({ packageJson }: { packageJson: PackageJson }): string[] {
|
|
23
|
+
if (!packageJson.workspaces) {
|
|
24
|
+
return []
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(packageJson.workspaces)) {
|
|
27
|
+
return packageJson.workspaces
|
|
28
|
+
}
|
|
29
|
+
return [...packageJson.workspaces?.packages ?? [], ...packageJson.workspaces?.nohoist ?? []]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static formatPackagesToInstall(packages: Record<string, string>): string[] {
|
|
33
|
+
return Object.entries(packages).map(([name, version]) => `${name}@${version}`)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { FsManager } from '../FsManager'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
import { PackageJson } from '../PackageJson'
|
|
5
|
+
import { PackageManager } from './PackageManager'
|
|
6
|
+
import { Package } from '../Package'
|
|
7
|
+
import { PackageManagerHelpers } from './PackageManagerHelpers'
|
|
8
|
+
import { runCommand } from '../../utils/commands'
|
|
9
|
+
|
|
10
|
+
export class Pnpm implements PackageManager {
|
|
11
|
+
constructor(
|
|
12
|
+
private readonly fsManager: FsManager,
|
|
13
|
+
) {
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async install({ pckg, dependencies, isDev }: { pckg: Package; isDev: boolean; dependencies: Record<string, string> }): Promise<void> {
|
|
17
|
+
const { output } = runCommand('pnpm', [
|
|
18
|
+
'add',
|
|
19
|
+
isDev ? '--save-dev' : '--save',
|
|
20
|
+
pckg.isRoot ? '--ignore-workspace-root-check' : undefined,
|
|
21
|
+
...PackageManagerHelpers.formatPackagesToInstall(dependencies),
|
|
22
|
+
], {
|
|
23
|
+
cwd: pckg.dir,
|
|
24
|
+
stderr: process.stderr,
|
|
25
|
+
stdout: process.stdout,
|
|
26
|
+
})
|
|
27
|
+
await output
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async isActive({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<boolean> {
|
|
31
|
+
return await this.fsManager.exists(join(dir, 'pnpm-lock.yaml'))
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async readWorkspacePackages({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<Package[]> {
|
|
35
|
+
const pnpmWorkspaces = await this.fsManager.tryReadJson(join(dir, 'pnpm-workspace.yaml'))
|
|
36
|
+
return await PackageManagerHelpers.readWorkspacePackages({
|
|
37
|
+
fsManager: this.fsManager,
|
|
38
|
+
dir,
|
|
39
|
+
workspaces: pnpmWorkspaces.packages,
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PackageManager } from './PackageManager'
|
|
2
|
+
import { FsManager } from '../FsManager'
|
|
3
|
+
import { Package } from '../Package'
|
|
4
|
+
import { PackageJson } from '../PackageJson'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
import { PackageManagerHelpers } from './PackageManagerHelpers'
|
|
7
|
+
import { runCommand } from '../../utils/commands'
|
|
8
|
+
|
|
9
|
+
export class Yarn implements PackageManager {
|
|
10
|
+
constructor(
|
|
11
|
+
private readonly fsManager: FsManager,
|
|
12
|
+
) {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async install({ pckg, dependencies, isDev }: { pckg: Package; isDev: boolean; dependencies: Record<string, string> }): Promise<void> {
|
|
16
|
+
const { output } = runCommand('yarn', [
|
|
17
|
+
'add',
|
|
18
|
+
isDev ? '--dev' : undefined,
|
|
19
|
+
...PackageManagerHelpers.formatPackagesToInstall(dependencies),
|
|
20
|
+
], {
|
|
21
|
+
cwd: pckg.dir,
|
|
22
|
+
stderr: process.stderr,
|
|
23
|
+
stdout: process.stdout,
|
|
24
|
+
})
|
|
25
|
+
await output
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async isActive({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<boolean> {
|
|
29
|
+
return await this.fsManager.exists(join(dir, 'yarn.lock'))
|
|
30
|
+
&& (!packageJson.packageManager || (packageJson.packageManager as string).startsWith('yarn@3') || (packageJson.packageManager as string).startsWith('yarn@2'))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async readWorkspacePackages({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<Package[]> {
|
|
34
|
+
return await PackageManagerHelpers.readWorkspacePackages({
|
|
35
|
+
fsManager: this.fsManager,
|
|
36
|
+
dir,
|
|
37
|
+
workspaces: PackageManagerHelpers.getWorkspacesFromPackageJson({ packageJson }),
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PackageManager } from './PackageManager'
|
|
2
|
+
import { FsManager } from '../FsManager'
|
|
3
|
+
import { Package } from '../Package'
|
|
4
|
+
import { PackageJson } from '../PackageJson'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
import { PackageManagerHelpers } from './PackageManagerHelpers'
|
|
7
|
+
import { runCommand } from '../../utils/commands'
|
|
8
|
+
|
|
9
|
+
export class YarnClassic implements PackageManager {
|
|
10
|
+
constructor(
|
|
11
|
+
private readonly fsManager: FsManager,
|
|
12
|
+
) {
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async install({ pckg, dependencies, isDev }: { pckg: Package; isDev: boolean; dependencies: Record<string, string> }): Promise<void> {
|
|
16
|
+
const { output } = runCommand('yarn', [
|
|
17
|
+
'add',
|
|
18
|
+
isDev ? '--dev' : undefined,
|
|
19
|
+
pckg.isRoot ? '--ignore-workspace-root-check' : undefined,
|
|
20
|
+
...PackageManagerHelpers.formatPackagesToInstall(dependencies),
|
|
21
|
+
], {
|
|
22
|
+
cwd: pckg.dir,
|
|
23
|
+
stderr: process.stderr,
|
|
24
|
+
stdout: process.stdout,
|
|
25
|
+
})
|
|
26
|
+
await output
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async isActive({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<boolean> {
|
|
30
|
+
return await this.fsManager.exists(join(dir, 'yarn.lock'))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async readWorkspacePackages({ dir, packageJson }: { dir: string; packageJson: PackageJson }): Promise<Package[]> {
|
|
34
|
+
return await PackageManagerHelpers.readWorkspacePackages({
|
|
35
|
+
fsManager: this.fsManager,
|
|
36
|
+
dir,
|
|
37
|
+
workspaces: PackageManagerHelpers.getWorkspacesFromPackageJson({ packageJson }),
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/utils/Workspace.ts
CHANGED
|
@@ -6,6 +6,12 @@ import { getPackageVersion } from './version'
|
|
|
6
6
|
import { readYaml } from './yaml'
|
|
7
7
|
import { CliEnv, readCliEnv } from '../application'
|
|
8
8
|
import { pathExists } from './fs'
|
|
9
|
+
import { PackageWorkspace, PackageWorkspaceResolver } from '../npm/PackageWorkspace'
|
|
10
|
+
import { FsManager } from '../npm/FsManager'
|
|
11
|
+
import { Yarn } from '../npm/packageManagers/Yarn'
|
|
12
|
+
import { YarnClassic } from '../npm/packageManagers/YarnClassic'
|
|
13
|
+
import { Pnpm } from '../npm/packageManagers/Pnpm'
|
|
14
|
+
import { Npm } from '../npm/packageManagers/Npm'
|
|
9
15
|
|
|
10
16
|
export interface WorkspaceDirectoryArgument {
|
|
11
17
|
workspaceDirectory: string
|
|
@@ -28,7 +34,6 @@ export const createWorkspace = async ({ workspaceDirectory, workspaceName, templ
|
|
|
28
34
|
|
|
29
35
|
export interface WorkspaceConfig {
|
|
30
36
|
api?: {
|
|
31
|
-
version?: string
|
|
32
37
|
configFile?: string
|
|
33
38
|
}
|
|
34
39
|
admin?: {
|
|
@@ -45,11 +50,20 @@ export class Workspace {
|
|
|
45
50
|
public readonly directory: string,
|
|
46
51
|
public readonly env: CliEnv,
|
|
47
52
|
public readonly config: WorkspaceConfig,
|
|
53
|
+
private readonly packageWorkspaceResolver: PackageWorkspaceResolver,
|
|
48
54
|
) {}
|
|
49
55
|
|
|
50
56
|
public static async get(workspaceDirectory: string) {
|
|
51
57
|
const config = await readWorkspaceConfig({ workspaceDirectory })
|
|
52
|
-
|
|
58
|
+
const fsManager = new FsManager()
|
|
59
|
+
const packageWorkspaceResolver = new PackageWorkspaceResolver(fsManager, [
|
|
60
|
+
new Yarn(fsManager),
|
|
61
|
+
new YarnClassic(fsManager),
|
|
62
|
+
new Pnpm(fsManager),
|
|
63
|
+
new Npm(fsManager),
|
|
64
|
+
])
|
|
65
|
+
|
|
66
|
+
return new Workspace(workspaceDirectory, readCliEnv(), config, packageWorkspaceResolver)
|
|
53
67
|
}
|
|
54
68
|
|
|
55
69
|
get name() {
|
|
@@ -60,14 +74,13 @@ export class Workspace {
|
|
|
60
74
|
return this.config?.admin?.enabled || false
|
|
61
75
|
}
|
|
62
76
|
|
|
63
|
-
get apiVersion(): string | undefined {
|
|
64
|
-
return this.config?.api?.version || undefined
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
77
|
public isSingleProjectMode(): boolean {
|
|
69
78
|
return !!this.env.projectName
|
|
70
79
|
}
|
|
80
|
+
|
|
81
|
+
public async resolvePackageWorkspace(): Promise<PackageWorkspace> {
|
|
82
|
+
return await this.packageWorkspaceResolver.resolve(this.directory)
|
|
83
|
+
}
|
|
71
84
|
}
|
|
72
85
|
|
|
73
86
|
export const formatWorkspaceConfigPath = (workspaceDirectory: string) => [
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ChildProcessWithoutNullStreams, spawn } from 'node:child_process'
|
|
2
|
+
import { Readable, Writable } from 'node:stream'
|
|
3
|
+
import chalk from 'chalk'
|
|
4
|
+
|
|
5
|
+
export type RunningCommand = { child: ChildProcessWithoutNullStreams; output: Promise<string> }
|
|
6
|
+
export const runCommand = (
|
|
7
|
+
command: string,
|
|
8
|
+
args: (string | undefined)[],
|
|
9
|
+
options: {
|
|
10
|
+
cwd: string
|
|
11
|
+
stdin?: Readable
|
|
12
|
+
stdout?: Writable
|
|
13
|
+
stderr?: Writable
|
|
14
|
+
env?: NodeJS.ProcessEnv
|
|
15
|
+
detached?: boolean
|
|
16
|
+
},
|
|
17
|
+
): RunningCommand => {
|
|
18
|
+
const args2 = args.filter((it): it is string => it !== undefined)
|
|
19
|
+
if (!process.env.DISABLE_COMMAND_PRINTING) {
|
|
20
|
+
console.error(chalk.gray(`$ ${command} ${args2.map(it => `'${it.replace(/'/g, `'\\''`)}'`).join(' ')}`))
|
|
21
|
+
}
|
|
22
|
+
const child = spawn(command, args2, {
|
|
23
|
+
cwd: options.cwd,
|
|
24
|
+
env: { ...process.env, ...(options.env || {}) },
|
|
25
|
+
detached: options.detached,
|
|
26
|
+
})
|
|
27
|
+
if (options.stdin) {
|
|
28
|
+
options.stdin.pipe(child.stdin)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let stdout = ''
|
|
32
|
+
let stderr = ''
|
|
33
|
+
|
|
34
|
+
child.stdout.on('data', (chunk): void => {
|
|
35
|
+
stdout += chunk.toString()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
child.stderr.on('data', (chunk): void => {
|
|
39
|
+
stderr += chunk.toString()
|
|
40
|
+
})
|
|
41
|
+
if (options.stdout) {
|
|
42
|
+
child.stdout.pipe(options.stdout)
|
|
43
|
+
}
|
|
44
|
+
if (options.stderr) {
|
|
45
|
+
child.stderr.pipe(options.stderr)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const output = new Promise<string>((resolve, reject) => {
|
|
49
|
+
child.on('exit', (exitCode): void => {
|
|
50
|
+
if (exitCode === 0) {
|
|
51
|
+
resolve(stdout)
|
|
52
|
+
} else {
|
|
53
|
+
reject(new ChildProcessError(exitCode, stderr))
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
return { output, child }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class ChildProcessError extends Error {
|
|
62
|
+
constructor(public readonly exitCode: number | null, public readonly stderr: string) {
|
|
63
|
+
super(`Command has failed(${exitCode}): ${stderr} `)
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/utils/version.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
2
|
import { packageRoot } from '../pathUtils'
|
|
3
3
|
|
|
4
|
-
export const getPackageVersion = () => {
|
|
4
|
+
export const getPackageVersion = (): string => {
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
6
6
|
return require(join(packageRoot, 'package.json')).version
|
|
7
7
|
}
|