@open-core/framework 1.0.1-beta.1 → 1.0.4-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/README.md +12 -2
- package/dist/client/client-bootstrap.js +11 -14
- package/dist/client/client-core.d.ts +0 -17
- package/dist/client/client-core.js +0 -45
- package/dist/client/controllers/spawner.controller.d.ts +12 -0
- package/dist/client/controllers/spawner.controller.js +51 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/client/interfaces/appearance.interface.d.ts +19 -0
- package/dist/client/interfaces/appearance.interface.js +2 -0
- package/dist/client/services/appearance.service.d.ts +6 -0
- package/dist/client/services/appearance.service.js +89 -0
- package/dist/client/services/{world/blip.service.d.ts → blip.service.d.ts} +1 -1
- package/dist/client/services/index.d.ts +9 -4
- package/dist/client/services/index.js +9 -8
- package/dist/client/services/{world/marker.service.d.ts → marker.service.d.ts} +1 -1
- package/dist/client/services/{world/ped.service.d.ts → ped.service.d.ts} +1 -1
- package/dist/client/services/spawn.service.d.ts +73 -0
- package/dist/client/services/spawn.service.js +261 -0
- package/dist/client/services/{ui/textui.service.d.ts → textui.service.d.ts} +1 -1
- package/dist/client/services/{world/vehicle.service.d.ts → vehicle.service.d.ts} +1 -1
- package/dist/client/system/processors/export.processor.js +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +1 -6
- package/dist/server/bootstrap.js +2 -2
- package/dist/server/controllers/command.controller.d.ts +1 -1
- package/dist/server/controllers/command.controller.js +6 -6
- package/dist/server/controllers/session.controller.d.ts +9 -0
- package/dist/server/controllers/session.controller.js +70 -0
- package/dist/server/database/adapters/oxmysql.adapter.js +1 -1
- package/dist/server/decorators/command.d.ts +34 -4
- package/dist/server/decorators/command.js +11 -6
- package/dist/server/decorators/controller.d.ts +22 -0
- package/dist/server/decorators/controller.js +22 -0
- package/dist/server/decorators/export.d.ts +38 -0
- package/dist/server/decorators/export.js +38 -0
- package/dist/server/decorators/guard.d.ts +51 -0
- package/dist/server/decorators/guard.js +43 -0
- package/dist/server/decorators/index.d.ts +4 -4
- package/dist/server/decorators/index.js +7 -4
- package/dist/server/decorators/onFiveMEvent.d.ts +6 -0
- package/dist/server/decorators/{coreEvent.js → onFiveMEvent.js} +8 -3
- package/dist/server/decorators/onFrameworkEvent.d.ts +22 -0
- package/dist/server/decorators/onFrameworkEvent.js +29 -0
- package/dist/server/decorators/onNet.d.ts +58 -0
- package/dist/server/decorators/onNet.js +57 -0
- package/dist/server/decorators/onTick.d.ts +31 -0
- package/dist/server/decorators/onTick.js +31 -0
- package/dist/server/decorators/public.d.ts +19 -8
- package/dist/server/decorators/public.js +19 -8
- package/dist/server/decorators/requiresState.d.ts +18 -17
- package/dist/server/decorators/requiresState.js +18 -17
- package/dist/server/decorators/throttle.d.ts +39 -0
- package/dist/server/decorators/throttle.js +27 -0
- package/dist/server/decorators/utils.d.ts +50 -0
- package/dist/server/decorators/utils.js +50 -0
- package/dist/server/entities/player.js +1 -1
- package/dist/server/error-handler.js +2 -2
- package/dist/server/helpers/resolve-method.d.ts +5 -0
- package/dist/server/helpers/resolve-method.js +18 -0
- package/dist/server/index.js +2 -0
- package/dist/server/loaders/playerSession.loader.js +13 -4
- package/dist/server/services/command.service.d.ts +1 -1
- package/dist/server/services/command.service.js +9 -6
- package/dist/server/system/metadata-server.keys.d.ts +1 -0
- package/dist/server/system/metadata-server.keys.js +1 -0
- package/dist/server/system/processors/command.processor.d.ts +2 -2
- package/dist/server/system/processors/command.processor.js +1 -2
- package/dist/server/system/processors/coreEvent.processor.d.ts +1 -1
- package/dist/server/system/processors/coreEvent.processor.js +6 -3
- package/dist/server/system/processors/export.processor.d.ts +1 -1
- package/dist/server/system/processors/export.processor.js +7 -3
- package/dist/server/system/processors/fivemEvent.processor.d.ts +7 -0
- package/dist/server/system/processors/fivemEvent.processor.js +40 -0
- package/dist/server/system/processors/netEvent.processor.d.ts +1 -1
- package/dist/server/system/processors/netEvent.processor.js +12 -9
- package/dist/server/system/processors.register.js +2 -0
- package/dist/server/system/schema-generator.d.ts +2 -0
- package/dist/server/system/schema-generator.js +34 -0
- package/dist/server/templates/admin/admin.controller-template.d.ts +7 -5
- package/dist/server/templates/auth/auth-provider.contract.d.ts +2 -2
- package/dist/server/types/core-events.d.ts +5 -0
- package/package.json +29 -1
- package/dist/client/loaders/exports.loader.d.ts +0 -1
- package/dist/client/loaders/exports.loader.js +0 -13
- package/dist/client/services/core/index.d.ts +0 -1
- package/dist/client/services/core/index.js +0 -17
- package/dist/client/services/core/spawn.service.d.ts +0 -20
- package/dist/client/services/core/spawn.service.js +0 -143
- package/dist/client/services/streaming/index.d.ts +0 -1
- package/dist/client/services/streaming/index.js +0 -17
- package/dist/client/services/ui/index.d.ts +0 -3
- package/dist/client/services/ui/index.js +0 -19
- package/dist/client/services/world/index.d.ts +0 -4
- package/dist/client/services/world/index.js +0 -20
- package/dist/server/decorators/coreEvent.d.ts +0 -2
- package/dist/server/decorators/netEvent.d.ts +0 -36
- package/dist/server/decorators/netEvent.js +0 -40
- /package/dist/client/services/{world/blip.service.js → blip.service.js} +0 -0
- /package/dist/client/services/{world/marker.service.js → marker.service.js} +0 -0
- /package/dist/client/services/{ui/notification.service.d.ts → notification.service.d.ts} +0 -0
- /package/dist/client/services/{ui/notification.service.js → notification.service.js} +0 -0
- /package/dist/client/services/{world/ped.service.js → ped.service.js} +0 -0
- /package/dist/client/services/{ui/progress.service.d.ts → progress.service.d.ts} +0 -0
- /package/dist/client/services/{ui/progress.service.js → progress.service.js} +0 -0
- /package/dist/client/services/{streaming/streaming.service.d.ts → streaming.service.d.ts} +0 -0
- /package/dist/client/services/{streaming/streaming.service.js → streaming.service.js} +0 -0
- /package/dist/client/services/{ui/textui.service.js → textui.service.js} +0 -0
- /package/dist/client/services/{world/vehicle.service.js → vehicle.service.js} +0 -0
|
@@ -1,9 +1,48 @@
|
|
|
1
1
|
import type { SecurityAction } from '../types/security.types';
|
|
2
2
|
interface ThrottleOptions {
|
|
3
|
+
/**
|
|
4
|
+
* limit of calls per windowMs
|
|
5
|
+
*/
|
|
3
6
|
limit: number;
|
|
7
|
+
/**
|
|
8
|
+
* time window for numeric overload
|
|
9
|
+
*/
|
|
4
10
|
windowMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* action to perform on exceed limit
|
|
13
|
+
*/
|
|
5
14
|
onExceed?: SecurityAction;
|
|
15
|
+
/**
|
|
16
|
+
* custom message to display on exceed limit (ERROR MESSAGE)
|
|
17
|
+
*/
|
|
6
18
|
message?: string;
|
|
7
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Rate-limits how frequently a method can be called by a specific player.
|
|
22
|
+
*
|
|
23
|
+
* Uses `RateLimiterService` and a unique key composed of:
|
|
24
|
+
* `playerID:ClassName:MethodName`.
|
|
25
|
+
*
|
|
26
|
+
* ## Overload
|
|
27
|
+
* - `@Throttle(5, 1000)` → limit = 5 calls per 1000 ms
|
|
28
|
+
* - `@Throttle({ limit, windowMs, onExceed, message })`
|
|
29
|
+
*
|
|
30
|
+
* ## Behavior
|
|
31
|
+
* If the rate limit is exceeded:
|
|
32
|
+
* - A `SecurityError` is thrown.
|
|
33
|
+
* - Optional custom behavior (`onExceed`) may be executed.
|
|
34
|
+
*
|
|
35
|
+
* ## Example
|
|
36
|
+
* ```ts
|
|
37
|
+
* @Throttle(5, 2000)
|
|
38
|
+
* async search(player: Server.Player, query: string) { ... }
|
|
39
|
+
*
|
|
40
|
+
* @Throttle({ limit: 1, windowMs: 5000, message: "Too fast!" })
|
|
41
|
+
* async placeOrder(player: Server.Player) { ... }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @param optionsOrLimit - Number (simple mode) or full config object.
|
|
45
|
+
* @param windowMs - Time window for numeric overload.
|
|
46
|
+
*/
|
|
8
47
|
export declare function Throttle(optionsOrLimit: number | ThrottleOptions, windowMs?: number): (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => PropertyDescriptor | undefined;
|
|
9
48
|
export {};
|
|
@@ -4,6 +4,33 @@ exports.Throttle = Throttle;
|
|
|
4
4
|
const tsyringe_1 = require("tsyringe");
|
|
5
5
|
const rate_limiter_service_1 = require("../services/rate-limiter.service");
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
|
+
/**
|
|
8
|
+
* Rate-limits how frequently a method can be called by a specific player.
|
|
9
|
+
*
|
|
10
|
+
* Uses `RateLimiterService` and a unique key composed of:
|
|
11
|
+
* `playerID:ClassName:MethodName`.
|
|
12
|
+
*
|
|
13
|
+
* ## Overload
|
|
14
|
+
* - `@Throttle(5, 1000)` → limit = 5 calls per 1000 ms
|
|
15
|
+
* - `@Throttle({ limit, windowMs, onExceed, message })`
|
|
16
|
+
*
|
|
17
|
+
* ## Behavior
|
|
18
|
+
* If the rate limit is exceeded:
|
|
19
|
+
* - A `SecurityError` is thrown.
|
|
20
|
+
* - Optional custom behavior (`onExceed`) may be executed.
|
|
21
|
+
*
|
|
22
|
+
* ## Example
|
|
23
|
+
* ```ts
|
|
24
|
+
* @Throttle(5, 2000)
|
|
25
|
+
* async search(player: Server.Player, query: string) { ... }
|
|
26
|
+
*
|
|
27
|
+
* @Throttle({ limit: 1, windowMs: 5000, message: "Too fast!" })
|
|
28
|
+
* async placeOrder(player: Server.Player) { ... }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param optionsOrLimit - Number (simple mode) or full config object.
|
|
32
|
+
* @param windowMs - Time window for numeric overload.
|
|
33
|
+
*/
|
|
7
34
|
function Throttle(optionsOrLimit, windowMs) {
|
|
8
35
|
return function (target, propertyKey, descriptor) {
|
|
9
36
|
if (!descriptor) {
|
|
@@ -1,7 +1,57 @@
|
|
|
1
1
|
import type { BindingScope } from './bind';
|
|
2
|
+
/**
|
|
3
|
+
* Marks a class as a framework-managed Service.
|
|
4
|
+
*
|
|
5
|
+
* The decorator binds the class into the dependency injection
|
|
6
|
+
* container using the provided scope (default: `singleton`).
|
|
7
|
+
*
|
|
8
|
+
* Services represent reusable, stateless or stateful logic such as:
|
|
9
|
+
* - Business rules
|
|
10
|
+
* - Utility layers
|
|
11
|
+
* - Gameplay systems
|
|
12
|
+
* - Internal modules
|
|
13
|
+
*
|
|
14
|
+
* This decorator is a convenience wrapper over `@Bind()`, allowing
|
|
15
|
+
* future extension of service-specific behavior without changing
|
|
16
|
+
* end-user code.
|
|
17
|
+
*
|
|
18
|
+
* ## Example
|
|
19
|
+
* ```ts
|
|
20
|
+
* @Service()
|
|
21
|
+
* export class InventoryService {
|
|
22
|
+
* addItem() { ... }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
27
|
+
*/
|
|
2
28
|
export declare function Service(options?: {
|
|
3
29
|
scope?: BindingScope;
|
|
4
30
|
}): (target: any) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Marks a class as a Repository within the framework.
|
|
33
|
+
*
|
|
34
|
+
* A Repository abstracts persistence operations (e.g., database,
|
|
35
|
+
* API, in-memory, or hybrid storage). It is registered in the
|
|
36
|
+
* dependency injection container using the provided scope
|
|
37
|
+
* (default: `singleton`).
|
|
38
|
+
*
|
|
39
|
+
* `@Repo()` is intentionally separate from `@Service()` to clearly
|
|
40
|
+
* distinguish persistence-oriented classes from business logic.
|
|
41
|
+
* In the future, repository-specific behavior (caching layers,
|
|
42
|
+
* transactional wrappers, profiling, etc.) can be attached here
|
|
43
|
+
* without modifying user code.
|
|
44
|
+
*
|
|
45
|
+
* ## Example
|
|
46
|
+
* ```ts
|
|
47
|
+
* @Repo()
|
|
48
|
+
* export class AccountRepository {
|
|
49
|
+
* async findById(id: string) { ... }
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
54
|
+
*/
|
|
5
55
|
export declare function Repo(options?: {
|
|
6
56
|
scope?: BindingScope;
|
|
7
57
|
}): (target: any) => void;
|
|
@@ -3,10 +3,60 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Service = Service;
|
|
4
4
|
exports.Repo = Repo;
|
|
5
5
|
const bind_1 = require("./bind");
|
|
6
|
+
/**
|
|
7
|
+
* Marks a class as a framework-managed Service.
|
|
8
|
+
*
|
|
9
|
+
* The decorator binds the class into the dependency injection
|
|
10
|
+
* container using the provided scope (default: `singleton`).
|
|
11
|
+
*
|
|
12
|
+
* Services represent reusable, stateless or stateful logic such as:
|
|
13
|
+
* - Business rules
|
|
14
|
+
* - Utility layers
|
|
15
|
+
* - Gameplay systems
|
|
16
|
+
* - Internal modules
|
|
17
|
+
*
|
|
18
|
+
* This decorator is a convenience wrapper over `@Bind()`, allowing
|
|
19
|
+
* future extension of service-specific behavior without changing
|
|
20
|
+
* end-user code.
|
|
21
|
+
*
|
|
22
|
+
* ## Example
|
|
23
|
+
* ```ts
|
|
24
|
+
* @Service()
|
|
25
|
+
* export class InventoryService {
|
|
26
|
+
* addItem() { ... }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
31
|
+
*/
|
|
6
32
|
function Service(options) {
|
|
7
33
|
var _a;
|
|
8
34
|
return (0, bind_1.Bind)((_a = options === null || options === void 0 ? void 0 : options.scope) !== null && _a !== void 0 ? _a : 'singleton');
|
|
9
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Marks a class as a Repository within the framework.
|
|
38
|
+
*
|
|
39
|
+
* A Repository abstracts persistence operations (e.g., database,
|
|
40
|
+
* API, in-memory, or hybrid storage). It is registered in the
|
|
41
|
+
* dependency injection container using the provided scope
|
|
42
|
+
* (default: `singleton`).
|
|
43
|
+
*
|
|
44
|
+
* `@Repo()` is intentionally separate from `@Service()` to clearly
|
|
45
|
+
* distinguish persistence-oriented classes from business logic.
|
|
46
|
+
* In the future, repository-specific behavior (caching layers,
|
|
47
|
+
* transactional wrappers, profiling, etc.) can be attached here
|
|
48
|
+
* without modifying user code.
|
|
49
|
+
*
|
|
50
|
+
* ## Example
|
|
51
|
+
* ```ts
|
|
52
|
+
* @Repo()
|
|
53
|
+
* export class AccountRepository {
|
|
54
|
+
* async findById(id: string) { ... }
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @param options.scope - Optional binding scope (`singleton` | `transient`)
|
|
59
|
+
*/
|
|
10
60
|
function Repo(options) {
|
|
11
61
|
var _a;
|
|
12
62
|
return (0, bind_1.Bind)((_a = options === null || options === void 0 ? void 0 : options.scope) !== null && _a !== void 0 ? _a : 'singleton');
|
|
@@ -95,7 +95,7 @@ class Player {
|
|
|
95
95
|
* @param vector - The target coordinates (x, y, z).
|
|
96
96
|
*/
|
|
97
97
|
teleportClient(vector) {
|
|
98
|
-
this.emit('
|
|
98
|
+
this.emit('opencore:spawner:teleport', vector);
|
|
99
99
|
}
|
|
100
100
|
/**
|
|
101
101
|
* Disconnects the player from the server.
|
|
@@ -14,8 +14,8 @@ function normalizeError(error, origin) {
|
|
|
14
14
|
}
|
|
15
15
|
function handleCommandError(error, meta, playerId) {
|
|
16
16
|
const appError = normalizeError(error, 'server');
|
|
17
|
-
logger_1.loggers.command.error(`Command execution failed: /${meta.
|
|
18
|
-
command: meta.
|
|
17
|
+
logger_1.loggers.command.error(`Command execution failed: /${meta.command}`, {
|
|
18
|
+
command: meta.command,
|
|
19
19
|
handler: meta.methodName,
|
|
20
20
|
playerId,
|
|
21
21
|
code: appError.code,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveMethod = resolveMethod;
|
|
4
|
+
const logger_1 = require("../../shared/logger");
|
|
5
|
+
function resolveMethod(instance, methodName, errorMessage) {
|
|
6
|
+
const proto = Object.getPrototypeOf(instance);
|
|
7
|
+
const method = instance[methodName];
|
|
8
|
+
if (typeof method !== 'function') {
|
|
9
|
+
logger_1.loggers.scanner.error(errorMessage, {
|
|
10
|
+
className: instance.constructor.name,
|
|
11
|
+
methodName,
|
|
12
|
+
});
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const handler = method.bind(instance);
|
|
16
|
+
const handlerName = `${instance.constructor.name}.${methodName}`;
|
|
17
|
+
return { handler, handlerName, proto };
|
|
18
|
+
}
|
package/dist/server/index.js
CHANGED
|
@@ -11,9 +11,9 @@ const playerSessionLoader = () => {
|
|
|
11
11
|
const persistenceService = tsyringe_1.container.resolve(persistence_service_1.PlayerPersistenceService);
|
|
12
12
|
// Initialize persistence service (resolves provider if configured)
|
|
13
13
|
persistenceService.initialize();
|
|
14
|
-
on('playerJoining', async (
|
|
14
|
+
on('playerJoining', async () => {
|
|
15
15
|
var _a;
|
|
16
|
-
const clientId =
|
|
16
|
+
const clientId = source;
|
|
17
17
|
const license = (_a = GetPlayerIdentifier(clientId.toString(), 0)) !== null && _a !== void 0 ? _a : undefined;
|
|
18
18
|
const player = playerManager.bind(clientId, { license });
|
|
19
19
|
logger_1.loggers.session.info(`Player session created`, {
|
|
@@ -26,9 +26,18 @@ const playerSessionLoader = () => {
|
|
|
26
26
|
clientId,
|
|
27
27
|
license,
|
|
28
28
|
});
|
|
29
|
+
setImmediate(() => {
|
|
30
|
+
const currentPlayer = playerManager.getByClient(clientId);
|
|
31
|
+
if (!currentPlayer)
|
|
32
|
+
return;
|
|
33
|
+
(0, core_event_bus_1.emitCoreEvent)('core:playerFullyConnected', {
|
|
34
|
+
clientId,
|
|
35
|
+
license,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
29
38
|
});
|
|
30
|
-
on('playerDropped', async () => {
|
|
31
|
-
const clientId = Number(
|
|
39
|
+
on('playerDropped', async (source) => {
|
|
40
|
+
const clientId = Number(source);
|
|
32
41
|
const player = playerManager.getByClient(clientId);
|
|
33
42
|
// Save player data before destroying session
|
|
34
43
|
if (player) {
|
|
@@ -8,7 +8,7 @@ export declare class CommandService {
|
|
|
8
8
|
register(meta: CommandMetadata, handler: Function): void;
|
|
9
9
|
execute(player: Server.Player, commandName: string, args: string[], raw: string): Promise<void>;
|
|
10
10
|
getAllCommands(): {
|
|
11
|
-
|
|
11
|
+
command: string;
|
|
12
12
|
description: string;
|
|
13
13
|
usage: string;
|
|
14
14
|
}[];
|
|
@@ -18,26 +18,29 @@ const utils_1 = require("../../utils");
|
|
|
18
18
|
const zod_1 = __importDefault(require("zod"));
|
|
19
19
|
const security_handler_contract_1 = require("../templates/security/security-handler.contract");
|
|
20
20
|
const logger_1 = require("../../shared/logger");
|
|
21
|
+
const schema_generator_1 = require("../system/schema-generator");
|
|
21
22
|
let CommandService = class CommandService {
|
|
22
23
|
constructor(securityHandler) {
|
|
23
24
|
this.securityHandler = securityHandler;
|
|
24
25
|
this.commands = new Map();
|
|
25
26
|
}
|
|
26
27
|
register(meta, handler) {
|
|
27
|
-
this.commands.set(meta.
|
|
28
|
-
logger_1.loggers.command.debug(`Registered: /${meta.
|
|
28
|
+
this.commands.set(meta.command.toLowerCase(), { meta, handler });
|
|
29
|
+
logger_1.loggers.command.debug(`Registered: /${meta.command}${meta.schema ? ' [Validated]' : ''}`);
|
|
29
30
|
}
|
|
30
31
|
async execute(player, commandName, args, raw) {
|
|
32
|
+
var _a;
|
|
31
33
|
const entry = this.commands.get(commandName.toLowerCase());
|
|
32
34
|
if (!entry) {
|
|
33
35
|
return;
|
|
34
36
|
}
|
|
35
37
|
const { meta, handler } = entry;
|
|
36
38
|
let validatedArgs = args;
|
|
37
|
-
|
|
39
|
+
// Use explicit schema or auto-generate from paramTypes
|
|
40
|
+
const schema = (_a = meta.schema) !== null && _a !== void 0 ? _a : (0, schema_generator_1.generateSchemaFromTypes)(meta.paramTypes);
|
|
41
|
+
if (schema) {
|
|
38
42
|
try {
|
|
39
|
-
|
|
40
|
-
validatedArgs = Array.isArray(result) ? result : [result];
|
|
43
|
+
validatedArgs = await schema.parseAsync(args);
|
|
41
44
|
}
|
|
42
45
|
catch (error) {
|
|
43
46
|
if (error instanceof zod_1.default.ZodError) {
|
|
@@ -60,7 +63,7 @@ let CommandService = class CommandService {
|
|
|
60
63
|
return Array.from(this.commands.values()).map((c) => {
|
|
61
64
|
var _a, _b;
|
|
62
65
|
return ({
|
|
63
|
-
|
|
66
|
+
command: c.meta.command,
|
|
64
67
|
description: (_a = c.meta.description) !== null && _a !== void 0 ? _a : '',
|
|
65
68
|
usage: (_b = c.meta.usage) !== null && _b !== void 0 ? _b : '',
|
|
66
69
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { DecoratorProcessor } from '../../../system/decorator-processor';
|
|
2
2
|
import { CommandService } from '../../services';
|
|
3
|
-
import {
|
|
3
|
+
import { CommandMetadata } from '../../decorators/command';
|
|
4
4
|
export declare class CommandProcessor implements DecoratorProcessor {
|
|
5
5
|
private commandService;
|
|
6
6
|
readonly metadataKey: string;
|
|
7
7
|
constructor(commandService: CommandService);
|
|
8
|
-
process(target: any, methodName: string, metadata:
|
|
8
|
+
process(target: any, methodName: string, metadata: CommandMetadata): void;
|
|
9
9
|
}
|
|
@@ -20,8 +20,7 @@ let CommandProcessor = class CommandProcessor {
|
|
|
20
20
|
}
|
|
21
21
|
process(target, methodName, metadata) {
|
|
22
22
|
const handler = target[methodName].bind(target);
|
|
23
|
-
|
|
24
|
-
this.commandService.register(fullMeta, handler);
|
|
23
|
+
this.commandService.register(metadata, handler);
|
|
25
24
|
}
|
|
26
25
|
};
|
|
27
26
|
exports.CommandProcessor = CommandProcessor;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DecoratorProcessor } from '../../../system/decorator-processor';
|
|
2
2
|
export declare class CoreEventProcessor implements DecoratorProcessor {
|
|
3
3
|
readonly metadataKey: string;
|
|
4
|
-
process(
|
|
4
|
+
process(instance: any, methodName: string, metadata: {
|
|
5
5
|
event: string;
|
|
6
6
|
}): void;
|
|
7
7
|
}
|
|
@@ -11,13 +11,16 @@ const tsyringe_1 = require("tsyringe");
|
|
|
11
11
|
const core_event_bus_1 = require("../../bus/core-event-bus");
|
|
12
12
|
const metadata_server_keys_1 = require("../metadata-server.keys");
|
|
13
13
|
const logger_1 = require("../../../shared/logger");
|
|
14
|
+
const resolve_method_1 = require("../../helpers/resolve-method");
|
|
14
15
|
let CoreEventProcessor = class CoreEventProcessor {
|
|
15
16
|
constructor() {
|
|
16
17
|
this.metadataKey = metadata_server_keys_1.METADATA_KEYS.CORE_EVENT;
|
|
17
18
|
}
|
|
18
|
-
process(
|
|
19
|
-
const
|
|
20
|
-
|
|
19
|
+
process(instance, methodName, metadata) {
|
|
20
|
+
const result = (0, resolve_method_1.resolveMethod)(instance, methodName, `[CoreEventProcessor] Method "${methodName}" not found`);
|
|
21
|
+
if (!result)
|
|
22
|
+
return;
|
|
23
|
+
const { handler, handlerName } = result;
|
|
21
24
|
(0, core_event_bus_1.onCoreEvent)(metadata.event, (payload) => {
|
|
22
25
|
try {
|
|
23
26
|
handler(payload);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DecoratorProcessor } from '../../../system/decorator-processor';
|
|
2
2
|
export declare class ExportProcessor implements DecoratorProcessor {
|
|
3
3
|
readonly metadataKey: string;
|
|
4
|
-
process(
|
|
4
|
+
process(instance: any, methodName: string, metadata: {
|
|
5
5
|
exportName: string;
|
|
6
6
|
}): void;
|
|
7
7
|
}
|
|
@@ -10,13 +10,17 @@ exports.ExportProcessor = void 0;
|
|
|
10
10
|
const tsyringe_1 = require("tsyringe");
|
|
11
11
|
const metadata_server_keys_1 = require("../metadata-server.keys");
|
|
12
12
|
const logger_1 = require("../../../shared/logger");
|
|
13
|
+
const resolve_method_1 = require("../../helpers/resolve-method");
|
|
13
14
|
let ExportProcessor = class ExportProcessor {
|
|
14
15
|
constructor() {
|
|
15
16
|
this.metadataKey = metadata_server_keys_1.METADATA_KEYS.EXPORT;
|
|
16
17
|
}
|
|
17
|
-
process(
|
|
18
|
-
const
|
|
19
|
-
|
|
18
|
+
process(instance, methodName, metadata) {
|
|
19
|
+
const result = (0, resolve_method_1.resolveMethod)(instance, methodName, `[ExportEventProcessor] Method "${methodName}" not found`);
|
|
20
|
+
if (!result)
|
|
21
|
+
return;
|
|
22
|
+
const { handler } = result;
|
|
23
|
+
globalThis.exports(metadata.exportName, handler);
|
|
20
24
|
logger_1.loggers.exports.debug(`Registered: ${metadata.exportName}`);
|
|
21
25
|
}
|
|
22
26
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DecoratorProcessor } from '../../../system/decorator-processor';
|
|
2
|
+
export declare class FiveMEventProcessor implements DecoratorProcessor {
|
|
3
|
+
readonly metadataKey: string;
|
|
4
|
+
process(instance: any, methodName: string, metadata: {
|
|
5
|
+
event: string;
|
|
6
|
+
}): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.FiveMEventProcessor = void 0;
|
|
10
|
+
const tsyringe_1 = require("tsyringe");
|
|
11
|
+
const metadata_server_keys_1 = require("../metadata-server.keys");
|
|
12
|
+
const logger_1 = require("../../../shared/logger");
|
|
13
|
+
const resolve_method_1 = require("../../helpers/resolve-method");
|
|
14
|
+
let FiveMEventProcessor = class FiveMEventProcessor {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.metadataKey = metadata_server_keys_1.METADATA_KEYS.FIVEM_EVENT;
|
|
17
|
+
}
|
|
18
|
+
process(instance, methodName, metadata) {
|
|
19
|
+
const result = (0, resolve_method_1.resolveMethod)(instance, methodName, `[FiveMEventProcessor] Method "${methodName}" not found`);
|
|
20
|
+
if (!result)
|
|
21
|
+
return;
|
|
22
|
+
const { handler, handlerName } = result;
|
|
23
|
+
on(metadata.event, (...args) => {
|
|
24
|
+
try {
|
|
25
|
+
handler(...args);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
logger_1.loggers.eventBus.error(`Handler error in FiveMEvent`, {
|
|
29
|
+
event: metadata.event,
|
|
30
|
+
handler: handlerName,
|
|
31
|
+
}, error);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
logger_1.loggers.eventBus.debug(`Registered FiveM event: ${metadata.event} -> ${handlerName}`);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
exports.FiveMEventProcessor = FiveMEventProcessor;
|
|
38
|
+
exports.FiveMEventProcessor = FiveMEventProcessor = __decorate([
|
|
39
|
+
(0, tsyringe_1.injectable)()
|
|
40
|
+
], FiveMEventProcessor);
|
|
@@ -7,5 +7,5 @@ export declare class NetEventProcessor implements DecoratorProcessor {
|
|
|
7
7
|
private securityHandler;
|
|
8
8
|
readonly metadataKey: string;
|
|
9
9
|
constructor(playerService: PlayerService, securityHandler: SecurityHandlerContract);
|
|
10
|
-
process(
|
|
10
|
+
process(instance: any, methodName: string, metadata: NetEventOptions): void;
|
|
11
11
|
}
|
|
@@ -20,19 +20,22 @@ const security_handler_contract_1 = require("../../templates/security/security-h
|
|
|
20
20
|
const utils_1 = require("../../../utils");
|
|
21
21
|
const logger_1 = require("../../../shared/logger");
|
|
22
22
|
const zod_1 = __importDefault(require("zod"));
|
|
23
|
+
const schema_generator_1 = require("../schema-generator");
|
|
24
|
+
const resolve_method_1 = require("../../helpers/resolve-method");
|
|
23
25
|
let NetEventProcessor = class NetEventProcessor {
|
|
24
26
|
constructor(playerService, securityHandler) {
|
|
25
27
|
this.playerService = playerService;
|
|
26
28
|
this.securityHandler = securityHandler;
|
|
27
29
|
this.metadataKey = metadata_server_keys_1.METADATA_KEYS.NET_EVENT;
|
|
28
30
|
}
|
|
29
|
-
process(
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
process(instance, methodName, metadata) {
|
|
32
|
+
const result = (0, resolve_method_1.resolveMethod)(instance, methodName, `[NetEventProcessor] Method "${methodName}" not found`);
|
|
33
|
+
if (!result)
|
|
34
|
+
return;
|
|
35
|
+
const { handler, handlerName, proto } = result;
|
|
33
36
|
const isPublic = Reflect.getMetadata(metadata_server_keys_1.METADATA_KEYS.PUBLIC, proto, methodName) === true;
|
|
34
37
|
onNet(metadata.eventName, async (...args) => {
|
|
35
|
-
const sourceId = Number(
|
|
38
|
+
const sourceId = Number(source);
|
|
36
39
|
const player = this.playerService.getByClient(sourceId);
|
|
37
40
|
if (!player) {
|
|
38
41
|
logger_1.loggers.netEvent.warn(`Event ignored: Player session not found`, {
|
|
@@ -53,11 +56,11 @@ let NetEventProcessor = class NetEventProcessor {
|
|
|
53
56
|
return;
|
|
54
57
|
}
|
|
55
58
|
let validatedArgs = args;
|
|
56
|
-
|
|
59
|
+
const schema = (0, schema_generator_1.generateSchemaFromTypes)(metadata.paramTypes);
|
|
60
|
+
if (schema) {
|
|
57
61
|
try {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
validatedArgs = [parsed];
|
|
62
|
+
const parsed = schema.parse(args);
|
|
63
|
+
validatedArgs = Array.isArray(parsed) ? parsed : [parsed];
|
|
61
64
|
}
|
|
62
65
|
catch (error) {
|
|
63
66
|
if (error instanceof zod_1.default.ZodError) {
|
|
@@ -7,6 +7,7 @@ const security_handler_contract_1 = require("../templates/security/security-hand
|
|
|
7
7
|
const command_processor_1 = require("./processors/command.processor");
|
|
8
8
|
const coreEvent_processor_1 = require("./processors/coreEvent.processor");
|
|
9
9
|
const export_processor_1 = require("./processors/export.processor");
|
|
10
|
+
const fivemEvent_processor_1 = require("./processors/fivemEvent.processor");
|
|
10
11
|
const netEvent_processor_1 = require("./processors/netEvent.processor");
|
|
11
12
|
const tick_processor_1 = require("./processors/tick.processor");
|
|
12
13
|
function registerSystemServer() {
|
|
@@ -15,6 +16,7 @@ function registerSystemServer() {
|
|
|
15
16
|
container_1.di.register('DecoratorProcessor', { useClass: export_processor_1.ExportProcessor });
|
|
16
17
|
container_1.di.register('DecoratorProcessor', { useClass: coreEvent_processor_1.CoreEventProcessor });
|
|
17
18
|
container_1.di.register('DecoratorProcessor', { useClass: command_processor_1.CommandProcessor });
|
|
19
|
+
container_1.di.register('DecoratorProcessor', { useClass: fivemEvent_processor_1.FiveMEventProcessor });
|
|
18
20
|
if (!container_1.di.isRegistered(security_handler_contract_1.SecurityHandlerContract)) {
|
|
19
21
|
container_1.di.registerSingleton(security_handler_contract_1.SecurityHandlerContract, default_security_handler_1.DefaultSecurityHandler);
|
|
20
22
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateSchemaFromTypes = generateSchemaFromTypes;
|
|
7
|
+
const zod_1 = __importDefault(require("zod"));
|
|
8
|
+
const player_1 = require("../entities/player");
|
|
9
|
+
function typeToZodSchema(type) {
|
|
10
|
+
switch (type) {
|
|
11
|
+
case String:
|
|
12
|
+
return zod_1.default.coerce.string();
|
|
13
|
+
case Number:
|
|
14
|
+
return zod_1.default.coerce.number();
|
|
15
|
+
case Boolean:
|
|
16
|
+
return zod_1.default.coerce.boolean();
|
|
17
|
+
case Array:
|
|
18
|
+
return zod_1.default.array(zod_1.default.any());
|
|
19
|
+
case Object:
|
|
20
|
+
return zod_1.default.any();
|
|
21
|
+
default:
|
|
22
|
+
return zod_1.default.any();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function generateSchemaFromTypes(paramTypes) {
|
|
26
|
+
var _a;
|
|
27
|
+
if (!paramTypes || paramTypes.length <= 1)
|
|
28
|
+
return null;
|
|
29
|
+
if (paramTypes[0] !== player_1.Player) {
|
|
30
|
+
throw new Error(`@OnNet: First parameter must be Player, got ${(_a = paramTypes[0]) === null || _a === void 0 ? void 0 : _a.name}`);
|
|
31
|
+
}
|
|
32
|
+
const argSchemas = paramTypes.slice(1).map(typeToZodSchema);
|
|
33
|
+
return zod_1.default.tuple(argSchemas);
|
|
34
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Player } from '../../entities';
|
|
2
|
+
type CommandArgs = string[] | any;
|
|
2
3
|
/**
|
|
3
4
|
* Template for admin controller implementations.
|
|
4
5
|
*/
|
|
5
6
|
export interface AdminControllerTemplate {
|
|
6
|
-
handleBanCommand(player:
|
|
7
|
-
handleKickCommand(player:
|
|
8
|
-
handleMuteCommand(player:
|
|
9
|
-
handleUnmuteCommand(player:
|
|
7
|
+
handleBanCommand(player: Player, args: CommandArgs, raw?: string): Promise<void>;
|
|
8
|
+
handleKickCommand(player: Player, args: CommandArgs, raw?: string): Promise<void>;
|
|
9
|
+
handleMuteCommand(player: Player, args: CommandArgs, raw?: string): Promise<void>;
|
|
10
|
+
handleUnmuteCommand(player: Player, args: CommandArgs, raw?: string): Promise<void>;
|
|
10
11
|
}
|
|
12
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { LinkedID } from '../../services';
|
|
2
|
-
import { Server } from '../../..';
|
|
1
|
+
import type { LinkedID } from '../../services';
|
|
2
|
+
import type { Server } from '../../..';
|
|
3
3
|
export interface AuthCredentials {
|
|
4
4
|
/** Standard username/password auth */
|
|
5
5
|
username?: string;
|