reg_prop & unreg_prop server hooks

This commit is contained in:
Rolands 2026-01-15 11:50:52 +02:00
parent ca5dd88fcb
commit ed5c3dcbd0
5 changed files with 19 additions and 8 deletions

View file

@ -214,6 +214,8 @@ sc.Query('all', {sql_is_endpoint:true, params:{}}, (val) => {
**Awaited** hook: Socio will async await the return value of the hook function, which doesnt have to be async, if it doesnt do any async operations, and all will be fine, bcs JS is lovely.
**Info** hook: Socio will just inform that something has happened. Meant for info logs.
##### SocioServer hooks:
* con [Awaited]: when a new WS/TCP connection with a client is created
* discon [Awaited]: when a session object disconnects (for whatever reason), but is not destroyed (forgotten) yet
@ -227,7 +229,8 @@ sc.Query('all', {sql_is_endpoint:true, params:{}}, (val) => {
* unsub [Interceptable, Awaited]: a client wants to unsubscribe from a query
* upd [Interceptable, Awaited]: works the same as msg, but for every time that updates need to be propogated to all the sockets.
* endpoint [Awaited]: if the client happens to want to use an endpoint keyname instead of SQL, retrieve the SQL string from this hook call.
* reg_prop [info]: a new prop was registered. Gives reason in params
* unreg_prop [info]: a new prop was unregistered. Gives reason in params, i.e. manual, observationaly_temporary, prop_reg_timeout
* gen_client_id [Awaited]: called to generate a unique ID for a client session. By default - UUID4
* gen_prop_name [Awaited]: called to generate a unique ID for a prop name. By default - UUID4. Usually used for generating party game room state prop and codes, when a prop is created client-side.

View file

@ -427,7 +427,7 @@ export class SocioServer extends LogHandler {
// check the prop is observationaly_temporary, meaning should be deleted when there no more subs on it
if (prop?.observationaly_temporary && prop.updates.size === 0) {
this.UnRegisterProp((data as S_PROP_UNSUB_data).prop);
this.UnRegisterProp((data as S_PROP_UNSUB_data).prop, 'observationaly_temporary');
this.HandleDebug('Temporary Prop UNregistered!', (data as S_PROP_UNSUB_data).prop);
}
break;
@ -490,7 +490,7 @@ export class SocioServer extends LogHandler {
if (this.#props.has((data as S_PROP_REG_data).prop as PropKey)) {
// @ts-expect-error
if (this.#props.get((data as S_PROP_REG_data).prop).updates.size === 0) { //if no subs, then delete it
this.UnRegisterProp((data as S_PROP_REG_data).prop as PropKey);
this.UnRegisterProp((data as S_PROP_REG_data).prop as PropKey, 'prop_reg_timeout');
this.HandleDebug(`Temporary Prop UNregistered, because nobody subbed it before prop_reg_timeout_ms (${this.prop_reg_timeout_ms}ms)!`, (data as S_PROP_REG_data).prop);
}
}
@ -851,7 +851,7 @@ export class SocioServer extends LogHandler {
}
//assigner defaults to basic setter
RegisterProp(key: PropKey, val: PropValue, { assigner = this.SetPropVal.bind(this), client_writable = true, send_as_diff = undefined, emit_to_sender = false, observationaly_temporary = false }: { assigner?: PropAssigner } & PropOpts = {}) {
RegisterProp(key: PropKey, val: PropValue, { assigner = this.SetPropVal.bind(this), client_writable = true, send_as_diff = undefined, emit_to_sender = false, observationaly_temporary = false }: { assigner?: PropAssigner } & PropOpts = {}, reason = 'server') {
try {
if (this.#props.has(key))
throw new E(`Prop key [${key}] has already been registered and for client continuity is forbiden to over-write at runtime. [#prop-key-exists]`);
@ -859,10 +859,13 @@ export class SocioServer extends LogHandler {
this.#props.set(key, { val, assigner, updates: new Map(), client_writable, send_as_diff, emit_to_sender, observationaly_temporary });
if (observationaly_temporary)
this.HandleDebug('Temporary Prop registered!', key);
if(this.lifecycle_hooks.reg_prop)
this.lifecycle_hooks.reg_prop(key, { reason, opts: { client_writable, send_as_diff, emit_to_sender, observationaly_temporary } });
} catch (e: err) { this.HandleError(e) }
}
UnRegisterProp(key: PropKey) {
UnRegisterProp(key: PropKey, reason = 'server') {
try {
const prop = this.#props.get(key);
if (!prop) throw new E(`Prop key [${key}] not registered! [#UnRegisterProp-prop-not-found]`);
@ -877,6 +880,9 @@ export class SocioServer extends LogHandler {
this.#sessions.get(client_id)?.Send(ClientMessageKind.PROP_DROP, { id: args.id, prop: key });
else this.#sessions.delete(client_id); //the client_id doesnt exist anymore for some reason, so unsubscribe
}
if(this.lifecycle_hooks.unreg_prop)
this.lifecycle_hooks.unreg_prop(key, { reason });
} catch (e: err) { this.HandleError(e) }
}
GetPropVal(key: PropKey): PropValue | undefined {

View file

@ -1,12 +1,12 @@
{
"name": "socio",
"version": "1.15.11",
"version": "1.15.12",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "socio",
"version": "1.15.11",
"version": "1.15.12",
"license": "MIT",
"dependencies": {
"@msgpack/msgpack": "^3.1.2",

View file

@ -1,6 +1,6 @@
{
"name": "socio",
"version": "1.15.11",
"version": "1.15.12",
"description": "A WebSocket Real-Time Communication (RTC) API framework.",
"main": "./dist/core.js",
"type": "module",

2
core/types.d.ts vendored
View file

@ -36,6 +36,8 @@ type ServerHookDefinitions = {
msg?: (caller_client: SocioSession, kind: ServerMessageKind, data: MessageDataObj) => boolean | void | Promise<boolean> | Promise<void>,
sub?: (caller_client: SocioSession, kind: ServerMessageKind, data: MessageDataObj) => boolean | Promise<boolean>,
unsub?: (caller_client: SocioSession, kind: ServerMessageKind, data: MessageDataObj) => boolean | Promise<boolean>,
reg_prop?: (key: PropKey, data: { reason: string, opts: PropOpts }) => void,
unreg_prop?: (key: PropKey, data: { reason: string }) => void,
upd?: (sessions: Map<ClientID, SocioSession>, initiator: SocioSession, sql: string, params: object | null) => boolean | Promise<boolean>,
auth?: (caller_client: SocioSession, params: object | null) => boolean | Promise<boolean>,
gen_client_id?: () => ClientID | Promise<ClientID>,