@jpp-toolkit/plugin-build-fivem 0.0.18 → 0.0.20
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/index.d.mts +0 -1
- package/dist/index.mjs +38 -29
- package/dist/index.mjs.map +1 -1
- package/oclif.manifest.json +1 -18
- package/package.json +5 -4
- package/src/fivem-build-command.ts +52 -37
package/dist/index.d.mts
CHANGED
|
@@ -6,7 +6,6 @@ declare class FivemBuildCommand extends Command {
|
|
|
6
6
|
static summary: string;
|
|
7
7
|
static flags: {
|
|
8
8
|
watch: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
9
|
-
env: _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
|
10
9
|
autoReload: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
11
10
|
server: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
|
|
12
11
|
password: _oclif_core_interfaces0.OptionFlag<string | undefined, _oclif_core_interfaces0.CustomOptions>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { Command } from "@jpp-toolkit/core";
|
|
3
|
-
import {
|
|
4
|
-
import { getErrMsg } from "@jpp-toolkit/utils";
|
|
3
|
+
import { createFivemScriptRspackConfig, createFivemUiRspackConfig } from "@jpp-toolkit/rspack-config";
|
|
4
|
+
import { debounce, getErrMsg } from "@jpp-toolkit/utils";
|
|
5
5
|
import { Flags } from "@oclif/core";
|
|
6
6
|
import { rspack } from "@rspack/core";
|
|
7
|
+
import { RspackDevServer } from "@rspack/dev-server";
|
|
7
8
|
import dgram from "node:dgram";
|
|
8
9
|
|
|
9
10
|
//#region src/fivem-rcon.ts
|
|
@@ -58,12 +59,6 @@ var FivemBuildCommand = class FivemBuildCommand extends Command {
|
|
|
58
59
|
description: "Watch files for changes and rebuild automatically.",
|
|
59
60
|
default: false
|
|
60
61
|
}),
|
|
61
|
-
env: Flags.string({
|
|
62
|
-
char: "e",
|
|
63
|
-
description: "Set the build environment (development or production).",
|
|
64
|
-
options: ["development", "production"],
|
|
65
|
-
required: false
|
|
66
|
-
}),
|
|
67
62
|
autoReload: Flags.boolean({
|
|
68
63
|
char: "r",
|
|
69
64
|
description: "Automatically reload FiveM resource after build.",
|
|
@@ -95,10 +90,6 @@ var FivemBuildCommand = class FivemBuildCommand extends Command {
|
|
|
95
90
|
description: "Build the FiveM resource in watch mode.",
|
|
96
91
|
command: "<%= config.bin %> <%= command.id %> --watch"
|
|
97
92
|
},
|
|
98
|
-
{
|
|
99
|
-
description: "Build the FiveM resource in production environment.",
|
|
100
|
-
command: "<%= config.bin %> <%= command.id %> --env=production"
|
|
101
|
-
},
|
|
102
93
|
{
|
|
103
94
|
description: "Build the FiveM resource and automatically reload it on the server after build.",
|
|
104
95
|
command: "<%= config.bin %> <%= command.id %> --auto-reload --password your_rcon_password"
|
|
@@ -113,42 +104,61 @@ var FivemBuildCommand = class FivemBuildCommand extends Command {
|
|
|
113
104
|
}
|
|
114
105
|
];
|
|
115
106
|
async run() {
|
|
116
|
-
const {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
107
|
+
const { resourceName, rconOptions, watch } = await this._parseOptions();
|
|
108
|
+
const scriptCompiler = rspack(createFivemScriptRspackConfig(void 0, { isProduction: !watch })({
|
|
109
|
+
RSPACK_BUILD: !watch,
|
|
110
|
+
RSPACK_WATCH: watch
|
|
120
111
|
}));
|
|
121
|
-
const
|
|
112
|
+
const uiConfig = createFivemUiRspackConfig({ resourceName }, { isProduction: !watch })({
|
|
113
|
+
RSPACK_BUILD: !watch,
|
|
114
|
+
RSPACK_SERVE: watch
|
|
115
|
+
});
|
|
116
|
+
const uiCompiler = rspack(uiConfig);
|
|
117
|
+
const reloadFivemResource = debounce(async () => {
|
|
122
118
|
if (!rconOptions) return;
|
|
119
|
+
this.logger.log("");
|
|
123
120
|
this.logger.info(`Reloading FiveM resource "${resourceName}"...`);
|
|
124
121
|
try {
|
|
125
122
|
await refreshAndEnsureFivemResource(resourceName, rconOptions);
|
|
126
123
|
this.logger.success(`FiveM resource reloaded successfully.\n`);
|
|
127
124
|
} catch (error) {
|
|
128
|
-
this.logger.error(`Failed to reload FiveM resource: ${
|
|
125
|
+
this.logger.error(`Failed to reload FiveM resource: ${error}\n`);
|
|
129
126
|
}
|
|
130
|
-
};
|
|
127
|
+
}, 500);
|
|
131
128
|
const compilerCallback = (err, stats) => {
|
|
132
129
|
if (err) {
|
|
133
|
-
this.logger.error(
|
|
134
|
-
if ("details" in err) this.logger.error(err.details);
|
|
135
|
-
if ("stack" in err) this.logger.error(err.stack);
|
|
130
|
+
this.logger.error(err.toString());
|
|
136
131
|
return;
|
|
137
132
|
}
|
|
138
|
-
if (stats)
|
|
133
|
+
if (!stats) return;
|
|
134
|
+
this.logger.log(stats.toString({
|
|
135
|
+
preset: "normal",
|
|
136
|
+
colors: true
|
|
137
|
+
}), "\n");
|
|
139
138
|
reloadFivemResource();
|
|
140
139
|
};
|
|
141
140
|
if (watch) {
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
const devServerOptions = uiConfig.devServer ?? {};
|
|
142
|
+
devServerOptions.hot = true;
|
|
143
|
+
await new RspackDevServer(devServerOptions, uiCompiler).start();
|
|
144
|
+
scriptCompiler.watch({}, compilerCallback);
|
|
144
145
|
} else {
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
uiCompiler.run((error, stats) => {
|
|
147
|
+
uiCompiler.close((closeErr) => {
|
|
148
|
+
if (closeErr) this.logger.error(closeErr.toString());
|
|
149
|
+
compilerCallback(error, stats);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
scriptCompiler.run((error, stats) => {
|
|
153
|
+
scriptCompiler.close((closeErr) => {
|
|
154
|
+
if (closeErr) this.logger.error(closeErr.toString());
|
|
155
|
+
compilerCallback(error, stats);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
147
158
|
}
|
|
148
159
|
}
|
|
149
160
|
async _parseOptions() {
|
|
150
161
|
const { flags } = await this.parse(FivemBuildCommand);
|
|
151
|
-
const env = flags.env ?? (flags.watch ? "development" : "production");
|
|
152
162
|
const resourceName = flags.resourceName ?? path.basename(process.cwd());
|
|
153
163
|
let rconOptions;
|
|
154
164
|
if (flags.autoReload) {
|
|
@@ -162,7 +172,6 @@ var FivemBuildCommand = class FivemBuildCommand extends Command {
|
|
|
162
172
|
};
|
|
163
173
|
}
|
|
164
174
|
return {
|
|
165
|
-
env,
|
|
166
175
|
resourceName,
|
|
167
176
|
rconOptions,
|
|
168
177
|
watch: flags.watch
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["timeoutId: NodeJS.Timeout","rconOptions: RconOptions | undefined"],"sources":["../src/fivem-rcon.ts","../src/fivem-build-command.ts","../src/index.ts"],"sourcesContent":["import dgram from 'node:dgram';\n\nimport { getErrMsg } from '@jpp-toolkit/utils';\n\nexport type RconOptions = {\n readonly host: string;\n readonly port: number;\n readonly password: string;\n readonly timeout?: number | undefined;\n};\n\nfunction buildCommand(command: string, password: string): Buffer {\n const buffer = Buffer.alloc(11 + password.length + command.length);\n buffer.writeUInt32LE(0xffffffff, 0);\n buffer.write('rcon ', 4);\n buffer.write(password, 9, password.length);\n buffer.write(' ', 9 + password.length, 1);\n buffer.write(command, 10 + password.length, command.length);\n buffer.write('\\n', 10 + password.length + command.length, 1);\n return buffer;\n}\n\nexport async function sendFivemRcon(command: string, options: RconOptions): Promise<string> {\n const socket = dgram.createSocket('udp4');\n\n return new Promise<string>((resolve, reject) => {\n let timeoutId: NodeJS.Timeout;\n\n const handleError = (err?: Error | string | null) => {\n if (!err) return;\n clearTimeout(timeoutId);\n const msg = getErrMsg(err);\n reject(new Error(`Failed to send command to ${options.host}:${options.port}: ${msg}`));\n };\n\n const handleMessage = (msg: Buffer) => {\n clearTimeout(timeoutId);\n const res = msg.toString('ascii').slice(4).trim();\n if (res.includes('Invalid password')) return void handleError('Invalid password');\n resolve(res);\n };\n\n timeoutId = setTimeout(\n () => handleError(`Timeout after ${options.timeout}ms`),\n options.timeout ?? 5000,\n );\n\n socket.once('error', handleError);\n socket.once('message', handleMessage);\n\n const cmd = buildCommand(command, options.password);\n socket.send(cmd, 0, cmd.length, options.port, options.host, handleError);\n }).finally(() => {\n socket.close();\n });\n}\n\nexport async function refreshAndEnsureFivemResource(\n resourceName: string,\n options: RconOptions,\n): Promise<void> {\n const res = await sendFivemRcon(`refresh; ensure ${resourceName}`, options);\n if (res.includes(\"Couldn't find resource\"))\n throw new Error(`Resource \"${resourceName}\" not found`);\n if (!res.includes('Started resource'))\n throw new Error(`Failed to start resource \"${resourceName}\"`);\n}\n","import path from 'node:path';\n\nimport { Command } from '@jpp-toolkit/core';\nimport { createFivemRspackConfig } from '@jpp-toolkit/rspack-config';\nimport { getErrMsg } from '@jpp-toolkit/utils';\nimport { Flags } from '@oclif/core';\nimport type { MultiStats } from '@rspack/core';\nimport { rspack } from '@rspack/core';\n\nimport { refreshAndEnsureFivemResource } from './fivem-rcon';\nimport type { RconOptions } from './fivem-rcon';\n\ntype Environment = 'development' | 'production';\n\ntype FivemBuildCommandOptions = {\n readonly env: Environment;\n readonly resourceName: string;\n readonly rconOptions?: RconOptions | undefined;\n readonly watch: boolean;\n};\n\nexport class FivemBuildCommand extends Command {\n static override summary = 'Build the FiveM resource using predefined config.';\n\n static override flags = {\n watch: Flags.boolean({\n char: 'w',\n description: 'Watch files for changes and rebuild automatically.',\n default: false,\n }),\n env: Flags.string({\n char: 'e',\n description: 'Set the build environment (development or production).',\n options: ['development', 'production'],\n required: false,\n }),\n autoReload: Flags.boolean({\n char: 'r',\n description: 'Automatically reload FiveM resource after build.',\n default: false,\n }),\n server: Flags.string({\n char: 's',\n description: 'Server \"ip:port\" to connect for reloading FiveM resource after build.',\n default: '127.0.0.1:30120',\n required: false,\n }),\n password: Flags.string({\n char: 'p',\n description: 'RCON password for the FiveM server to reload resource after build.',\n required: false,\n }),\n resourceName: Flags.string({\n char: 'n',\n description:\n 'Name of the FiveM resource to reload. If not provided, the name of the folder containing the resource will be used.',\n required: false,\n }),\n };\n\n static override examples = [\n {\n description: 'Build the FiveM resource.',\n command: '<%= config.bin %> <%= command.id %>',\n },\n {\n description: 'Build the FiveM resource in watch mode.',\n command: '<%= config.bin %> <%= command.id %> --watch',\n },\n {\n description: 'Build the FiveM resource in production environment.',\n command: '<%= config.bin %> <%= command.id %> --env=production',\n },\n {\n description:\n 'Build the FiveM resource and automatically reload it on the server after build.',\n command:\n '<%= config.bin %> <%= command.id %> --auto-reload --password your_rcon_password',\n },\n {\n description:\n 'Build the FiveM resource in watch mode and automatically reload it on the server after each build.',\n command:\n '<%= config.bin %> <%= command.id %> --watch --auto-reload --password your_rcon_password',\n },\n {\n description:\n 'Build the FiveM resource and connect to a specific server for auto-reload.',\n command:\n '<%= config.bin %> <%= command.id %> --auto-reload --server=127.0.0.1:30120 --password your_rcon_password',\n },\n ];\n\n public async run(): Promise<void> {\n const { env, resourceName, rconOptions, watch } = await this._parseOptions();\n\n const config = createFivemRspackConfig({ environment: env, resourceName });\n const compiler = rspack(config);\n\n const reloadFivemResource = async () => {\n if (!rconOptions) return;\n this.logger.info(`Reloading FiveM resource \"${resourceName}\"...`);\n try {\n await refreshAndEnsureFivemResource(resourceName, rconOptions);\n this.logger.success(`FiveM resource reloaded successfully.\\n`);\n } catch (error) {\n this.logger.error(`Failed to reload FiveM resource: ${getErrMsg(error)}\\n`);\n }\n };\n\n const compilerCallback = (err: Error | null, stats: MultiStats | undefined) => {\n if (err) {\n this.logger.error(getErrMsg(err));\n if ('details' in err) this.logger.error(err.details as string);\n if ('stack' in err) this.logger.error(err.stack);\n return;\n }\n\n if (stats) this.logger.log(stats.toString(true), '\\n');\n\n void reloadFivemResource();\n };\n\n if (watch) {\n this.logger.info(`Building FiveM resource in watch mode...\\n`);\n compiler.watch({}, compilerCallback);\n } else {\n this.logger.info(`Building FiveM resource...\\n`);\n compiler.run(compilerCallback);\n }\n }\n\n private async _parseOptions(): Promise<FivemBuildCommandOptions> {\n const { flags } = await this.parse(FivemBuildCommand);\n\n const env = (flags.env ?? (flags.watch ? 'development' : 'production')) as Environment;\n const resourceName = flags.resourceName ?? path.basename(process.cwd());\n\n let rconOptions: RconOptions | undefined;\n\n if (flags.autoReload) {\n if (!flags.password) {\n throw new Error(\n 'RCON password is required for auto-reload. Please provide it using the --password flag.',\n );\n }\n\n const match = /^(?<host>[^:]+):(?<port>\\d+)$/u.exec(flags.server);\n const { host, port } = match?.groups ?? {};\n\n if (!host || !port) {\n throw new Error(\n `Invalid server address format: ${flags.server}. Expected format is \"ip:port\".`,\n );\n }\n\n rconOptions = {\n host,\n port: parseInt(port),\n password: flags.password,\n };\n }\n\n return { env, resourceName, rconOptions, watch: flags.watch };\n }\n}\n","import { FivemBuildCommand } from './fivem-build-command';\n\nexport const commands = {\n 'build:fivem': FivemBuildCommand,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["timeoutId: NodeJS.Timeout","rconOptions: RconOptions | undefined"],"sources":["../src/fivem-rcon.ts","../src/fivem-build-command.ts","../src/index.ts"],"sourcesContent":["import dgram from 'node:dgram';\n\nimport { getErrMsg } from '@jpp-toolkit/utils';\n\nexport type RconOptions = {\n readonly host: string;\n readonly port: number;\n readonly password: string;\n readonly timeout?: number | undefined;\n};\n\nfunction buildCommand(command: string, password: string): Buffer {\n const buffer = Buffer.alloc(11 + password.length + command.length);\n buffer.writeUInt32LE(0xffffffff, 0);\n buffer.write('rcon ', 4);\n buffer.write(password, 9, password.length);\n buffer.write(' ', 9 + password.length, 1);\n buffer.write(command, 10 + password.length, command.length);\n buffer.write('\\n', 10 + password.length + command.length, 1);\n return buffer;\n}\n\nexport async function sendFivemRcon(command: string, options: RconOptions): Promise<string> {\n const socket = dgram.createSocket('udp4');\n\n return new Promise<string>((resolve, reject) => {\n let timeoutId: NodeJS.Timeout;\n\n const handleError = (err?: Error | string | null) => {\n if (!err) return;\n clearTimeout(timeoutId);\n const msg = getErrMsg(err);\n reject(new Error(`Failed to send command to ${options.host}:${options.port}: ${msg}`));\n };\n\n const handleMessage = (msg: Buffer) => {\n clearTimeout(timeoutId);\n const res = msg.toString('ascii').slice(4).trim();\n if (res.includes('Invalid password')) return void handleError('Invalid password');\n resolve(res);\n };\n\n timeoutId = setTimeout(\n () => handleError(`Timeout after ${options.timeout}ms`),\n options.timeout ?? 5000,\n );\n\n socket.once('error', handleError);\n socket.once('message', handleMessage);\n\n const cmd = buildCommand(command, options.password);\n socket.send(cmd, 0, cmd.length, options.port, options.host, handleError);\n }).finally(() => {\n socket.close();\n });\n}\n\nexport async function refreshAndEnsureFivemResource(\n resourceName: string,\n options: RconOptions,\n): Promise<void> {\n const res = await sendFivemRcon(`refresh; ensure ${resourceName}`, options);\n if (res.includes(\"Couldn't find resource\"))\n throw new Error(`Resource \"${resourceName}\" not found`);\n if (!res.includes('Started resource'))\n throw new Error(`Failed to start resource \"${resourceName}\"`);\n}\n","import path from 'node:path';\n\nimport { Command } from '@jpp-toolkit/core';\nimport {\n createFivemScriptRspackConfig,\n createFivemUiRspackConfig,\n} from '@jpp-toolkit/rspack-config';\nimport { debounce } from '@jpp-toolkit/utils';\nimport { Flags } from '@oclif/core';\nimport type { MultiStats, Stats } from '@rspack/core';\nimport { rspack } from '@rspack/core';\nimport { RspackDevServer } from '@rspack/dev-server';\n\nimport { refreshAndEnsureFivemResource } from './fivem-rcon';\nimport type { RconOptions } from './fivem-rcon';\n\ntype FivemBuildCommandOptions = {\n readonly resourceName: string;\n readonly rconOptions?: RconOptions | undefined;\n readonly watch: boolean;\n};\n\nexport class FivemBuildCommand extends Command {\n static override summary = 'Build the FiveM resource using predefined config.';\n\n static override flags = {\n watch: Flags.boolean({\n char: 'w',\n description: 'Watch files for changes and rebuild automatically.',\n default: false,\n }),\n autoReload: Flags.boolean({\n char: 'r',\n description: 'Automatically reload FiveM resource after build.',\n default: false,\n }),\n server: Flags.string({\n char: 's',\n description: 'Server \"ip:port\" to connect for reloading FiveM resource after build.',\n default: '127.0.0.1:30120',\n required: false,\n }),\n password: Flags.string({\n char: 'p',\n description: 'RCON password for the FiveM server to reload resource after build.',\n required: false,\n }),\n resourceName: Flags.string({\n char: 'n',\n description:\n 'Name of the FiveM resource to reload. If not provided, the name of the folder containing the resource will be used.',\n required: false,\n }),\n };\n\n static override examples = [\n {\n description: 'Build the FiveM resource.',\n command: '<%= config.bin %> <%= command.id %>',\n },\n {\n description: 'Build the FiveM resource in watch mode.',\n command: '<%= config.bin %> <%= command.id %> --watch',\n },\n {\n description:\n 'Build the FiveM resource and automatically reload it on the server after build.',\n command:\n '<%= config.bin %> <%= command.id %> --auto-reload --password your_rcon_password',\n },\n {\n description:\n 'Build the FiveM resource in watch mode and automatically reload it on the server after each build.',\n command:\n '<%= config.bin %> <%= command.id %> --watch --auto-reload --password your_rcon_password',\n },\n {\n description:\n 'Build the FiveM resource and connect to a specific server for auto-reload.',\n command:\n '<%= config.bin %> <%= command.id %> --auto-reload --server=127.0.0.1:30120 --password your_rcon_password',\n },\n ];\n\n public async run(): Promise<void> {\n const { resourceName, rconOptions, watch } = await this._parseOptions();\n\n const scriptConfig = createFivemScriptRspackConfig(undefined, {\n isProduction: !watch,\n })({\n RSPACK_BUILD: !watch,\n RSPACK_WATCH: watch,\n });\n const scriptCompiler = rspack(scriptConfig);\n\n const uiConfig = createFivemUiRspackConfig(\n { resourceName },\n { isProduction: !watch },\n )({\n RSPACK_BUILD: !watch,\n RSPACK_SERVE: watch,\n });\n const uiCompiler = rspack(uiConfig);\n\n const reloadFivemResource = debounce(async () => {\n if (!rconOptions) return;\n this.logger.log('');\n this.logger.info(`Reloading FiveM resource \"${resourceName}\"...`);\n try {\n await refreshAndEnsureFivemResource(resourceName, rconOptions);\n this.logger.success(`FiveM resource reloaded successfully.\\n`);\n } catch (error) {\n this.logger.error(`Failed to reload FiveM resource: ${error}\\n`);\n }\n }, 500);\n\n const compilerCallback = (err: Error | null, stats: Stats | MultiStats | undefined) => {\n if (err) {\n this.logger.error(err.toString());\n return;\n }\n if (!stats) return;\n this.logger.log(stats.toString({ preset: 'normal', colors: true }), '\\n');\n void reloadFivemResource();\n };\n\n if (watch) {\n const devServerOptions = uiConfig.devServer ?? {};\n devServerOptions.hot = true;\n const devServer = new RspackDevServer(devServerOptions, uiCompiler);\n await devServer.start();\n scriptCompiler.watch({}, compilerCallback);\n } else {\n uiCompiler.run((error: Error | null, stats: Stats | MultiStats | undefined) => {\n uiCompiler.close((closeErr) => {\n if (closeErr) this.logger.error(closeErr.toString());\n compilerCallback(error, stats);\n });\n });\n scriptCompiler.run((error: Error | null, stats: Stats | MultiStats | undefined) => {\n scriptCompiler.close((closeErr) => {\n if (closeErr) this.logger.error(closeErr.toString());\n compilerCallback(error, stats);\n });\n });\n }\n }\n\n private async _parseOptions(): Promise<FivemBuildCommandOptions> {\n const { flags } = await this.parse(FivemBuildCommand);\n\n const resourceName = flags.resourceName ?? path.basename(process.cwd());\n\n let rconOptions: RconOptions | undefined;\n\n if (flags.autoReload) {\n if (!flags.password) {\n throw new Error(\n 'RCON password is required for auto-reload. Please provide it using the --password flag.',\n );\n }\n\n const match = /^(?<host>[^:]+):(?<port>\\d+)$/u.exec(flags.server);\n const { host, port } = match?.groups ?? {};\n\n if (!host || !port) {\n throw new Error(\n `Invalid server address format: ${flags.server}. Expected format is \"ip:port\".`,\n );\n }\n\n rconOptions = {\n host,\n port: parseInt(port),\n password: flags.password,\n };\n }\n\n return { resourceName, rconOptions, watch: flags.watch };\n }\n}\n","import { FivemBuildCommand } from './fivem-build-command';\n\nexport const commands = {\n 'build:fivem': FivemBuildCommand,\n};\n"],"mappings":"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"}
|
package/oclif.manifest.json
CHANGED
|
@@ -12,10 +12,6 @@
|
|
|
12
12
|
"description": "Build the FiveM resource in watch mode.",
|
|
13
13
|
"command": "<%= config.bin %> <%= command.id %> --watch"
|
|
14
14
|
},
|
|
15
|
-
{
|
|
16
|
-
"description": "Build the FiveM resource in production environment.",
|
|
17
|
-
"command": "<%= config.bin %> <%= command.id %> --env=production"
|
|
18
|
-
},
|
|
19
15
|
{
|
|
20
16
|
"description": "Build the FiveM resource and automatically reload it on the server after build.",
|
|
21
17
|
"command": "<%= config.bin %> <%= command.id %> --auto-reload --password your_rcon_password"
|
|
@@ -37,19 +33,6 @@
|
|
|
37
33
|
"allowNo": false,
|
|
38
34
|
"type": "boolean"
|
|
39
35
|
},
|
|
40
|
-
"env": {
|
|
41
|
-
"char": "e",
|
|
42
|
-
"description": "Set the build environment (development or production).",
|
|
43
|
-
"name": "env",
|
|
44
|
-
"required": false,
|
|
45
|
-
"hasDynamicHelp": false,
|
|
46
|
-
"multiple": false,
|
|
47
|
-
"options": [
|
|
48
|
-
"development",
|
|
49
|
-
"production"
|
|
50
|
-
],
|
|
51
|
-
"type": "option"
|
|
52
|
-
},
|
|
53
36
|
"autoReload": {
|
|
54
37
|
"char": "r",
|
|
55
38
|
"description": "Automatically reload FiveM resource after build.",
|
|
@@ -96,5 +79,5 @@
|
|
|
96
79
|
"summary": "Build the FiveM resource using predefined config."
|
|
97
80
|
}
|
|
98
81
|
},
|
|
99
|
-
"version": "0.0.
|
|
82
|
+
"version": "0.0.20"
|
|
100
83
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jpp-toolkit/plugin-build-fivem",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "Plugin that add the fivem build command to the jpp cli.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jpp",
|
|
@@ -36,9 +36,10 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@oclif/core": "4.8.0",
|
|
38
38
|
"@rspack/core": "1.6.8",
|
|
39
|
-
"@
|
|
40
|
-
"@jpp-toolkit/
|
|
41
|
-
"@jpp-toolkit/
|
|
39
|
+
"@rspack/dev-server": "1.1.4",
|
|
40
|
+
"@jpp-toolkit/core": "0.0.19",
|
|
41
|
+
"@jpp-toolkit/rspack-config": "0.0.9",
|
|
42
|
+
"@jpp-toolkit/utils": "0.0.17"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"oclif": "4.22.57"
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
|
|
3
3
|
import { Command } from '@jpp-toolkit/core';
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
createFivemScriptRspackConfig,
|
|
6
|
+
createFivemUiRspackConfig,
|
|
7
|
+
} from '@jpp-toolkit/rspack-config';
|
|
8
|
+
import { debounce } from '@jpp-toolkit/utils';
|
|
6
9
|
import { Flags } from '@oclif/core';
|
|
7
|
-
import type { MultiStats } from '@rspack/core';
|
|
10
|
+
import type { MultiStats, Stats } from '@rspack/core';
|
|
8
11
|
import { rspack } from '@rspack/core';
|
|
12
|
+
import { RspackDevServer } from '@rspack/dev-server';
|
|
9
13
|
|
|
10
14
|
import { refreshAndEnsureFivemResource } from './fivem-rcon';
|
|
11
15
|
import type { RconOptions } from './fivem-rcon';
|
|
12
16
|
|
|
13
|
-
type Environment = 'development' | 'production';
|
|
14
|
-
|
|
15
17
|
type FivemBuildCommandOptions = {
|
|
16
|
-
readonly env: Environment;
|
|
17
18
|
readonly resourceName: string;
|
|
18
19
|
readonly rconOptions?: RconOptions | undefined;
|
|
19
20
|
readonly watch: boolean;
|
|
@@ -28,12 +29,6 @@ export class FivemBuildCommand extends Command {
|
|
|
28
29
|
description: 'Watch files for changes and rebuild automatically.',
|
|
29
30
|
default: false,
|
|
30
31
|
}),
|
|
31
|
-
env: Flags.string({
|
|
32
|
-
char: 'e',
|
|
33
|
-
description: 'Set the build environment (development or production).',
|
|
34
|
-
options: ['development', 'production'],
|
|
35
|
-
required: false,
|
|
36
|
-
}),
|
|
37
32
|
autoReload: Flags.boolean({
|
|
38
33
|
char: 'r',
|
|
39
34
|
description: 'Automatically reload FiveM resource after build.',
|
|
@@ -67,10 +62,6 @@ export class FivemBuildCommand extends Command {
|
|
|
67
62
|
description: 'Build the FiveM resource in watch mode.',
|
|
68
63
|
command: '<%= config.bin %> <%= command.id %> --watch',
|
|
69
64
|
},
|
|
70
|
-
{
|
|
71
|
-
description: 'Build the FiveM resource in production environment.',
|
|
72
|
-
command: '<%= config.bin %> <%= command.id %> --env=production',
|
|
73
|
-
},
|
|
74
65
|
{
|
|
75
66
|
description:
|
|
76
67
|
'Build the FiveM resource and automatically reload it on the server after build.',
|
|
@@ -92,48 +83,72 @@ export class FivemBuildCommand extends Command {
|
|
|
92
83
|
];
|
|
93
84
|
|
|
94
85
|
public async run(): Promise<void> {
|
|
95
|
-
const {
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
86
|
+
const { resourceName, rconOptions, watch } = await this._parseOptions();
|
|
87
|
+
|
|
88
|
+
const scriptConfig = createFivemScriptRspackConfig(undefined, {
|
|
89
|
+
isProduction: !watch,
|
|
90
|
+
})({
|
|
91
|
+
RSPACK_BUILD: !watch,
|
|
92
|
+
RSPACK_WATCH: watch,
|
|
93
|
+
});
|
|
94
|
+
const scriptCompiler = rspack(scriptConfig);
|
|
95
|
+
|
|
96
|
+
const uiConfig = createFivemUiRspackConfig(
|
|
97
|
+
{ resourceName },
|
|
98
|
+
{ isProduction: !watch },
|
|
99
|
+
)({
|
|
100
|
+
RSPACK_BUILD: !watch,
|
|
101
|
+
RSPACK_SERVE: watch,
|
|
102
|
+
});
|
|
103
|
+
const uiCompiler = rspack(uiConfig);
|
|
104
|
+
|
|
105
|
+
const reloadFivemResource = debounce(async () => {
|
|
101
106
|
if (!rconOptions) return;
|
|
107
|
+
this.logger.log('');
|
|
102
108
|
this.logger.info(`Reloading FiveM resource "${resourceName}"...`);
|
|
103
109
|
try {
|
|
104
110
|
await refreshAndEnsureFivemResource(resourceName, rconOptions);
|
|
105
111
|
this.logger.success(`FiveM resource reloaded successfully.\n`);
|
|
106
112
|
} catch (error) {
|
|
107
|
-
this.logger.error(`Failed to reload FiveM resource: ${
|
|
113
|
+
this.logger.error(`Failed to reload FiveM resource: ${error}\n`);
|
|
108
114
|
}
|
|
109
|
-
};
|
|
115
|
+
}, 500);
|
|
110
116
|
|
|
111
|
-
const compilerCallback = (err: Error | null, stats: MultiStats | undefined) => {
|
|
117
|
+
const compilerCallback = (err: Error | null, stats: Stats | MultiStats | undefined) => {
|
|
112
118
|
if (err) {
|
|
113
|
-
this.logger.error(
|
|
114
|
-
if ('details' in err) this.logger.error(err.details as string);
|
|
115
|
-
if ('stack' in err) this.logger.error(err.stack);
|
|
119
|
+
this.logger.error(err.toString());
|
|
116
120
|
return;
|
|
117
121
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
if (!stats) return;
|
|
123
|
+
this.logger.log(stats.toString({ preset: 'normal', colors: true }), '\n');
|
|
121
124
|
void reloadFivemResource();
|
|
122
125
|
};
|
|
123
126
|
|
|
124
127
|
if (watch) {
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
const devServerOptions = uiConfig.devServer ?? {};
|
|
129
|
+
devServerOptions.hot = true;
|
|
130
|
+
const devServer = new RspackDevServer(devServerOptions, uiCompiler);
|
|
131
|
+
await devServer.start();
|
|
132
|
+
scriptCompiler.watch({}, compilerCallback);
|
|
127
133
|
} else {
|
|
128
|
-
|
|
129
|
-
|
|
134
|
+
uiCompiler.run((error: Error | null, stats: Stats | MultiStats | undefined) => {
|
|
135
|
+
uiCompiler.close((closeErr) => {
|
|
136
|
+
if (closeErr) this.logger.error(closeErr.toString());
|
|
137
|
+
compilerCallback(error, stats);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
scriptCompiler.run((error: Error | null, stats: Stats | MultiStats | undefined) => {
|
|
141
|
+
scriptCompiler.close((closeErr) => {
|
|
142
|
+
if (closeErr) this.logger.error(closeErr.toString());
|
|
143
|
+
compilerCallback(error, stats);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
130
146
|
}
|
|
131
147
|
}
|
|
132
148
|
|
|
133
149
|
private async _parseOptions(): Promise<FivemBuildCommandOptions> {
|
|
134
150
|
const { flags } = await this.parse(FivemBuildCommand);
|
|
135
151
|
|
|
136
|
-
const env = (flags.env ?? (flags.watch ? 'development' : 'production')) as Environment;
|
|
137
152
|
const resourceName = flags.resourceName ?? path.basename(process.cwd());
|
|
138
153
|
|
|
139
154
|
let rconOptions: RconOptions | undefined;
|
|
@@ -161,6 +176,6 @@ export class FivemBuildCommand extends Command {
|
|
|
161
176
|
};
|
|
162
177
|
}
|
|
163
178
|
|
|
164
|
-
return {
|
|
179
|
+
return { resourceName, rconOptions, watch: flags.watch };
|
|
165
180
|
}
|
|
166
181
|
}
|