Skip to content

Commit 6c689df

Browse files
feat: plugin utils
1 parent a448cfa commit 6c689df

File tree

18 files changed

+916
-8
lines changed

18 files changed

+916
-8
lines changed

src/cmd.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { VERSION } from './version.ts'
66

77
import { buildgraph } from './commands/buildgraph/index.ts'
88
import { run } from './commands/run/index.ts'
9+
import { plugin } from './commands/plugin/index.ts'
910
import { engine } from './commands/engine/index.ts'
1011
import { info } from './commands/info/index.ts'
1112
import { build } from './commands/build/index.ts'
@@ -57,6 +58,7 @@ export const cli = cmd
5758
.command('buildgraph', buildgraph)
5859
.command('run', run)
5960
.command('engine', engine)
61+
.command('plugin', plugin)
6062
.command('build', build)
6163
.command('cook', cook)
6264
.command('pkg', pkg)

src/commands/info/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import type { GlobalOptions } from '../../lib/types.ts'
44
import { buildId } from './buildId.ts'
55
import { config } from './config.ts'
66
import { listTargets } from './list-targets.ts'
7+
import { project } from './project.ts'
8+
import { plugin } from './plugin.ts'
79

810
export const info = new Command<GlobalOptions>()
911
.description('info')
@@ -13,3 +15,5 @@ export const info = new Command<GlobalOptions>()
1315
.command('buildId', buildId)
1416
.command('config', config)
1517
.command('list-targets', listTargets)
18+
.command('project', project)
19+
.command('plugin', plugin)

src/commands/info/plugin.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Command } from '@cliffy/command'
2+
import * as path from '@std/path'
3+
4+
import type { GlobalOptions } from '../../lib/types.ts'
5+
import { Config } from '../../lib/config.ts'
6+
import { displayUPluginInfo, findPluginFile, readUPluginFile } from '../../lib/project-info.ts'
7+
8+
export const plugin = new Command<GlobalOptions>()
9+
.description('Displays information about a plugin')
10+
.arguments('<pluginName>')
11+
.action(async (options, pluginName: string) => {
12+
const config = Config.getInstance()
13+
const { engine: { path: enginePath }, project: { path: projectPath } } = config.mergeConfigCLIConfig({
14+
cliOptions: options,
15+
})
16+
17+
const match = await findPluginFile(pluginName, projectPath, enginePath)
18+
if (match) {
19+
const pluginData = await readUPluginFile(match)
20+
if (pluginData) {
21+
displayUPluginInfo(pluginData)
22+
} else {
23+
console.log(`The plugin ${pluginName} could not be loaded`)
24+
}
25+
} else {
26+
console.log(`Unable to find the plugin ${pluginName}`)
27+
}
28+
})

src/commands/info/project.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Command } from '@cliffy/command'
2+
3+
import { createProject } from '../../lib/project.ts'
4+
import type { GlobalOptions } from '../../lib/types.ts'
5+
import { Config } from '../../lib/config.ts'
6+
import { displayUProjectInfo, readUProjectFile } from '../../lib/project-info.ts'
7+
8+
export const project = new Command<GlobalOptions>()
9+
.description('Displays information about the project')
10+
.action(async (options) => {
11+
const config = Config.getInstance()
12+
const { engine: { path: enginePath }, project: { path: projectPath } } = config.mergeConfigCLIConfig({
13+
cliOptions: options,
14+
})
15+
const project = await createProject(enginePath, projectPath)
16+
17+
const projectData = await readUProjectFile(project.projectFileVars.projectFullPath)
18+
if (projectData) {
19+
displayUProjectInfo(projectData)
20+
} else {
21+
console.log('The project file could not be loaded')
22+
}
23+
})

src/commands/plugin/add.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Command } from '@cliffy/command'
2+
import { Config } from '../../lib/config.ts'
3+
import type { GlobalOptions } from '../../lib/types.ts'
4+
import { createProject } from '../../lib/project.ts'
5+
import { readUProjectFile, UnrealEnginePluginReference, UProject, writeUProjectFile } from '../../lib/project-info.ts'
6+
import { exec } from '../../lib/utils.ts'
7+
import * as path from '@std/path'
8+
9+
export type AddOptions = typeof add extends Command<void, void, infer Options, infer Argument, GlobalOptions> ? Options
10+
: never
11+
12+
export const add = new Command<GlobalOptions>()
13+
.description('Adds an external plugin to the project')
14+
.arguments('<url:string> <pluginName:string>')
15+
.option(
16+
'-f, --folder <folder:string>',
17+
"Plugin subfolder to install to, leaving default will install directly into the project's Plugin folder",
18+
{ default: '' },
19+
)
20+
.option('-e, --enable', 'Enable this plugin in the project, defaults to true', { default: true })
21+
.action(async (options, url, pluginName) => {
22+
const { folder, enable } = options as AddOptions
23+
const config = Config.getInstance()
24+
const { engine: { path: enginePath }, project: { path: projectPath } } = config.mergeConfigCLIConfig({
25+
cliOptions: options,
26+
})
27+
const project = await createProject(enginePath, projectPath)
28+
29+
const target_loc = path.relative(
30+
Deno.cwd(),
31+
path.join(project.projectFileVars.projectDir, 'Plugins', folder, pluginName),
32+
)
33+
34+
console.log(`installing ${pluginName} to ${target_loc}`)
35+
36+
await exec('git', ['clone', '--depth', '1', url, target_loc])
37+
38+
if (enable) {
39+
project.enablePlugin({
40+
pluginName: pluginName,
41+
shouldEnable: true,
42+
})
43+
}
44+
})

src/commands/plugin/disable.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Command } from '@cliffy/command'
2+
import { Config } from '../../lib/config.ts'
3+
import type { GlobalOptions } from '../../lib/types.ts'
4+
import { createProject } from '../../lib/project.ts'
5+
import { readUProjectFile, UnrealEnginePluginReference, UProject, writeUProjectFile } from '../../lib/project-info.ts'
6+
7+
export type DisableOptions = typeof disable extends Command<void, void, infer Options, infer Argument, GlobalOptions>
8+
? Options
9+
: never
10+
11+
export const disable = new Command<GlobalOptions>()
12+
.description('Disables a plugin for the project')
13+
.arguments('<target:string>')
14+
.action(async (options, target) => {
15+
const config = Config.getInstance()
16+
const { engine: { path: enginePath }, project: { path: projectPath } } = config.mergeConfigCLIConfig({
17+
cliOptions: options,
18+
})
19+
const project = await createProject(enginePath, projectPath)
20+
project.enablePlugin({
21+
pluginName: target,
22+
shouldEnable: false,
23+
})
24+
})

src/commands/plugin/enable.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Command } from '@cliffy/command'
2+
import { Config } from '../../lib/config.ts'
3+
import type { GlobalOptions } from '../../lib/types.ts'
4+
import { createProject } from '../../lib/project.ts'
5+
import { readUProjectFile, UnrealEnginePluginReference, UProject, writeUProjectFile } from '../../lib/project-info.ts'
6+
7+
export type EnableOptions = typeof enable extends Command<void, void, infer Options, infer Argument, GlobalOptions>
8+
? Options
9+
: never
10+
11+
export const enable = new Command<GlobalOptions>()
12+
.description('Disables a plugin for the project')
13+
.arguments('<target:string>')
14+
.action(async (options, target) => {
15+
const config = Config.getInstance()
16+
const { engine: { path: enginePath }, project: { path: projectPath } } = config.mergeConfigCLIConfig({
17+
cliOptions: options,
18+
})
19+
const project = await createProject(enginePath, projectPath)
20+
project.enablePlugin({
21+
pluginName: target,
22+
shouldEnable: true,
23+
})
24+
})

src/commands/plugin/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Command } from '@cliffy/command'
2+
import type { GlobalOptions } from '../../lib/types.ts'
3+
4+
import { info } from './info.ts'
5+
import { add } from './add.ts'
6+
import { list } from './list.ts'
7+
import { enable } from './enable.ts'
8+
import { disable } from './disable.ts'
9+
10+
export const plugin = new Command<GlobalOptions>()
11+
.description('Prints information about a plugin')
12+
.action(function () {
13+
this.showHelp()
14+
})
15+
.command('info', info)
16+
.command('list', list)
17+
.command('enable', enable)
18+
.command('disable', disable)
19+
.command('add', add)

src/commands/plugin/info.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Command } from '@cliffy/command'
2+
import { Config } from '../../lib/config.ts'
3+
import type { GlobalOptions } from '../../lib/types.ts'
4+
5+
export const info = new Command<GlobalOptions>()
6+
.description('Prints information about a plugin')
7+
.action((options) => {
8+
const config = Config.getInstance()
9+
const cfg = config.mergeConfigCLIConfig({ cliOptions: options })
10+
})

src/commands/plugin/list.ts

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import { Command, EnumType } from '@cliffy/command'
2+
import { Config } from '../../lib/config.ts'
3+
import type { GlobalOptions } from '../../lib/types.ts'
4+
import { createProject } from '../../lib/project.ts'
5+
import { findFilesByExtension } from '../../lib/utils.ts'
6+
import * as path from '@std/path'
7+
import { findPluginFile, readUPluginFile, readUProjectFile } from '../../lib/project-info.ts'
8+
9+
async function getEnabledPlugins(pluginName: string, projectPath: string, enginePath: string, refArray: Array<string>) {
10+
const pluginArray: Array<string> = []
11+
const match = await findPluginFile(pluginName, projectPath, enginePath)
12+
if (match && match != '') {
13+
const pluginData = await readUPluginFile(match)
14+
15+
if (pluginData && pluginData.Plugins) {
16+
for (const plugin of pluginData.Plugins) {
17+
if (plugin.Enabled) {
18+
if (![...refArray, ...pluginArray].includes(plugin.Name)) {
19+
pluginArray.push(plugin.Name)
20+
}
21+
}
22+
}
23+
24+
const subPlugins: Array<string> = []
25+
for (const pluginName of pluginArray) {
26+
if (![...refArray, ...subPlugins].includes(pluginName)) {
27+
const subPluginArray = await getEnabledPlugins(pluginName, projectPath, enginePath, [
28+
...pluginArray,
29+
...refArray,
30+
...subPlugins,
31+
])
32+
subPlugins.push(...subPluginArray)
33+
}
34+
}
35+
pluginArray.push(...subPlugins)
36+
}
37+
} else {
38+
console.log(`Unable to find the plugin ${pluginName}`)
39+
}
40+
return pluginArray
41+
}
42+
43+
enum ListTarget {
44+
All = 'all',
45+
Referenced = 'referenced',
46+
Project = 'project',
47+
Engine = 'engine',
48+
Default = 'default',
49+
}
50+
51+
export type ListOptions = typeof list extends Command<void, void, infer Options, infer Argument, GlobalOptions>
52+
? Options
53+
: never
54+
55+
export const list = new Command<GlobalOptions>()
56+
.description(`
57+
Lists plugins
58+
target - defaults to referenced:
59+
* all - Lists all plugins from the engine and project
60+
* referenced - Lists all plugins referenced by the project
61+
* engine - Lists all engine plugins
62+
* project - Lists only plugins in the project plugins
63+
* default - Lists all plugins that are enabled by default
64+
`)
65+
.type('ListTarget', new EnumType(ListTarget))
66+
.arguments('<target:ListTarget>')
67+
.option('-r, --recursive', 'List all nested plugins that are enabled when used with "referenced" or "default"', {
68+
default: false,
69+
})
70+
.action(async (options, target = ListTarget.Project) => {
71+
const { recursive } = options as ListOptions
72+
const config = Config.getInstance()
73+
const { engine: { path: enginePath }, project: { path: projectPath } } = config.mergeConfigCLIConfig({
74+
cliOptions: options,
75+
})
76+
const project = await createProject(enginePath, projectPath)
77+
const projectData = await readUProjectFile(project.projectFileVars.projectFullPath)
78+
79+
switch (target) {
80+
case ListTarget.All: {
81+
const projectPlugins = await findFilesByExtension(path.join(projectPath, 'Plugins'), 'uplugin', true)
82+
const enginePlugins = await findFilesByExtension(path.join(enginePath, 'Engine', 'Plugins'), 'uplugin', true)
83+
console.log('Project Plugins:\n')
84+
projectPlugins.forEach((plugin) => {
85+
console.log(path.basename(plugin, '.uplugin'))
86+
})
87+
console.log('Engine Plugins:\n')
88+
enginePlugins.forEach((plugin) => {
89+
console.log(path.basename(plugin, '.uplugin'))
90+
})
91+
break
92+
}
93+
case ListTarget.Referenced: {
94+
const allEnabledPlugins: Array<string> = []
95+
96+
if (projectData && projectData.Plugins) {
97+
for (const plugin of projectData.Plugins) {
98+
if (plugin.Enabled) {
99+
allEnabledPlugins.push(plugin.Name)
100+
}
101+
if (recursive) {
102+
const enabledPlugins = await getEnabledPlugins(plugin.Name, projectPath, enginePath, allEnabledPlugins)
103+
allEnabledPlugins.push(...enabledPlugins)
104+
}
105+
}
106+
}
107+
const uniquePlugins = [...new Set(allEnabledPlugins)]
108+
console.log('All Referenced Plugins:')
109+
console.log(uniquePlugins)
110+
break
111+
}
112+
case ListTarget.Project: {
113+
const projectPlugins = await findFilesByExtension(path.join(projectPath, 'Plugins'), 'uplugin', true)
114+
console.log('Project Plugins:\n')
115+
projectPlugins.forEach((plugin) => {
116+
console.log(path.basename(plugin, '.uplugin'))
117+
})
118+
break
119+
}
120+
case ListTarget.Engine: {
121+
const enginePlugins = await findFilesByExtension(path.join(enginePath, 'Engine', 'Plugins'), 'uplugin', true)
122+
console.log('Engine Plugins:\n')
123+
enginePlugins.forEach((plugin) => {
124+
console.log(path.basename(plugin, '.uplugin'))
125+
})
126+
break
127+
}
128+
case ListTarget.Default: {
129+
const projectPlugins = await findFilesByExtension(path.join(projectPath, 'Plugins'), 'uplugin', true)
130+
console.log('Project Plugins enabled by default:\n')
131+
for (const plugin of projectPlugins) {
132+
const uplugin = await readUPluginFile(plugin)
133+
if (uplugin && uplugin.EnabledByDefault) {
134+
console.log(path.basename(plugin, '.uplugin'))
135+
}
136+
}
137+
console.log('Engine Plugins enabled by default:\n')
138+
const enginePlugins = await findFilesByExtension(path.join(enginePath, 'Engine', 'Plugins'), 'uplugin', true)
139+
for (const plugin of enginePlugins) {
140+
const uplugin = await readUPluginFile(plugin)
141+
if (uplugin && uplugin.EnabledByDefault) {
142+
console.log(path.basename(plugin, '.uplugin'))
143+
}
144+
}
145+
break
146+
}
147+
}
148+
})

0 commit comments

Comments
 (0)