diff --git a/Documentation.md b/Documentation.md index dc21246..afaf2fe 100644 --- a/Documentation.md +++ b/Documentation.md @@ -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. diff --git a/core/core-server.ts b/core/core-server.ts index 4306a39..51f56fd 100644 --- a/core/core-server.ts +++ b/core/core-server.ts @@ -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 { diff --git a/core/package-lock.json b/core/package-lock.json index 96a4daa..3f67a48 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -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", diff --git a/core/package.json b/core/package.json index d074a1b..69f2ef7 100644 --- a/core/package.json +++ b/core/package.json @@ -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", diff --git a/core/types.d.ts b/core/types.d.ts index c8de101..e4c40e4 100644 --- a/core/types.d.ts +++ b/core/types.d.ts @@ -36,6 +36,8 @@ type ServerHookDefinitions = { msg?: (caller_client: SocioSession, kind: ServerMessageKind, data: MessageDataObj) => boolean | void | Promise | Promise, sub?: (caller_client: SocioSession, kind: ServerMessageKind, data: MessageDataObj) => boolean | Promise, unsub?: (caller_client: SocioSession, kind: ServerMessageKind, data: MessageDataObj) => boolean | Promise, + reg_prop?: (key: PropKey, data: { reason: string, opts: PropOpts }) => void, + unreg_prop?: (key: PropKey, data: { reason: string }) => void, upd?: (sessions: Map, initiator: SocioSession, sql: string, params: object | null) => boolean | Promise, auth?: (caller_client: SocioSession, params: object | null) => boolean | Promise, gen_client_id?: () => ClientID | Promise,