@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.
- package/LICENSE +373 -373
- package/README.md +217 -217
- package/dist/adapters/node/node-entity-server.js +3 -0
- package/dist/adapters/node/node-exports.d.ts +2 -2
- package/dist/kernel/utils/vector3.d.ts +1 -0
- package/dist/kernel/utils/vector3.js +1 -0
- package/dist/runtime/client/services/appearance.service.js +4 -0
- package/dist/runtime/server/bootstrap.js +1 -1
- package/dist/runtime/server/bootstrap.validation.js +2 -0
- package/dist/runtime/server/bus/core-event-bus.js +5 -2
- package/dist/runtime/server/controllers/principal-export.controller.js +1 -1
- package/dist/runtime/server/decorators/throttle.js +3 -1
- package/dist/runtime/server/helpers/command-validation.helper.d.ts +1 -1
- package/dist/runtime/server/helpers/function-helper.d.ts +1 -1
- package/dist/runtime/server/services/core/command.service.d.ts +1 -1
- package/dist/runtime/server/services/parallel/worker-pool.js +4 -0
- package/dist/runtime/server/services/ports/command-execution.port.d.ts +1 -1
- package/dist/runtime/server/services/remote/remote-command.service.d.ts +1 -1
- package/dist/runtime/server/services/services.register.js +2 -2
- package/package.json +100 -99
- package/dist/kernel/di/tokens.d.ts +0 -30
- package/dist/kernel/di/tokens.js +0 -38
- package/dist/runtime/client/interfaces/appearance.interface.d.ts +0 -25
- package/dist/runtime/client/interfaces/appearance.interface.js +0 -2
- package/dist/runtime/server/controllers/command.controller.d.ts +0 -15
- package/dist/runtime/server/controllers/command.controller.js +0 -100
- package/dist/runtime/server/services/access-control.service.d.ts +0 -59
- package/dist/runtime/server/services/access-control.service.js +0 -127
- package/dist/runtime/server/services/core/vehicle-modification.service.d.ts +0 -104
- package/dist/runtime/server/services/core/vehicle-modification.service.js +0 -330
- package/dist/runtime/server/services/core/vehicle.service.d.ts +0 -128
- package/dist/runtime/server/services/core/vehicle.service.js +0 -391
- package/dist/runtime/server/services/remote/remote-principal.provider.d.ts +0 -55
- package/dist/runtime/server/services/remote/remote-principal.provider.js +0 -130
package/README.md
CHANGED
|
@@ -1,217 +1,217 @@
|
|
|
1
|
-
# OpenCore Framework (v0.2.
|
|
2
|
-
|
|
3
|
-
OpenCore is a TypeScript multiplayer runtime framework targeting FiveM via an adapter.
|
|
4
|
-
|
|
5
|
-
It is not a gamemode or RP framework. It provides:
|
|
6
|
-
|
|
7
|
-
- A stable execution model (server and client)
|
|
8
|
-
- Dependency Injection and metadata-driven wiring
|
|
9
|
-
- An event/command system
|
|
10
|
-
- Security primitives (validation, access control, rate limiting)
|
|
11
|
-
|
|
12
|
-
License: MPL-2.0
|
|
13
|
-
|
|
14
|
-
## Scope
|
|
15
|
-
|
|
16
|
-
This package (`@open-core/framework`) contains transversal infrastructure only.
|
|
17
|
-
|
|
18
|
-
- Controllers, services, decorators, and processors
|
|
19
|
-
- Session/lifecycle primitives and contracts
|
|
20
|
-
- Adapters and capability registration
|
|
21
|
-
|
|
22
|
-
Gameplay logic must live in separate resources/modules.
|
|
23
|
-
|
|
24
|
-
## Installation
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
pnpm add @open-core/framework reflect-metadata tsyringe zod uuid
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
This framework uses TypeScript decorators. Ensure your project has decorators enabled.
|
|
31
|
-
|
|
32
|
-
## Imports and entry points
|
|
33
|
-
|
|
34
|
-
The package exposes subpath entry points:
|
|
35
|
-
|
|
36
|
-
- `@open-core/framework` (root)
|
|
37
|
-
- `@open-core/framework/server`
|
|
38
|
-
- `@open-core/framework/client`
|
|
39
|
-
- `@open-core/framework/shared`
|
|
40
|
-
- `@open-core/framework/utils`
|
|
41
|
-
|
|
42
|
-
Most projects will import the `Server`/`Client` namespaces:
|
|
43
|
-
|
|
44
|
-
```ts
|
|
45
|
-
import { Server } from '@open-core/framework'
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Architecture
|
|
49
|
-
|
|
50
|
-
OpenCore follows a Ports & Adapters (Hexagonal) architecture.
|
|
51
|
-
|
|
52
|
-
- Kernel (`src/kernel`): engine-agnostic infrastructure (DI, logger, metadata scanning)
|
|
53
|
-
- Runtime (`src/runtime`): multiplayer execution model (controllers, processors, security, lifecycle)
|
|
54
|
-
- Adapters (`src/adapters`): platform integration (FiveM, Node testing)
|
|
55
|
-
|
|
56
|
-
The runtime never auto-detects the platform. Adapters are selected explicitly at bootstrap time.
|
|
57
|
-
|
|
58
|
-
## Operating modes
|
|
59
|
-
|
|
60
|
-
Each instance runs in exactly one mode configured via `Server.init()`:
|
|
61
|
-
|
|
62
|
-
- `CORE`: authoritative runtime. Typically provides identity/auth/players via exports.
|
|
63
|
-
- `RESOURCE`: a normal FiveM resource using CORE as provider for some features.
|
|
64
|
-
- `STANDALONE`: a self-contained runtime (useful for tooling, simulations, or small servers).
|
|
65
|
-
|
|
66
|
-
## Server bootstrap
|
|
67
|
-
|
|
68
|
-
Initialize the server runtime:
|
|
69
|
-
|
|
70
|
-
```ts
|
|
71
|
-
import { Server } from '@open-core/framework/server'
|
|
72
|
-
|
|
73
|
-
await Server.init({
|
|
74
|
-
mode: 'STANDALONE',
|
|
75
|
-
features: {
|
|
76
|
-
commands: { enabled: true },
|
|
77
|
-
netEvents: { enabled: true },
|
|
78
|
-
},
|
|
79
|
-
})
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Some features require providers (depending on your mode and configuration). Configure them before calling `init()`:
|
|
83
|
-
|
|
84
|
-
```ts
|
|
85
|
-
import { Server } from '@open-core/framework/server'
|
|
86
|
-
|
|
87
|
-
Server.setPrincipalProvider(MyPrincipalProvider)
|
|
88
|
-
Server.setAuthProvider(MyAuthProvider)
|
|
89
|
-
Server.setSecurityHandler(MySecurityHandler)
|
|
90
|
-
Server.setPersistenceProvider(MyPlayerPersistence)
|
|
91
|
-
Server.setNetEventSecurityObserver(MyNetEventSecurityObserver)
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Controllers and decorators
|
|
95
|
-
|
|
96
|
-
OpenCore uses a decorator + processor pattern.
|
|
97
|
-
|
|
98
|
-
Decorators store metadata with `Reflect.defineMetadata()`. During bootstrap, the `MetadataScanner` reads metadata and processors register handlers.
|
|
99
|
-
|
|
100
|
-
### Commands
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
import { Server } from '@open-core/framework/server'
|
|
104
|
-
import { z } from 'zod'
|
|
105
|
-
|
|
106
|
-
const TransferSchema = z.tuple([z.coerce.number().int().positive(), z.coerce.number().min(1)])
|
|
107
|
-
|
|
108
|
-
@Server.Controller()
|
|
109
|
-
export class BankController {
|
|
110
|
-
@Server.Command({
|
|
111
|
-
command: 'transfer',
|
|
112
|
-
usage: '/transfer <id> <amount>',
|
|
113
|
-
schema: TransferSchema,
|
|
114
|
-
})
|
|
115
|
-
@Server.Guard({ rank: 1 })
|
|
116
|
-
@Server.Throttle(1, 2000)
|
|
117
|
-
async transfer(player: Server.Player, args: z.infer<typeof TransferSchema>) {
|
|
118
|
-
const [targetId, amount] = args
|
|
119
|
-
player.emit('chat:message', `transfer -> ${targetId} (${amount})`)
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Network events
|
|
125
|
-
|
|
126
|
-
`@OnNet()` handlers always receive `Player` as the first parameter.
|
|
127
|
-
|
|
128
|
-
```ts
|
|
129
|
-
import { Server } from '@open-core/framework/server'
|
|
130
|
-
import { z } from 'zod'
|
|
131
|
-
|
|
132
|
-
const PayloadSchema = z.object({ action: z.string(), amount: z.number().int().positive() })
|
|
133
|
-
|
|
134
|
-
@Server.Controller()
|
|
135
|
-
export class ExampleNetController {
|
|
136
|
-
@Server.OnNet('bank:action', { schema: PayloadSchema })
|
|
137
|
-
async onBankAction(player: Server.Player, payload: z.infer<typeof PayloadSchema>) {
|
|
138
|
-
player.emit('chat:message', `action=${payload.action} amount=${payload.amount}`)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Security decorators
|
|
144
|
-
|
|
145
|
-
- `@Guard({ rank })` or `@Guard({ permission })`
|
|
146
|
-
- `@Throttle(limit, windowMs)`
|
|
147
|
-
- `@RequiresState({ missing: [...] })`
|
|
148
|
-
|
|
149
|
-
## Testing
|
|
150
|
-
|
|
151
|
-
Tests run with Vitest.
|
|
152
|
-
|
|
153
|
-
```bash
|
|
154
|
-
pnpm test
|
|
155
|
-
pnpm test:unit
|
|
156
|
-
pnpm test:integration
|
|
157
|
-
pnpm test:coverage
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Note: `pnpm test` does not run benchmarks.
|
|
161
|
-
|
|
162
|
-
## Benchmarks
|
|
163
|
-
|
|
164
|
-
There are two benchmark suites:
|
|
165
|
-
|
|
166
|
-
- Core benchmarks (Tinybench)
|
|
167
|
-
- Load benchmarks (Vitest project `benchmark`)
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
pnpm bench:core
|
|
171
|
-
pnpm bench:load
|
|
172
|
-
pnpm bench:all
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Snapshot (latest local run)
|
|
176
|
-
|
|
177
|
-
These values are a small extract from a recent local run (Dec 22, 2025). Results vary by machine.
|
|
178
|
-
|
|
179
|
-
- **Core**
|
|
180
|
-
- Decorators - Define metadata (Command): `~5.72M ops/sec` (mean `0.17μs`)
|
|
181
|
-
- EventBus - Multiple event types: `~2.01M ops/sec` (mean `0.50μs`)
|
|
182
|
-
- Dependency Injection (simple resolve): `~1.7M ops/sec`
|
|
183
|
-
- **Load**
|
|
184
|
-
- Net Events - Simple (10 players): `~28.85K ops/sec` (p95 `0.25ms`)
|
|
185
|
-
- Net Events - Concurrent (500 players): `~1.18M ops/sec` (p95 `0.40ms`)
|
|
186
|
-
- Commands (validated, ~500 players): `~14M ops/sec`
|
|
187
|
-
|
|
188
|
-
Full reports and methodology are available in benchmark/README.md.
|
|
189
|
-
|
|
190
|
-
### Reports
|
|
191
|
-
|
|
192
|
-
Benchmark reports are generated under `benchmark/reports/`.
|
|
193
|
-
|
|
194
|
-
- `pnpm bench:all` generates aggregated reports (text/json/html)
|
|
195
|
-
- Load metrics used by load benchmarks are persisted in `benchmark/reports/.load-metrics.json`
|
|
196
|
-
|
|
197
|
-
For details about the benchmark system, see `benchmark/README.md`.
|
|
198
|
-
|
|
199
|
-
## Development scripts
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
pnpm build
|
|
203
|
-
pnpm watch
|
|
204
|
-
pnpm lint
|
|
205
|
-
pnpm lint:fix
|
|
206
|
-
pnpm format
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
## Ecosystem
|
|
210
|
-
|
|
211
|
-
OpenCore is designed to be extended via separate packages/resources.
|
|
212
|
-
|
|
213
|
-
- `@open-core/identity`: identity and permission system
|
|
214
|
-
|
|
215
|
-
## License
|
|
216
|
-
|
|
217
|
-
MPL-2.0. See `LICENSE`.
|
|
1
|
+
# OpenCore Framework (v0.2.4) Open Stable beta
|
|
2
|
+
|
|
3
|
+
OpenCore is a TypeScript multiplayer runtime framework targeting FiveM via an adapter.
|
|
4
|
+
|
|
5
|
+
It is not a gamemode or RP framework. It provides:
|
|
6
|
+
|
|
7
|
+
- A stable execution model (server and client)
|
|
8
|
+
- Dependency Injection and metadata-driven wiring
|
|
9
|
+
- An event/command system
|
|
10
|
+
- Security primitives (validation, access control, rate limiting)
|
|
11
|
+
|
|
12
|
+
License: MPL-2.0
|
|
13
|
+
|
|
14
|
+
## Scope
|
|
15
|
+
|
|
16
|
+
This package (`@open-core/framework`) contains transversal infrastructure only.
|
|
17
|
+
|
|
18
|
+
- Controllers, services, decorators, and processors
|
|
19
|
+
- Session/lifecycle primitives and contracts
|
|
20
|
+
- Adapters and capability registration
|
|
21
|
+
|
|
22
|
+
Gameplay logic must live in separate resources/modules.
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm add @open-core/framework reflect-metadata tsyringe zod uuid
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This framework uses TypeScript decorators. Ensure your project has decorators enabled.
|
|
31
|
+
|
|
32
|
+
## Imports and entry points
|
|
33
|
+
|
|
34
|
+
The package exposes subpath entry points:
|
|
35
|
+
|
|
36
|
+
- `@open-core/framework` (root)
|
|
37
|
+
- `@open-core/framework/server`
|
|
38
|
+
- `@open-core/framework/client`
|
|
39
|
+
- `@open-core/framework/shared`
|
|
40
|
+
- `@open-core/framework/utils`
|
|
41
|
+
|
|
42
|
+
Most projects will import the `Server`/`Client` namespaces:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { Server } from '@open-core/framework'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Architecture
|
|
49
|
+
|
|
50
|
+
OpenCore follows a Ports & Adapters (Hexagonal) architecture.
|
|
51
|
+
|
|
52
|
+
- Kernel (`src/kernel`): engine-agnostic infrastructure (DI, logger, metadata scanning)
|
|
53
|
+
- Runtime (`src/runtime`): multiplayer execution model (controllers, processors, security, lifecycle)
|
|
54
|
+
- Adapters (`src/adapters`): platform integration (FiveM, Node testing)
|
|
55
|
+
|
|
56
|
+
The runtime never auto-detects the platform. Adapters are selected explicitly at bootstrap time.
|
|
57
|
+
|
|
58
|
+
## Operating modes
|
|
59
|
+
|
|
60
|
+
Each instance runs in exactly one mode configured via `Server.init()`:
|
|
61
|
+
|
|
62
|
+
- `CORE`: authoritative runtime. Typically provides identity/auth/players via exports.
|
|
63
|
+
- `RESOURCE`: a normal FiveM resource using CORE as provider for some features.
|
|
64
|
+
- `STANDALONE`: a self-contained runtime (useful for tooling, simulations, or small servers).
|
|
65
|
+
|
|
66
|
+
## Server bootstrap
|
|
67
|
+
|
|
68
|
+
Initialize the server runtime:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { Server } from '@open-core/framework/server'
|
|
72
|
+
|
|
73
|
+
await Server.init({
|
|
74
|
+
mode: 'STANDALONE',
|
|
75
|
+
features: {
|
|
76
|
+
commands: { enabled: true },
|
|
77
|
+
netEvents: { enabled: true },
|
|
78
|
+
},
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Some features require providers (depending on your mode and configuration). Configure them before calling `init()`:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { Server } from '@open-core/framework/server'
|
|
86
|
+
|
|
87
|
+
Server.setPrincipalProvider(MyPrincipalProvider)
|
|
88
|
+
Server.setAuthProvider(MyAuthProvider)
|
|
89
|
+
Server.setSecurityHandler(MySecurityHandler)
|
|
90
|
+
Server.setPersistenceProvider(MyPlayerPersistence)
|
|
91
|
+
Server.setNetEventSecurityObserver(MyNetEventSecurityObserver)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Controllers and decorators
|
|
95
|
+
|
|
96
|
+
OpenCore uses a decorator + processor pattern.
|
|
97
|
+
|
|
98
|
+
Decorators store metadata with `Reflect.defineMetadata()`. During bootstrap, the `MetadataScanner` reads metadata and processors register handlers.
|
|
99
|
+
|
|
100
|
+
### Commands
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { Server } from '@open-core/framework/server'
|
|
104
|
+
import { z } from 'zod'
|
|
105
|
+
|
|
106
|
+
const TransferSchema = z.tuple([z.coerce.number().int().positive(), z.coerce.number().min(1)])
|
|
107
|
+
|
|
108
|
+
@Server.Controller()
|
|
109
|
+
export class BankController {
|
|
110
|
+
@Server.Command({
|
|
111
|
+
command: 'transfer',
|
|
112
|
+
usage: '/transfer <id> <amount>',
|
|
113
|
+
schema: TransferSchema,
|
|
114
|
+
})
|
|
115
|
+
@Server.Guard({ rank: 1 })
|
|
116
|
+
@Server.Throttle(1, 2000)
|
|
117
|
+
async transfer(player: Server.Player, args: z.infer<typeof TransferSchema>) {
|
|
118
|
+
const [targetId, amount] = args
|
|
119
|
+
player.emit('chat:message', `transfer -> ${targetId} (${amount})`)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Network events
|
|
125
|
+
|
|
126
|
+
`@OnNet()` handlers always receive `Player` as the first parameter.
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { Server } from '@open-core/framework/server'
|
|
130
|
+
import { z } from 'zod'
|
|
131
|
+
|
|
132
|
+
const PayloadSchema = z.object({ action: z.string(), amount: z.number().int().positive() })
|
|
133
|
+
|
|
134
|
+
@Server.Controller()
|
|
135
|
+
export class ExampleNetController {
|
|
136
|
+
@Server.OnNet('bank:action', { schema: PayloadSchema })
|
|
137
|
+
async onBankAction(player: Server.Player, payload: z.infer<typeof PayloadSchema>) {
|
|
138
|
+
player.emit('chat:message', `action=${payload.action} amount=${payload.amount}`)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Security decorators
|
|
144
|
+
|
|
145
|
+
- `@Guard({ rank })` or `@Guard({ permission })`
|
|
146
|
+
- `@Throttle(limit, windowMs)`
|
|
147
|
+
- `@RequiresState({ missing: [...] })`
|
|
148
|
+
|
|
149
|
+
## Testing
|
|
150
|
+
|
|
151
|
+
Tests run with Vitest.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pnpm test
|
|
155
|
+
pnpm test:unit
|
|
156
|
+
pnpm test:integration
|
|
157
|
+
pnpm test:coverage
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Note: `pnpm test` does not run benchmarks.
|
|
161
|
+
|
|
162
|
+
## Benchmarks
|
|
163
|
+
|
|
164
|
+
There are two benchmark suites:
|
|
165
|
+
|
|
166
|
+
- Core benchmarks (Tinybench)
|
|
167
|
+
- Load benchmarks (Vitest project `benchmark`)
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pnpm bench:core
|
|
171
|
+
pnpm bench:load
|
|
172
|
+
pnpm bench:all
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Snapshot (latest local run)
|
|
176
|
+
|
|
177
|
+
These values are a small extract from a recent local run (Dec 22, 2025). Results vary by machine.
|
|
178
|
+
|
|
179
|
+
- **Core**
|
|
180
|
+
- Decorators - Define metadata (Command): `~5.72M ops/sec` (mean `0.17μs`)
|
|
181
|
+
- EventBus - Multiple event types: `~2.01M ops/sec` (mean `0.50μs`)
|
|
182
|
+
- Dependency Injection (simple resolve): `~1.7M ops/sec`
|
|
183
|
+
- **Load**
|
|
184
|
+
- Net Events - Simple (10 players): `~28.85K ops/sec` (p95 `0.25ms`)
|
|
185
|
+
- Net Events - Concurrent (500 players): `~1.18M ops/sec` (p95 `0.40ms`)
|
|
186
|
+
- Commands (validated, ~500 players): `~14M ops/sec`
|
|
187
|
+
|
|
188
|
+
Full reports and methodology are available in benchmark/README.md.
|
|
189
|
+
|
|
190
|
+
### Reports
|
|
191
|
+
|
|
192
|
+
Benchmark reports are generated under `benchmark/reports/`.
|
|
193
|
+
|
|
194
|
+
- `pnpm bench:all` generates aggregated reports (text/json/html)
|
|
195
|
+
- Load metrics used by load benchmarks are persisted in `benchmark/reports/.load-metrics.json`
|
|
196
|
+
|
|
197
|
+
For details about the benchmark system, see `benchmark/README.md`.
|
|
198
|
+
|
|
199
|
+
## Development scripts
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
pnpm build
|
|
203
|
+
pnpm watch
|
|
204
|
+
pnpm lint
|
|
205
|
+
pnpm lint:fix
|
|
206
|
+
pnpm format
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Ecosystem
|
|
210
|
+
|
|
211
|
+
OpenCore is designed to be extended via separate packages/resources.
|
|
212
|
+
|
|
213
|
+
- `@open-core/identity`: identity and permission system
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
MPL-2.0. See `LICENSE`.
|
|
@@ -68,6 +68,9 @@ let NodeEntityServer = class NodeEntityServer extends IEntityServer_1.IEntitySer
|
|
|
68
68
|
this.stateBags.set(handle, new Map());
|
|
69
69
|
}
|
|
70
70
|
const bag = this.stateBags.get(handle);
|
|
71
|
+
if (!bag) {
|
|
72
|
+
throw new Error(`[OpenCore] NodeEntityServer state bag missing for handle ${handle}`);
|
|
73
|
+
}
|
|
71
74
|
return {
|
|
72
75
|
set: (key, value) => {
|
|
73
76
|
bag.set(key, value);
|
|
@@ -5,7 +5,7 @@ import { IExports } from '../contracts/IExports';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare class NodeExports implements IExports {
|
|
7
7
|
private exports;
|
|
8
|
-
register(exportName: string, handler:
|
|
8
|
+
register(exportName: string, handler: (...args: any[]) => any): void;
|
|
9
9
|
getResource(resourceName: string): any;
|
|
10
10
|
/**
|
|
11
11
|
* Get all registered exports as an object
|
|
@@ -18,7 +18,7 @@ export declare class NodeExports implements IExports {
|
|
|
18
18
|
/**
|
|
19
19
|
* Utility method for testing: get a specific export
|
|
20
20
|
*/
|
|
21
|
-
getExport(exportName: string):
|
|
21
|
+
getExport(exportName: string): ((...args: any[]) => any) | undefined;
|
|
22
22
|
/**
|
|
23
23
|
* Utility method for testing: clear all exports
|
|
24
24
|
*/
|
|
@@ -129,6 +129,10 @@ let AppearanceService = class AppearanceService {
|
|
|
129
129
|
components: {},
|
|
130
130
|
props: {},
|
|
131
131
|
};
|
|
132
|
+
if (!appearance.components)
|
|
133
|
+
appearance.components = {};
|
|
134
|
+
if (!appearance.props)
|
|
135
|
+
appearance.props = {};
|
|
132
136
|
// Components (0-11)
|
|
133
137
|
for (let i = 0; i <= 11; i++) {
|
|
134
138
|
const drawable = this.pedAdapter.getDrawableVariation(ped, i);
|
|
@@ -37,8 +37,8 @@ exports.initServer = initServer;
|
|
|
37
37
|
const register_capabilities_1 = require("../../adapters/register-capabilities");
|
|
38
38
|
const index_1 = require("../../kernel/di/index");
|
|
39
39
|
const logger_1 = require("../../kernel/shared/logger");
|
|
40
|
-
const index_2 = require("./contracts/index");
|
|
41
40
|
const bootstrap_validation_1 = require("./bootstrap.validation");
|
|
41
|
+
const index_2 = require("./contracts/index");
|
|
42
42
|
const controller_1 = require("./decorators/controller");
|
|
43
43
|
const runtime_1 = require("./runtime");
|
|
44
44
|
const services_register_1 = require("./services/services.register");
|
|
@@ -84,6 +84,8 @@ function validatePersistence() {
|
|
|
84
84
|
if (!parsed.success)
|
|
85
85
|
return zodIssuesToLines('persistence', parsed.error);
|
|
86
86
|
if (adapter === 'resource') {
|
|
87
|
+
if (!resourceName)
|
|
88
|
+
return ['persistence.resourceName: Missing opencore_db_resource'];
|
|
87
89
|
const db = exports[resourceName];
|
|
88
90
|
if (!db) {
|
|
89
91
|
return [
|
|
@@ -5,8 +5,11 @@ exports.emitFrameworkEvent = emitFrameworkEvent;
|
|
|
5
5
|
const logger_1 = require("../../../kernel/shared/logger");
|
|
6
6
|
const handlers = {};
|
|
7
7
|
function onFrameworkEvent(event, handler) {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
let list = handlers[event];
|
|
9
|
+
if (!list) {
|
|
10
|
+
list = [];
|
|
11
|
+
handlers[event] = list;
|
|
12
|
+
}
|
|
10
13
|
list.push(handler);
|
|
11
14
|
return () => {
|
|
12
15
|
const index = list.indexOf(handler);
|
|
@@ -16,8 +16,8 @@ exports.PrincipalExportController = void 0;
|
|
|
16
16
|
const tsyringe_1 = require("tsyringe");
|
|
17
17
|
const utils_1 = require("../../../kernel/utils");
|
|
18
18
|
const index_1 = require("../contracts/index");
|
|
19
|
-
const index_2 = require("../decorators/index");
|
|
20
19
|
const export_1 = require("../decorators/export");
|
|
20
|
+
const index_2 = require("../decorators/index");
|
|
21
21
|
const player_directory_port_1 = require("../services/ports/player-directory.port");
|
|
22
22
|
/**
|
|
23
23
|
* Exports principal/permission functionality for RESOURCE mode access.
|
|
@@ -43,6 +43,7 @@ const metadata_server_keys_1 = require("../system/metadata-server.keys");
|
|
|
43
43
|
*/
|
|
44
44
|
function Throttle(optionsOrLimit, windowMs) {
|
|
45
45
|
return (target, propertyKey, descriptor) => {
|
|
46
|
+
var _a;
|
|
46
47
|
if (!descriptor) {
|
|
47
48
|
// In benchmarks or edge cases, skip method wrapping
|
|
48
49
|
// This should NOT happen in production code with proper TypeScript compilation
|
|
@@ -57,6 +58,7 @@ function Throttle(optionsOrLimit, windowMs) {
|
|
|
57
58
|
else {
|
|
58
59
|
opts = Object.assign({ onExceed: 'LOG' }, optionsOrLimit);
|
|
59
60
|
}
|
|
61
|
+
const onExceed = (_a = opts.onExceed) !== null && _a !== void 0 ? _a : 'LOG';
|
|
60
62
|
// Store metadata for remote transmission
|
|
61
63
|
Reflect.defineMetadata(metadata_server_keys_1.METADATA_KEYS.THROTTLE, opts, target, propertyKey);
|
|
62
64
|
descriptor.value = async function (...args) {
|
|
@@ -65,7 +67,7 @@ function Throttle(optionsOrLimit, windowMs) {
|
|
|
65
67
|
const service = tsyringe_1.container.resolve(rate_limiter_service_1.RateLimiterService);
|
|
66
68
|
const key = `${player.clientID}:${target.constructor.name}:${propertyKey}`;
|
|
67
69
|
if (!service.checkLimit(key, opts.limit, opts.windowMs)) {
|
|
68
|
-
throw new security_error_1.SecurityError(
|
|
70
|
+
throw new security_error_1.SecurityError(onExceed, opts.message || `Rate limit exceeded on ${propertyKey}`, { limit: opts.limit, key });
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
return originalMethod.apply(this, args);
|
|
@@ -3,4 +3,4 @@ import { Player } from '../entities';
|
|
|
3
3
|
/**
|
|
4
4
|
* Centraliza validación de argumentos de comandos.
|
|
5
5
|
*/
|
|
6
|
-
export declare function validateAndExecuteCommand(meta: CommandMetadata, player: Player, args: string[], handler:
|
|
6
|
+
export declare function validateAndExecuteCommand(meta: CommandMetadata, player: Player, args: string[], handler: (...args: any[]) => any): Promise<any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function getParameterNames(func:
|
|
1
|
+
export declare function getParameterNames(func: (...args: any[]) => any): string[];
|
|
@@ -22,7 +22,7 @@ export declare class CommandService extends CommandExecutionPort {
|
|
|
22
22
|
* @param meta - Command metadata collected from the {@link Command} decorator.
|
|
23
23
|
* @param handler - The bound method to invoke.
|
|
24
24
|
*/
|
|
25
|
-
register(meta: CommandMetadata, handler:
|
|
25
|
+
register(meta: CommandMetadata, handler: (...args: any[]) => any): void;
|
|
26
26
|
/**
|
|
27
27
|
* Executes a registered command.
|
|
28
28
|
*
|
|
@@ -305,12 +305,16 @@ class WorkerPool extends SimpleEventEmitter {
|
|
|
305
305
|
const idleWorker = this.findIdleWorker();
|
|
306
306
|
if (idleWorker) {
|
|
307
307
|
const task = this.taskQueue.shift();
|
|
308
|
+
if (!task)
|
|
309
|
+
break;
|
|
308
310
|
this.assignTask(idleWorker, task);
|
|
309
311
|
}
|
|
310
312
|
else if (this.workers.size < this.config.maxWorkers) {
|
|
311
313
|
const newWorker = this.spawnWorker();
|
|
312
314
|
if (newWorker) {
|
|
313
315
|
const task = this.taskQueue.shift();
|
|
316
|
+
if (!task)
|
|
317
|
+
break;
|
|
314
318
|
this.assignTask(newWorker, task);
|
|
315
319
|
}
|
|
316
320
|
else {
|
|
@@ -25,7 +25,7 @@ export declare abstract class CommandExecutionPort {
|
|
|
25
25
|
* @param metadata - Command metadata from decorator
|
|
26
26
|
* @param handler - Bound method to invoke when command is executed
|
|
27
27
|
*/
|
|
28
|
-
abstract register(metadata: CommandMetadata, handler:
|
|
28
|
+
abstract register(metadata: CommandMetadata, handler: (...args: any[]) => any): void;
|
|
29
29
|
/**
|
|
30
30
|
* Executes a registered command.
|
|
31
31
|
*
|
|
@@ -36,7 +36,7 @@ export declare class RemoteCommandService extends CommandExecutionPort {
|
|
|
36
36
|
* The handler and full metadata are stored locally for schema validation.
|
|
37
37
|
* Only serializable metadata is sent to CORE for security validation.
|
|
38
38
|
*/
|
|
39
|
-
register(metadata: CommandMetadata, handler:
|
|
39
|
+
register(metadata: CommandMetadata, handler: (...args: any[]) => any): void;
|
|
40
40
|
/**
|
|
41
41
|
* Executes a command handler stored in this resource.
|
|
42
42
|
*
|
|
@@ -9,13 +9,13 @@ const player_service_1 = require("./core/player.service");
|
|
|
9
9
|
const principal_service_1 = require("./core/principal.service");
|
|
10
10
|
const http_service_1 = require("./http/http.service");
|
|
11
11
|
const persistence_service_1 = require("./persistence.service");
|
|
12
|
-
const
|
|
12
|
+
const command_execution_port_1 = require("./ports/command-execution.port");
|
|
13
13
|
const player_directory_port_1 = require("./ports/player-directory.port");
|
|
14
|
+
const player_session_lifecycle_port_1 = require("./ports/player-session-lifecycle.port");
|
|
14
15
|
const principal_port_1 = require("./ports/principal.port");
|
|
15
16
|
const remote_command_service_1 = require("./remote/remote-command.service");
|
|
16
17
|
const remote_player_service_1 = require("./remote/remote-player.service");
|
|
17
18
|
const remote_principal_service_1 = require("./remote/remote-principal.service");
|
|
18
|
-
const command_execution_port_1 = require("./ports/command-execution.port");
|
|
19
19
|
/**
|
|
20
20
|
* Registers server runtime services in the dependency injection container.
|
|
21
21
|
*
|