@open-core/framework 0.2.2-beta.1 → 0.2.4

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.
Files changed (34) hide show
  1. package/LICENSE +373 -373
  2. package/README.md +217 -217
  3. package/dist/adapters/node/node-entity-server.js +3 -0
  4. package/dist/adapters/node/node-exports.d.ts +2 -2
  5. package/dist/kernel/utils/vector3.d.ts +1 -0
  6. package/dist/kernel/utils/vector3.js +1 -0
  7. package/dist/runtime/client/services/appearance.service.js +4 -0
  8. package/dist/runtime/server/bootstrap.js +1 -1
  9. package/dist/runtime/server/bootstrap.validation.js +2 -0
  10. package/dist/runtime/server/bus/core-event-bus.js +5 -2
  11. package/dist/runtime/server/controllers/principal-export.controller.js +1 -1
  12. package/dist/runtime/server/decorators/throttle.js +3 -1
  13. package/dist/runtime/server/helpers/command-validation.helper.d.ts +1 -1
  14. package/dist/runtime/server/helpers/function-helper.d.ts +1 -1
  15. package/dist/runtime/server/services/core/command.service.d.ts +1 -1
  16. package/dist/runtime/server/services/parallel/worker-pool.js +4 -0
  17. package/dist/runtime/server/services/ports/command-execution.port.d.ts +1 -1
  18. package/dist/runtime/server/services/remote/remote-command.service.d.ts +1 -1
  19. package/dist/runtime/server/services/services.register.js +2 -2
  20. package/package.json +100 -99
  21. package/dist/kernel/di/tokens.d.ts +0 -30
  22. package/dist/kernel/di/tokens.js +0 -38
  23. package/dist/runtime/client/interfaces/appearance.interface.d.ts +0 -25
  24. package/dist/runtime/client/interfaces/appearance.interface.js +0 -2
  25. package/dist/runtime/server/controllers/command.controller.d.ts +0 -15
  26. package/dist/runtime/server/controllers/command.controller.js +0 -100
  27. package/dist/runtime/server/services/access-control.service.d.ts +0 -59
  28. package/dist/runtime/server/services/access-control.service.js +0 -127
  29. package/dist/runtime/server/services/core/vehicle-modification.service.d.ts +0 -104
  30. package/dist/runtime/server/services/core/vehicle-modification.service.js +0 -330
  31. package/dist/runtime/server/services/core/vehicle.service.d.ts +0 -128
  32. package/dist/runtime/server/services/core/vehicle.service.js +0 -391
  33. package/dist/runtime/server/services/remote/remote-principal.provider.d.ts +0 -55
  34. package/dist/runtime/server/services/remote/remote-principal.provider.js +0 -130
package/package.json CHANGED
@@ -1,99 +1,100 @@
1
- {
2
- "name": "@open-core/framework",
3
- "version": "0.2.2-beta.1",
4
- "description": "Secure, Event-Driven, OOP Engine for FiveM. Stop scripting, start engineering.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "type": "commonjs",
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/newcore-network/opencore.git"
11
- },
12
- "homepage": "https://github.com/newcore-network/opencore",
13
- "bugs": {
14
- "url": "https://github.com/newcore-network/opencore/issues"
15
- },
16
- "files": [
17
- "dist",
18
- "README.md",
19
- "LICENSE"
20
- ],
21
- "exports": {
22
- ".": {
23
- "types": "./dist/index.d.ts",
24
- "import": "./dist/index.js",
25
- "require": "./dist/index.js"
26
- },
27
- "./server": {
28
- "types": "./dist/runtime/server/index.d.ts",
29
- "import": "./dist/runtime/server/index.js",
30
- "require": "./dist/runtime/server/index.js"
31
- },
32
- "./client": {
33
- "types": "./dist/runtime/client/index.d.ts",
34
- "import": "./dist/runtime/client/index.js",
35
- "require": "./dist/runtime/client/index.js"
36
- },
37
- "./shared": {
38
- "types": "./dist/kernel/shared/index.d.ts",
39
- "import": "./dist/kernel/shared/index.js",
40
- "require": "./dist/kernel/shared/index.js"
41
- },
42
- "./utils": {
43
- "types": "./dist/kernel/utils/index.d.ts",
44
- "import": "./dist/kernel/utils/index.js",
45
- "require": "./dist/kernel/utils/index.js"
46
- },
47
- "./package.json": "./package.json"
48
- },
49
- "scripts": {
50
- "publish": "pnpm build && npm publish",
51
- "build": "tsc -p tsconfig.build.json",
52
- "watch": "tsc -p tsconfig.build.json --watch",
53
- "check": "biome check .",
54
- "check:fix": "biome check --write .",
55
- "check:fix:unsafe": "biome check --write --unsafe",
56
- "format": "biome format --write .",
57
- "lint": "biome lint .",
58
- "lint:fix": "biome lint --write .",
59
- "typecheck": "tsc --noEmit",
60
- "test": "npx vitest run --project unit --project integration --project e2e",
61
- "test:watch": "npx vitest --project unit --project integration --project e2e",
62
- "test:unit": "npx vitest run --project unit",
63
- "test:integration": "npx vitest run --project integration",
64
- "test:coverage": "npx vitest run --coverage",
65
- "bench": "npx tsx benchmark/index.ts",
66
- "bench:core": "npx tsx benchmark/index.ts --core",
67
- "bench:load": "npx vitest run --project benchmark",
68
- "bench:all": "npx tsx benchmark/index.ts --all"
69
- },
70
- "keywords": [
71
- "framework",
72
- "opencore",
73
- "fivem",
74
- "typescript",
75
- "roleplay"
76
- ],
77
- "author": "OpenCore Team",
78
- "license": "MPL-2.0",
79
- "packageManager": "pnpm@10.13.1",
80
- "dependencies": {
81
- "reflect-metadata": "^0.2.2",
82
- "tsyringe": "^4.10.0",
83
- "uuid": "^13.0.0",
84
- "zod": "^4.1.13"
85
- },
86
- "devDependencies": {
87
- "@biomejs/biome": "^2.3.10",
88
- "@citizenfx/client": "2.0.22443-1",
89
- "@citizenfx/server": "2.0.22443-1",
90
- "@types/node": "^24.10.1",
91
- "@vitest/coverage-v8": "^4.0.15",
92
- "eslint-config-prettier": "^10.1.8",
93
- "eslint-plugin-import": "^2.32.0",
94
- "tinybench": "^2.7.0",
95
- "tsx": "^4.19.2",
96
- "typescript": "^5.9.3",
97
- "vitest": "^4.0.15"
98
- }
99
- }
1
+ {
2
+ "name": "@open-core/framework",
3
+ "version": "0.2.4",
4
+ "description": "Secure, Event-Driven, OOP Engine for FiveM. Stop scripting, start engineering.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "commonjs",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/newcore-network/opencore.git"
11
+ },
12
+ "homepage": "https://github.com/newcore-network/opencore",
13
+ "bugs": {
14
+ "url": "https://github.com/newcore-network/opencore/issues"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js",
25
+ "require": "./dist/index.js"
26
+ },
27
+ "./server": {
28
+ "types": "./dist/runtime/server/index.d.ts",
29
+ "import": "./dist/runtime/server/index.js",
30
+ "require": "./dist/runtime/server/index.js"
31
+ },
32
+ "./client": {
33
+ "types": "./dist/runtime/client/index.d.ts",
34
+ "import": "./dist/runtime/client/index.js",
35
+ "require": "./dist/runtime/client/index.js"
36
+ },
37
+ "./shared": {
38
+ "types": "./dist/kernel/shared/index.d.ts",
39
+ "import": "./dist/kernel/shared/index.js",
40
+ "require": "./dist/kernel/shared/index.js"
41
+ },
42
+ "./utils": {
43
+ "types": "./dist/kernel/utils/index.d.ts",
44
+ "import": "./dist/kernel/utils/index.js",
45
+ "require": "./dist/kernel/utils/index.js"
46
+ },
47
+ "./package.json": "./package.json"
48
+ },
49
+ "scripts": {
50
+ "build": "tsc -p tsconfig.build.json",
51
+ "watch": "tsc -p tsconfig.build.json --watch",
52
+ "check": "biome check .",
53
+ "check:fix": "biome check --write .",
54
+ "check:fix:unsafe": "biome check --write --unsafe",
55
+ "format": "biome format --write .",
56
+ "lint": "biome lint .",
57
+ "lint:fix": "biome lint --write .",
58
+ "typecheck": "tsc --noEmit",
59
+ "test": "npx vitest run --project unit --project integration --project e2e",
60
+ "test:ci": "npx vitest run --project unit --project integration",
61
+ "test:watch": "npx vitest --project unit --project integration --project e2e",
62
+ "test:unit": "npx vitest run --project unit",
63
+ "test:integration": "npx vitest run --project integration",
64
+ "test:e2e": "npx vitest run --project e2e",
65
+ "test:coverage": "npx vitest run --coverage",
66
+ "bench": "npx tsx benchmark/index.ts",
67
+ "bench:core": "npx tsx benchmark/index.ts --core",
68
+ "bench:load": "npx vitest run --project benchmark",
69
+ "bench:all": "npx tsx benchmark/index.ts --all"
70
+ },
71
+ "keywords": [
72
+ "framework",
73
+ "opencore",
74
+ "fivem",
75
+ "typescript",
76
+ "roleplay"
77
+ ],
78
+ "author": "OpenCore Team",
79
+ "license": "MPL-2.0",
80
+ "packageManager": "pnpm@10.13.1",
81
+ "dependencies": {
82
+ "reflect-metadata": "^0.2.2",
83
+ "tsyringe": "^4.10.0",
84
+ "uuid": "^13.0.0",
85
+ "zod": "^4.1.13"
86
+ },
87
+ "devDependencies": {
88
+ "@biomejs/biome": "^2.3.10",
89
+ "@citizenfx/client": "2.0.22443-1",
90
+ "@citizenfx/server": "2.0.22443-1",
91
+ "@types/node": "^24.10.1",
92
+ "@vitest/coverage-v8": "^4.0.15",
93
+ "eslint-config-prettier": "^10.1.8",
94
+ "eslint-plugin-import": "^2.32.0",
95
+ "tinybench": "^2.7.0",
96
+ "tsx": "^4.19.2",
97
+ "typescript": "^5.9.3",
98
+ "vitest": "^4.0.15"
99
+ }
100
+ }
@@ -1,30 +0,0 @@
1
- /**
2
- * Dependency Injection Tokens for OpenCore.
3
- *
4
- * Using string tokens instead of class references for injection
5
- * avoids issues with circular dependencies and "TypeInfo not known"
6
- * errors in certain build environments.
7
- */
8
- export declare const DI_TOKENS: {
9
- readonly CommandExecutionPort: symbol;
10
- readonly PlayerDirectoryPort: symbol;
11
- readonly PrincipalPort: symbol;
12
- readonly DecoratorProcessor: "DecoratorProcessor";
13
- readonly DatabaseService: symbol;
14
- readonly HttpService: symbol;
15
- readonly ChatService: symbol;
16
- readonly RateLimiterService: symbol;
17
- readonly PrincipalProvider: symbol;
18
- readonly AuthProvider: symbol;
19
- readonly Exports: symbol;
20
- readonly EngineEvents: symbol;
21
- readonly NetTransport: symbol;
22
- readonly Tick: symbol;
23
- readonly PlayerInfo: symbol;
24
- readonly ResourceInfo: symbol;
25
- readonly EntityServer: symbol;
26
- readonly VehicleServer: symbol;
27
- readonly PlayerServer: symbol;
28
- readonly Hasher: symbol;
29
- readonly PedAppearanceServer: symbol;
30
- };
@@ -1,38 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DI_TOKENS = void 0;
4
- /**
5
- * Dependency Injection Tokens for OpenCore.
6
- *
7
- * Using string tokens instead of class references for injection
8
- * avoids issues with circular dependencies and "TypeInfo not known"
9
- * errors in certain build environments.
10
- */
11
- exports.DI_TOKENS = {
12
- // Ports
13
- CommandExecutionPort: Symbol.for('CommandExecutionPort'),
14
- PlayerDirectoryPort: Symbol.for('PlayerDirectoryPort'),
15
- PrincipalPort: Symbol.for('PrincipalPort'),
16
- // Decorator Processors
17
- DecoratorProcessor: 'DecoratorProcessor',
18
- // Services
19
- DatabaseService: Symbol.for('DatabaseService'),
20
- HttpService: Symbol.for('HttpService'),
21
- ChatService: Symbol.for('ChatService'),
22
- RateLimiterService: Symbol.for('RateLimiterService'),
23
- // Providers
24
- PrincipalProvider: Symbol.for('PrincipalProvider'),
25
- AuthProvider: Symbol.for('AuthProvider'),
26
- // Adapters
27
- Exports: Symbol.for('IExports'),
28
- EngineEvents: Symbol.for('IEngineEvents'),
29
- NetTransport: Symbol.for('INetTransport'),
30
- Tick: Symbol.for('ITick'),
31
- PlayerInfo: Symbol.for('IPlayerInfo'),
32
- ResourceInfo: Symbol.for('IResourceInfo'),
33
- EntityServer: Symbol.for('IEntityServer'),
34
- VehicleServer: Symbol.for('IVehicleServer'),
35
- PlayerServer: Symbol.for('IPlayerServer'),
36
- Hasher: Symbol.for('IHasher'),
37
- PedAppearanceServer: Symbol.for('IPedAppearanceServer'),
38
- };
@@ -1,25 +0,0 @@
1
- export interface PlayerAppearance {
2
- components?: Record<
3
- number,
4
- {
5
- drawable: number
6
- texture: number
7
- }
8
- >
9
- props?: Record<
10
- number,
11
- {
12
- drawable: number
13
- texture: number
14
- }
15
- >
16
- faceFeatures?: Record<number, number>
17
- headBlend?: {
18
- shapeFirst: number
19
- shapeSecond: number
20
- shapeMix: number
21
- skinFirst: number
22
- skinSecond: number
23
- skinMix: number
24
- }
25
- }
@@ -1,2 +0,0 @@
1
- 'use strict'
2
- Object.defineProperty(exports, '__esModule', { value: true })
@@ -1,15 +0,0 @@
1
- import { CommandExecutionPort } from '../services/ports/command-execution.port'
2
- import { Player } from '../entities'
3
- /**
4
- * Network controller for command execution.
5
- *
6
- * @remarks
7
- * Receives command execution requests from clients and delegates to CommandExecutionPort.
8
- * In CORE mode, executes commands directly or delegates to owning resource.
9
- * In RESOURCE mode, delegates to CORE via exports.
10
- */
11
- export declare class CommandNetworkController {
12
- private readonly commandService
13
- constructor(commandService: CommandExecutionPort)
14
- onCommandReceived(player: Player, command: string, args: string[]): Promise<void>
15
- }
@@ -1,100 +0,0 @@
1
- 'use strict'
2
- var __decorate =
3
- (this && this.__decorate) ||
4
- function (decorators, target, key, desc) {
5
- var c = arguments.length,
6
- r =
7
- c < 3
8
- ? target
9
- : desc === null
10
- ? (desc = Object.getOwnPropertyDescriptor(target, key))
11
- : desc,
12
- d
13
- if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
14
- r = Reflect.decorate(decorators, target, key, desc)
15
- else
16
- for (var i = decorators.length - 1; i >= 0; i--)
17
- if ((d = decorators[i]))
18
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r
19
- return c > 3 && r && Object.defineProperty(target, key, r), r
20
- }
21
- var __metadata =
22
- (this && this.__metadata) ||
23
- ((k, v) => {
24
- if (typeof Reflect === 'object' && typeof Reflect.metadata === 'function')
25
- return Reflect.metadata(k, v)
26
- })
27
- Object.defineProperty(exports, '__esModule', { value: true })
28
- exports.CommandNetworkController = void 0
29
- const onNet_1 = require('../decorators/onNet')
30
- const command_execution_port_1 = require('../services/ports/command-execution.port')
31
- const entities_1 = require('../entities')
32
- const decorators_1 = require('../decorators')
33
- const logger_1 = require('../../../kernel/shared/logger')
34
- const utils_1 = require('../../../kernel/utils')
35
- /**
36
- * Network controller for command execution.
37
- *
38
- * @remarks
39
- * Receives command execution requests from clients and delegates to CommandExecutionPort.
40
- * In CORE mode, executes commands directly or delegates to owning resource.
41
- * In RESOURCE mode, delegates to CORE via exports.
42
- */
43
- let CommandNetworkController = class CommandNetworkController {
44
- constructor(commandService) {
45
- this.commandService = commandService
46
- }
47
- async onCommandReceived(player, command, args) {
48
- try {
49
- if (command.startsWith('/')) command = command.slice(1)
50
- if (!player.clientID || player.clientID === null || player.clientID === undefined) {
51
- console.log('DEBUG; Player entity not received in core:execute-command')
52
- }
53
- if (args.length > 10 || !/^[a-zA-Z0-9:_-]+$/.test(command)) {
54
- logger_1.loggers.command.warn(`Rejected suspicious command: ${command}`, {
55
- playerId: player.clientID,
56
- playerName: player.name,
57
- })
58
- return
59
- }
60
- logger_1.loggers.command.trace(`Received: /${command}`, {
61
- playerId: player.clientID,
62
- playerName: player.name,
63
- })
64
- await this.commandService.execute(player, command, args)
65
- } catch (error) {
66
- if (error instanceof utils_1.AppError) {
67
- if (error.code === 'GAME:BAD_REQUEST' || error.code === 'COMMAND:NOT_FOUND')
68
- player.send(error.message, 'error')
69
- else player.send('An error occurred while executing the command', 'error')
70
- logger_1.loggers.command.error(
71
- `Execution failed: /${command}`,
72
- {
73
- playerId: player.clientID,
74
- },
75
- error,
76
- )
77
- }
78
- }
79
- }
80
- }
81
- exports.CommandNetworkController = CommandNetworkController
82
- __decorate(
83
- [
84
- (0, decorators_1.Public)(),
85
- (0, onNet_1.OnNet)('core:execute-command'),
86
- __metadata('design:type', Function),
87
- __metadata('design:paramtypes', [entities_1.Player, String, Array]),
88
- __metadata('design:returntype', Promise),
89
- ],
90
- CommandNetworkController.prototype,
91
- 'onCommandReceived',
92
- null,
93
- )
94
- exports.CommandNetworkController = CommandNetworkController = __decorate(
95
- [
96
- (0, decorators_1.Controller)(),
97
- __metadata('design:paramtypes', [command_execution_port_1.CommandExecutionPort]),
98
- ],
99
- CommandNetworkController,
100
- )
@@ -1,59 +0,0 @@
1
- import { Server } from '../../..'
2
- import { PrincipalProviderContract } from '../contracts'
3
- /**
4
- * **Core Security Service**
5
- *
6
- * This service acts as the central enforcement point for the Access Control system.
7
- * It uses the configured `PrincipalProvider` to query roles and validates them against requirements.
8
- *
9
- * It is primarily used internally by the `@Guard` decorator, but can be injected
10
- * into services to perform manual checks.
11
- */
12
- export declare class AccessControlService {
13
- private readonly principalProvider
14
- constructor(principalProvider: PrincipalProviderContract)
15
- /**
16
- * Verifies if a player meets a minimum numeric rank requirement.
17
- *
18
- * @param player - The target player.
19
- * @param minRank - The minimum numeric value required (Inclusive).
20
- *
21
- * @returns `true` if `Principal.rank >= minRank`.
22
- *
23
- * @throws {AppError} code `UNAUTHORIZED` if the player has no Principal (not logged in).
24
- * @throws {AppError} code `NO_RANK_IN_PRINCIPAL` if the Principal exists but has no `rank` defined.
25
- */
26
- hasRank(player: Server.Player, minRank: number): Promise<boolean>
27
- /**
28
- * Verifies if a player possesses a specific permission string.
29
- *
30
- * @remarks
31
- * This method supports the **Wildcard ('*')** permission. If the principal has `'*'`
32
- * in their permissions array, this method always returns `true`.
33
- *
34
- * @param player - The target player.
35
- * @param permission - The specific permission key (e.g., `'admin.ban'`).
36
- * @returns `true` if the player has the permission or the wildcard.
37
- */
38
- hasPermission(player: Server.Player, permission: string): Promise<boolean>
39
- /**
40
- * **Strict Enforcement**
41
- *
42
- * Validates a set of requirements against a player. If any requirement fails,
43
- * it throws an exception, halting the execution flow.
44
- *
45
- * Used primarily by the `@Guard` decorator logic.
46
- *
47
- * @param player - The server player to validate.
48
- * @param requirements - An object containing rank and/or permission constraints.
49
- *
50
- * @throws {AppError} code `PERMISSION_DENIED` if validation fails.
51
- */
52
- enforce(
53
- player: Server.Player,
54
- requirements: {
55
- minRank?: number
56
- permission?: string
57
- },
58
- ): Promise<void>
59
- }
@@ -1,127 +0,0 @@
1
- 'use strict'
2
- var __decorate =
3
- (this && this.__decorate) ||
4
- function (decorators, target, key, desc) {
5
- var c = arguments.length,
6
- r =
7
- c < 3
8
- ? target
9
- : desc === null
10
- ? (desc = Object.getOwnPropertyDescriptor(target, key))
11
- : desc,
12
- d
13
- if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
14
- r = Reflect.decorate(decorators, target, key, desc)
15
- else
16
- for (var i = decorators.length - 1; i >= 0; i--)
17
- if ((d = decorators[i]))
18
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r
19
- return c > 3 && r && Object.defineProperty(target, key, r), r
20
- }
21
- var __metadata =
22
- (this && this.__metadata) ||
23
- ((k, v) => {
24
- if (typeof Reflect === 'object' && typeof Reflect.metadata === 'function')
25
- return Reflect.metadata(k, v)
26
- })
27
- Object.defineProperty(exports, '__esModule', { value: true })
28
- exports.AccessControlService = void 0
29
- const tsyringe_1 = require('tsyringe')
30
- const utils_1 = require('../../../kernel/utils')
31
- const contracts_1 = require('../contracts')
32
- /**
33
- * **Core Security Service**
34
- *
35
- * This service acts as the central enforcement point for the Access Control system.
36
- * It uses the configured `PrincipalProvider` to query roles and validates them against requirements.
37
- *
38
- * It is primarily used internally by the `@Guard` decorator, but can be injected
39
- * into services to perform manual checks.
40
- */
41
- let AccessControlService = class AccessControlService {
42
- constructor(principalProvider) {
43
- this.principalProvider = principalProvider
44
- }
45
- /**
46
- * Verifies if a player meets a minimum numeric rank requirement.
47
- *
48
- * @param player - The target player.
49
- * @param minRank - The minimum numeric value required (Inclusive).
50
- *
51
- * @returns `true` if `Principal.rank >= minRank`.
52
- *
53
- * @throws {AppError} code `UNAUTHORIZED` if the player has no Principal (not logged in).
54
- * @throws {AppError} code `NO_RANK_IN_PRINCIPAL` if the Principal exists but has no `rank` defined.
55
- */
56
- async hasRank(player, minRank) {
57
- const principal = await this.principalProvider.getPrincipal(player)
58
- if (!principal) throw new utils_1.AppError('AUTH:UNAUTHORIZED', 'No principal found', 'core')
59
- if (principal.rank === undefined)
60
- throw new utils_1.AppError(
61
- 'GAME:NO_RANK_IN_PRINCIPAL',
62
- "You're trying to compare a Principal rank, but there's no defined rank! ",
63
- 'core',
64
- )
65
- return principal.rank >= minRank
66
- }
67
- /**
68
- * Verifies if a player possesses a specific permission string.
69
- *
70
- * @remarks
71
- * This method supports the **Wildcard ('*')** permission. If the principal has `'*'`
72
- * in their permissions array, this method always returns `true`.
73
- *
74
- * @param player - The target player.
75
- * @param permission - The specific permission key (e.g., `'admin.ban'`).
76
- * @returns `true` if the player has the permission or the wildcard.
77
- */
78
- async hasPermission(player, permission) {
79
- const principal = await this.principalProvider.getPrincipal(player)
80
- if (!principal) return false
81
- if (principal.permissions.includes('*')) return true
82
- return principal.permissions.includes(permission)
83
- }
84
- /**
85
- * **Strict Enforcement**
86
- *
87
- * Validates a set of requirements against a player. If any requirement fails,
88
- * it throws an exception, halting the execution flow.
89
- *
90
- * Used primarily by the `@Guard` decorator logic.
91
- *
92
- * @param player - The server player to validate.
93
- * @param requirements - An object containing rank and/or permission constraints.
94
- *
95
- * @throws {AppError} code `PERMISSION_DENIED` if validation fails.
96
- */
97
- async enforce(player, requirements) {
98
- if (requirements.minRank !== undefined) {
99
- const hasRank = await this.hasRank(player, requirements.minRank)
100
- if (!hasRank) {
101
- throw new utils_1.AppError(
102
- 'AUTH:PERMISSION_DENIED',
103
- `Access Denied: Requires minimum rank level ${requirements.minRank}`,
104
- 'core',
105
- )
106
- }
107
- }
108
- if (requirements.permission) {
109
- const hasPerm = await this.hasPermission(player, requirements.permission)
110
- if (!hasPerm) {
111
- throw new utils_1.AppError(
112
- 'AUTH:PERMISSION_DENIED',
113
- `Access Denied: Missing required permission '${requirements.permission}'`,
114
- 'core',
115
- )
116
- }
117
- }
118
- }
119
- }
120
- exports.AccessControlService = AccessControlService
121
- exports.AccessControlService = AccessControlService = __decorate(
122
- [
123
- (0, tsyringe_1.injectable)(),
124
- __metadata('design:paramtypes', [contracts_1.PrincipalProviderContract]),
125
- ],
126
- AccessControlService,
127
- )