-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a474aec
commit edee780
Showing
29 changed files
with
2,346 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/dist/ | ||
/node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "@bitlerjs/nexus-notifications", | ||
"version": "1.0.0", | ||
"main": "dist/exports.js", | ||
"type": "module", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"build": "tsc --build", | ||
"dev": "tsc --build --watch" | ||
}, | ||
"devDependencies": { | ||
"@bitlerjs/nexus-config": "workspace:*", | ||
"typescript": "^5.7.2" | ||
}, | ||
"dependencies": { | ||
"@bitlerjs/nexus": "workspace:*", | ||
"@bitlerjs/nexus-data": "workspace:*", | ||
"nanoid": "^5.0.9" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { createDatabase, createMigration } from '@bitlerjs/nexus-data'; | ||
|
||
const init = createMigration({ | ||
name: 'init', | ||
up: async (knex) => { | ||
await knex.schema.createTable('notifications', (table) => { | ||
table.string('id').primary(); | ||
table.string('title').notNullable(); | ||
table.string('message').notNullable(); | ||
table.timestamp('createdAt').defaultTo(knex.fn.now()); | ||
}); | ||
|
||
await knex.schema.createTable('notificationActions', (table) => { | ||
table.string('id').primary(); | ||
table.string('title').notNullable(); | ||
table.string('description').nullable(); | ||
table.string('notificationId').notNullable().references('id').inTable('notifications').onDelete('CASCADE'); | ||
table.string('kind').notNullable(); | ||
table.boolean('removeNotification').defaultTo(false); | ||
table.json('data').notNullable(); | ||
}); | ||
|
||
await knex.schema.createTable('notificationEntities', (table) => { | ||
table.string('notificationId').notNullable().references('id').inTable('notifications').onDelete('CASCADE'); | ||
table.string('kind').notNullable(); | ||
table.string('role').nullable(); | ||
table.string('entityId').notNullable(); | ||
table.primary(['notificationId', 'kind', 'entityId']); | ||
}); | ||
}, | ||
down: async (knex) => { | ||
await knex.schema.dropTable('notificationEntities'); | ||
await knex.schema.dropTable('notificationActions'); | ||
await knex.schema.dropTable('notifications'); | ||
}, | ||
}); | ||
|
||
const dbConfig = createDatabase({ | ||
name: 'notifications', | ||
migrations: [init], | ||
}); | ||
|
||
export { dbConfig }; |
29 changes: 29 additions & 0 deletions
29
extensions/nexus-notifications/src/events/events.created.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { createEvent, Type } from '@bitlerjs/nexus'; | ||
|
||
const notificationCreatedEvent = createEvent({ | ||
kind: 'notification.created', | ||
name: 'Notification created', | ||
description: 'A notification was created', | ||
input: Type.Object({}), | ||
output: Type.Object({ | ||
id: Type.String(), | ||
title: Type.String(), | ||
message: Type.String(), | ||
entities: Type.Array( | ||
Type.Object({ | ||
kind: Type.String(), | ||
id: Type.String(), | ||
role: Type.Optional(Type.String()), | ||
}), | ||
), | ||
actions: Type.Array( | ||
Type.Object({ | ||
id: Type.String(), | ||
title: Type.String(), | ||
description: Type.Optional(Type.String()), | ||
}), | ||
), | ||
}), | ||
}); | ||
|
||
export { notificationCreatedEvent }; |
18 changes: 18 additions & 0 deletions
18
extensions/nexus-notifications/src/events/events.removed.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { createEvent, Type } from '@bitlerjs/nexus'; | ||
|
||
const notificationRemovedEvent = createEvent({ | ||
kind: 'notification.removed', | ||
name: 'Notification Removed', | ||
description: 'A notification was removed', | ||
input: Type.Object({ | ||
ids: Type.Optional(Type.Array(Type.String())), | ||
}), | ||
output: Type.Object({ | ||
id: Type.String(), | ||
}), | ||
filter: async ({ input, event }) => { | ||
return input.ids?.includes(event.id) || false; | ||
}, | ||
}); | ||
|
||
export { notificationRemovedEvent }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { createExtension, EventsService, TasksService } from '@bitlerjs/nexus'; | ||
|
||
import { notificationRemovedEvent } from './events/events.removed.js'; | ||
import { notificationCreatedEvent } from './events/events.created.js'; | ||
import { addNotificationTask } from './tasks/tasks.add.js'; | ||
import { listNotificationTask } from './tasks/tasks.list.js'; | ||
import { removeNotificationsTask } from './tasks/tasks.remove.js'; | ||
import { runNotificationActionTask } from './tasks/tasks.run-action.js'; | ||
|
||
const tasks = { | ||
addNotification: addNotificationTask, | ||
listNotifications: listNotificationTask, | ||
removeNotifications: removeNotificationsTask, | ||
runNotificationAction: runNotificationActionTask, | ||
}; | ||
|
||
const events = [notificationRemovedEvent, notificationCreatedEvent]; | ||
const notifications = createExtension({ | ||
setup: async ({ container }) => { | ||
const tasksService = container.get(TasksService); | ||
tasksService.register(Object.values(tasks)); | ||
|
||
const eventsService = container.get(EventsService); | ||
eventsService.register(Object.values(events)); | ||
}, | ||
}); | ||
|
||
export { notifications, tasks, events }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { EventsService, Type, createTask } from '@bitlerjs/nexus'; | ||
import { nanoid } from 'nanoid'; | ||
import { Databases } from '@bitlerjs/nexus-data'; | ||
|
||
import { dbConfig } from '../databases/databases.js'; | ||
import { notificationCreatedEvent } from '../events/events.created.js'; | ||
|
||
const addNotificationTask = createTask({ | ||
kind: 'notification.add', | ||
name: 'Add notification', | ||
description: 'Add a notification', | ||
input: Type.Object({ | ||
id: Type.Optional(Type.String()), | ||
title: Type.String(), | ||
message: Type.String(), | ||
entities: Type.Optional( | ||
Type.Array( | ||
Type.Object({ | ||
kind: Type.String(), | ||
id: Type.String(), | ||
rolw: Type.Optional(Type.String()), | ||
}), | ||
), | ||
), | ||
actions: Type.Optional( | ||
Type.Array( | ||
Type.Object({ | ||
title: Type.String(), | ||
description: Type.Optional(Type.String()), | ||
kind: Type.String(), | ||
removeNotification: Type.Optional(Type.Boolean()), | ||
data: Type.Unknown(), | ||
}), | ||
), | ||
), | ||
}), | ||
output: Type.Object({ | ||
id: Type.String(), | ||
}), | ||
handler: async ({ input, container }) => { | ||
const dbs = container.get(Databases); | ||
const eventsService = container.get(EventsService); | ||
const db = await dbs.get(dbConfig); | ||
const id = input.id || nanoid(); | ||
const actions = input.actions?.map((action) => ({ | ||
id, | ||
title: action.title, | ||
description: action.description, | ||
kind: action.kind, | ||
removeNotification: action.removeNotification || false, | ||
data: action.data, | ||
})); | ||
|
||
await db.transaction(async (trx) => { | ||
await trx('notifications') | ||
.insert({ | ||
id, | ||
title: input.title, | ||
message: input.message, | ||
}) | ||
.onConflict('id') | ||
.merge(); | ||
|
||
await trx('notificationActions').where('notificationId', id).delete(); | ||
await trx('notificationEntities').where('notificationId', id).delete(); | ||
|
||
if (actions) { | ||
await trx('notificationActions').insert(actions); | ||
} | ||
|
||
if (input.entities) { | ||
await trx('notificationEntities').insert(input.entities.map((entity) => ({ ...entity, notificationId: id }))); | ||
} | ||
}); | ||
|
||
eventsService.emit(notificationCreatedEvent, { | ||
id, | ||
title: input.title, | ||
message: input.message, | ||
actions: actions || [], | ||
entities: input.entities || [], | ||
}); | ||
|
||
return { id }; | ||
}, | ||
}); | ||
|
||
export { addNotificationTask }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { createTask, Type } from '@bitlerjs/nexus'; | ||
import { Databases } from '@bitlerjs/nexus-data'; | ||
|
||
import { dbConfig } from '../databases/databases.js'; | ||
|
||
const listNotificationTask = createTask({ | ||
kind: 'notification.list', | ||
name: 'List', | ||
group: 'Notification', | ||
description: 'List notifications', | ||
input: Type.Object({}), | ||
output: Type.Object({ | ||
notifications: Type.Array( | ||
Type.Object({ | ||
id: Type.String(), | ||
title: Type.String(), | ||
message: Type.String(), | ||
createdAt: Type.String(), | ||
actions: Type.Array( | ||
Type.Object({ | ||
id: Type.String(), | ||
title: Type.String(), | ||
description: Type.Optional(Type.String()), | ||
kind: Type.String(), | ||
removeNotification: Type.Optional(Type.Boolean()), | ||
data: Type.Unknown(), | ||
}), | ||
), | ||
}), | ||
), | ||
}), | ||
handler: async ({ container }) => { | ||
const dbs = container.get(Databases); | ||
const db = await dbs.get(dbConfig); | ||
|
||
const notifications = await db('notifications').select('*'); | ||
const actions = await db('notificationActions').select('*'); | ||
|
||
const result = notifications.map((notification) => ({ | ||
...notification, | ||
actions: actions.filter((action) => action.notificationId === notification.id), | ||
})); | ||
|
||
return { notifications: result }; | ||
}, | ||
}); | ||
|
||
export { listNotificationTask }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { createTask, EventsService, Type } from '@bitlerjs/nexus'; | ||
import { Databases } from '@bitlerjs/nexus-data'; | ||
|
||
import { dbConfig } from '../databases/databases.js'; | ||
import { notificationRemovedEvent } from '../events/events.removed.js'; | ||
|
||
const removeNotificationsTask = createTask({ | ||
kind: 'notification.remove', | ||
name: 'Remove', | ||
group: 'Notification', | ||
description: 'Remove a notification', | ||
input: Type.Object({ | ||
ids: Type.Array(Type.String()), | ||
}), | ||
output: Type.Object({ | ||
success: Type.Boolean(), | ||
}), | ||
handler: async ({ input, container }) => { | ||
const dbs = container.get(Databases); | ||
const eventsService = container.get(EventsService); | ||
const db = await dbs.get(dbConfig); | ||
|
||
await db.transaction(async (trx) => { | ||
await trx('notifications').whereIn('id', input.ids).delete(); | ||
}); | ||
|
||
input.ids.forEach((id) => { | ||
eventsService.emit(notificationRemovedEvent, { id }); | ||
}); | ||
|
||
return { success: true }; | ||
}, | ||
}); | ||
|
||
export { removeNotificationsTask }; |
Oops, something went wrong.