@xrengine/server-core
Version:
Shared components for XREngine server
141 lines (122 loc) • 3.55 kB
text/typescript
import { Params } from '@feathersjs/feathers/lib'
import { LocationInterface } from '@xrengine/common/src/dbmodels/Location'
import { Instance as InstanceInterface } from '@xrengine/common/src/interfaces/Instance'
import { Application } from '../../../declarations'
import authenticate from '../../hooks/authenticate'
import verifyScope from '../../hooks/verify-scope'
import logger from '../../ServerLogger'
import { Instance } from './instance.class'
import instanceDocs from './instance.docs'
import hooks from './instance.hooks'
import createModel from './instance.model'
declare module '@xrengine/common/declarations' {
interface ServiceTypes {
instance: Instance
'instances-active': {
find: ReturnType<typeof getActiveInstancesForScene>
}
}
}
type ActiveInstance = {
id: string
location: string
currentUsers: number
}
// TODO: paginate this
export const getActiveInstancesForScene =
(app: Application) =>
async (params: Params & { query: { sceneId: string } }): Promise<ActiveInstance[]> => {
const sceneId = params.query!.sceneId
if (!sceneId) return []
// get all locationIds for sceneId
const locations = (await app.service('location').Model.findAll({
where: {
sceneId
}
})) as LocationInterface[]
if (!locations) return []
const instances = (
(await Promise.all(
locations.map((location) => {
return app.service('instance').Model.findAll({
where: {
ended: false,
locationId: location.id
},
include: [
{
model: app.service('location').Model,
where: {}
}
]
})
})
)) as InstanceInterface[]
).flat()
// return all active instances for each location
const instancesData: ActiveInstance[] = instances
.map((instance) => {
return {
id: instance.id,
location: instance.location!.id,
currentUsers: instance.currentUsers
}
})
.filter((a) => !!a)
return instancesData
}
export default (app: Application) => {
const options = {
Model: createModel(app),
paginate: app.get('paginate'),
multi: true
}
/**
* Initialize our service with any options it requires and docs
*/
const event = new Instance(options, app)
event.docs = instanceDocs
app.use('instance', event)
const service = app.service('instance')
service.hooks(hooks)
/**
* A method used to remove specific instance
*
* @param data
* @returns deleted channel
*/
service.publish('removed', async (data): Promise<any> => {
try {
const admins = await app.service('user').Model.findAll({
include: [
{
model: app.service('scope').Model,
where: {
type: 'admin:admin'
}
}
]
})
const targetIds = admins.map((admin) => admin.id)
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return await Promise.all(
targetIds.map((userId: string) => {
return app.channel(`userIds/${userId}`).send({
instance: data
})
})
)
} catch (err) {
logger.error(err)
throw err
}
})
app.use('instances-active', {
find: getActiveInstancesForScene(app)
})
app.service('instances-active').hooks({
before: {
find: [authenticate(), verifyScope('editor', 'write')]
}
})
}