@dudousxd/nestjs-notifications-database 0.1.0
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/dist/database.channel.d.ts +15 -0
- package/dist/database.channel.d.ts.map +1 -0
- package/dist/database.channel.js +71 -0
- package/dist/database.channel.js.map +1 -0
- package/dist/database.module.d.ts +24 -0
- package/dist/database.module.d.ts.map +1 -0
- package/dist/database.module.js +52 -0
- package/dist/database.module.js.map +1 -0
- package/dist/in-memory.store.d.ts +13 -0
- package/dist/in-memory.store.d.ts.map +1 -0
- package/dist/in-memory.store.js +64 -0
- package/dist/in-memory.store.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +41 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +3 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/tokens.d.ts +3 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +6 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +32 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ChannelDriver, Notifiable, Notification } from '@dudousxd/nestjs-notifications-core';
|
|
2
|
+
import type { NotificationStore } from './interfaces';
|
|
3
|
+
/**
|
|
4
|
+
* Persists notifications via a {@link NotificationStore} so they can be shown in-app.
|
|
5
|
+
* Reads the payload from `toDatabase()`, then `toArray()`, then a structural copy.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DatabaseChannel implements ChannelDriver {
|
|
8
|
+
private readonly store;
|
|
9
|
+
readonly channel = "database";
|
|
10
|
+
constructor(store: NotificationStore);
|
|
11
|
+
send(notifiable: Notifiable, notification: Notification): Promise<void>;
|
|
12
|
+
private referenceFor;
|
|
13
|
+
private payloadFor;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=database.channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.channel.d.ts","sourceRoot":"","sources":["../src/database.channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EAEV,YAAY,EACb,MAAM,qCAAqC,CAAC;AAE7C,OAAO,KAAK,EAAwB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAG5E;;;GAGG;AACH,qBACa,eAAgB,YAAW,aAAa;IAKjD,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJxB,QAAQ,CAAC,OAAO,cAAc;gBAIX,KAAK,EAAE,iBAAiB;IAGrC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAe7E,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,UAAU;CASnB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.DatabaseChannel = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const tokens_1 = require("./tokens");
|
|
18
|
+
/**
|
|
19
|
+
* Persists notifications via a {@link NotificationStore} so they can be shown in-app.
|
|
20
|
+
* Reads the payload from `toDatabase()`, then `toArray()`, then a structural copy.
|
|
21
|
+
*/
|
|
22
|
+
let DatabaseChannel = class DatabaseChannel {
|
|
23
|
+
store;
|
|
24
|
+
channel = 'database';
|
|
25
|
+
constructor(store) {
|
|
26
|
+
this.store = store;
|
|
27
|
+
}
|
|
28
|
+
async send(notifiable, notification) {
|
|
29
|
+
const ref = this.referenceFor(notifiable, notification);
|
|
30
|
+
const data = this.payloadFor(notifiable, notification);
|
|
31
|
+
const type = notification.constructor.notificationName ??
|
|
32
|
+
notification.constructor.name;
|
|
33
|
+
await this.store.save({
|
|
34
|
+
type,
|
|
35
|
+
notifiableType: ref.type,
|
|
36
|
+
notifiableId: String(ref.id),
|
|
37
|
+
data,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
referenceFor(notifiable, notification) {
|
|
41
|
+
const routed = notifiable.routeNotificationFor('database', notification);
|
|
42
|
+
if (isRef(routed))
|
|
43
|
+
return routed;
|
|
44
|
+
if (typeof notifiable.toNotifiableRef === 'function')
|
|
45
|
+
return notifiable.toNotifiableRef();
|
|
46
|
+
throw new Error('The database channel needs a notifiable reference. Implement toNotifiableRef() on the ' +
|
|
47
|
+
'notifiable, or return { type, id } from routeNotificationFor("database").');
|
|
48
|
+
}
|
|
49
|
+
payloadFor(notifiable, notification) {
|
|
50
|
+
if (typeof notification.toDatabase === 'function')
|
|
51
|
+
return notification.toDatabase(notifiable);
|
|
52
|
+
if (typeof notification.toArray === 'function')
|
|
53
|
+
return notification.toArray(notifiable);
|
|
54
|
+
const { ...rest } = notification;
|
|
55
|
+
return rest;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
exports.DatabaseChannel = DatabaseChannel;
|
|
59
|
+
exports.DatabaseChannel = DatabaseChannel = __decorate([
|
|
60
|
+
(0, common_1.Injectable)(),
|
|
61
|
+
__param(0, (0, common_1.Inject)(tokens_1.NOTIFICATION_STORE)),
|
|
62
|
+
__metadata("design:paramtypes", [Object])
|
|
63
|
+
], DatabaseChannel);
|
|
64
|
+
function isRef(value) {
|
|
65
|
+
return (typeof value === 'object' &&
|
|
66
|
+
value !== null &&
|
|
67
|
+
'type' in value &&
|
|
68
|
+
'id' in value &&
|
|
69
|
+
typeof value.type === 'string');
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=database.channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.channel.js","sourceRoot":"","sources":["../src/database.channel.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAMA,2CAAoD;AAEpD,qCAA8C;AAE9C;;;GAGG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAe;IAKP;IAJV,OAAO,GAAG,UAAU,CAAC;IAE9B,YAEmB,KAAwB;QAAxB,UAAK,GAAL,KAAK,CAAmB;IACxC,CAAC;IAEJ,KAAK,CAAC,IAAI,CAAC,UAAsB,EAAE,YAA0B;QAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACvD,MAAM,IAAI,GACP,YAAY,CAAC,WAA6C,CAAC,gBAAgB;YAC5E,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC;QAEhC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACpB,IAAI;YACJ,cAAc,EAAE,GAAG,CAAC,IAAI;YACxB,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAEO,YAAY,CAAC,UAAsB,EAAE,YAA0B;QACrE,MAAM,MAAM,GAAG,UAAU,CAAC,oBAAoB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACzE,IAAI,KAAK,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACjC,IAAI,OAAO,UAAU,CAAC,eAAe,KAAK,UAAU;YAAE,OAAO,UAAU,CAAC,eAAe,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CACb,wFAAwF;YACtF,2EAA2E,CAC9E,CAAC;IACJ,CAAC;IAEO,UAAU,CAChB,UAAsB,EACtB,YAAkC;QAElC,IAAI,OAAO,YAAY,CAAC,UAAU,KAAK,UAAU;YAAE,OAAO,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC9F,IAAI,OAAO,YAAY,CAAC,OAAO,KAAK,UAAU;YAAE,OAAO,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxF,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,YAAkD,CAAC;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AA1CY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,eAAM,EAAC,2BAAkB,CAAC,CAAA;;GAJlB,eAAe,CA0C3B;AAED,SAAS,KAAK,CAAC,KAAc;IAC3B,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,MAAM,IAAI,KAAK;QACf,IAAI,IAAI,KAAK;QACb,OAAQ,KAAuB,CAAC,IAAI,KAAK,QAAQ,CAClD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type DynamicModule, type Type } from '@nestjs/common';
|
|
2
|
+
import type { NotificationStore } from './interfaces';
|
|
3
|
+
export interface DatabaseChannelOptions {
|
|
4
|
+
/** A store class to instantiate, or omit to use the in-memory store. */
|
|
5
|
+
store?: Type<NotificationStore>;
|
|
6
|
+
/** Register globally so the channel is discoverable app-wide. Default true. */
|
|
7
|
+
global?: boolean;
|
|
8
|
+
/** Extra modules to import (e.g. the ORM module providing the store's dependencies). */
|
|
9
|
+
imports?: DynamicModule['imports'];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Registers the database channel. Pair with an ORM adapter package
|
|
13
|
+
* (`@dudousxd/nestjs-notifications-database-typeorm` or `-mikro-orm`) or pass a custom store.
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* DatabaseChannelModule.forRoot({ store: TypeOrmNotificationStore, imports: [TypeOrmModule.forFeature([...])] })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare class DatabaseChannelModule {
|
|
20
|
+
static forRoot(options?: DatabaseChannelOptions): DynamicModule;
|
|
21
|
+
/** Register with an already-provided store token (e.g. provided by an ORM adapter module). */
|
|
22
|
+
static forFeature(): DynamicModule;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=database.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.module.d.ts","sourceRoot":"","sources":["../src/database.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAyB,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAGtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD,MAAM,WAAW,sBAAsB;IACrC,wEAAwE;IACxE,KAAK,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAChC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,qBACa,qBAAqB;IAChC,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,sBAA2B,GAAG,aAAa;IAgBnE,8FAA8F;IAC9F,MAAM,CAAC,UAAU,IAAI,aAAa;CAOnC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var DatabaseChannelModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.DatabaseChannelModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const database_channel_1 = require("./database.channel");
|
|
13
|
+
const in_memory_store_1 = require("./in-memory.store");
|
|
14
|
+
const tokens_1 = require("./tokens");
|
|
15
|
+
/**
|
|
16
|
+
* Registers the database channel. Pair with an ORM adapter package
|
|
17
|
+
* (`@dudousxd/nestjs-notifications-database-typeorm` or `-mikro-orm`) or pass a custom store.
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* DatabaseChannelModule.forRoot({ store: TypeOrmNotificationStore, imports: [TypeOrmModule.forFeature([...])] })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
let DatabaseChannelModule = DatabaseChannelModule_1 = class DatabaseChannelModule {
|
|
24
|
+
static forRoot(options = {}) {
|
|
25
|
+
const storeClass = options.store ?? in_memory_store_1.InMemoryStore;
|
|
26
|
+
const providers = [
|
|
27
|
+
storeClass,
|
|
28
|
+
{ provide: tokens_1.NOTIFICATION_STORE, useExisting: storeClass },
|
|
29
|
+
database_channel_1.DatabaseChannel,
|
|
30
|
+
];
|
|
31
|
+
return {
|
|
32
|
+
module: DatabaseChannelModule_1,
|
|
33
|
+
global: options.global ?? true,
|
|
34
|
+
imports: options.imports ?? [],
|
|
35
|
+
providers,
|
|
36
|
+
exports: [database_channel_1.DatabaseChannel, tokens_1.NOTIFICATION_STORE],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Register with an already-provided store token (e.g. provided by an ORM adapter module). */
|
|
40
|
+
static forFeature() {
|
|
41
|
+
return {
|
|
42
|
+
module: DatabaseChannelModule_1,
|
|
43
|
+
providers: [database_channel_1.DatabaseChannel],
|
|
44
|
+
exports: [database_channel_1.DatabaseChannel],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
exports.DatabaseChannelModule = DatabaseChannelModule;
|
|
49
|
+
exports.DatabaseChannelModule = DatabaseChannelModule = DatabaseChannelModule_1 = __decorate([
|
|
50
|
+
(0, common_1.Module)({})
|
|
51
|
+
], DatabaseChannelModule);
|
|
52
|
+
//# sourceMappingURL=database.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.module.js","sourceRoot":"","sources":["../src/database.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAsF;AACtF,yDAAqD;AACrD,uDAAkD;AAElD,qCAA8C;AAW9C;;;;;;;GAOG;AAEI,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IAChC,MAAM,CAAC,OAAO,CAAC,UAAkC,EAAE;QACjD,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,IAAI,+BAAa,CAAC;QAClD,MAAM,SAAS,GAAe;YAC5B,UAAU;YACV,EAAE,OAAO,EAAE,2BAAkB,EAAE,WAAW,EAAE,UAAU,EAAE;YACxD,kCAAe;SAChB,CAAC;QACF,OAAO;YACL,MAAM,EAAE,uBAAqB;YAC7B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI;YAC9B,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,SAAS;YACT,OAAO,EAAE,CAAC,kCAAe,EAAE,2BAAkB,CAAC;SAC/C,CAAC;IACJ,CAAC;IAED,8FAA8F;IAC9F,MAAM,CAAC,UAAU;QACf,OAAO;YACL,MAAM,EAAE,uBAAqB;YAC7B,SAAS,EAAE,CAAC,kCAAe,CAAC;YAC5B,OAAO,EAAE,CAAC,kCAAe,CAAC;SAC3B,CAAC;IACJ,CAAC;CACF,CAAA;AAzBY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,qBAAqB,CAyBjC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NewStoredNotification, NotificationStore, StoredNotification } from './interfaces';
|
|
2
|
+
/** In-memory {@link NotificationStore} for tests and prototyping. Not for production. */
|
|
3
|
+
export declare class InMemoryStore implements NotificationStore {
|
|
4
|
+
private readonly rows;
|
|
5
|
+
save(input: NewStoredNotification): Promise<StoredNotification>;
|
|
6
|
+
markAsRead(id: string): Promise<void>;
|
|
7
|
+
markAllAsRead(notifiableType: string, notifiableId: string): Promise<void>;
|
|
8
|
+
getForNotifiable(notifiableType: string, notifiableId: string): Promise<StoredNotification[]>;
|
|
9
|
+
getUnread(notifiableType: string, notifiableId: string): Promise<StoredNotification[]>;
|
|
10
|
+
delete(id: string): Promise<void>;
|
|
11
|
+
private all;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=in-memory.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory.store.d.ts","sourceRoot":"","sources":["../src/in-memory.store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEjG,yFAAyF;AACzF,qBACa,aAAc,YAAW,iBAAiB;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyC;IAExD,IAAI,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgB/D,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrC,aAAa,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1E,gBAAgB,CACpB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAM1B,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAItF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,OAAO,CAAC,GAAG;CAGZ"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.InMemoryStore = void 0;
|
|
10
|
+
const node_crypto_1 = require("node:crypto");
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
/** In-memory {@link NotificationStore} for tests and prototyping. Not for production. */
|
|
13
|
+
let InMemoryStore = class InMemoryStore {
|
|
14
|
+
rows = new Map();
|
|
15
|
+
async save(input) {
|
|
16
|
+
const now = new Date();
|
|
17
|
+
const row = {
|
|
18
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
19
|
+
type: input.type,
|
|
20
|
+
notifiableType: input.notifiableType,
|
|
21
|
+
notifiableId: input.notifiableId,
|
|
22
|
+
data: input.data,
|
|
23
|
+
readAt: null,
|
|
24
|
+
createdAt: now,
|
|
25
|
+
updatedAt: now,
|
|
26
|
+
};
|
|
27
|
+
this.rows.set(row.id, row);
|
|
28
|
+
return row;
|
|
29
|
+
}
|
|
30
|
+
async markAsRead(id) {
|
|
31
|
+
const row = this.rows.get(id);
|
|
32
|
+
if (row && !row.readAt) {
|
|
33
|
+
row.readAt = new Date();
|
|
34
|
+
row.updatedAt = new Date();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async markAllAsRead(notifiableType, notifiableId) {
|
|
38
|
+
for (const row of this.rows.values()) {
|
|
39
|
+
if (row.notifiableType === notifiableType &&
|
|
40
|
+
row.notifiableId === notifiableId &&
|
|
41
|
+
!row.readAt) {
|
|
42
|
+
row.readAt = new Date();
|
|
43
|
+
row.updatedAt = new Date();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async getForNotifiable(notifiableType, notifiableId) {
|
|
48
|
+
return this.all().filter((r) => r.notifiableType === notifiableType && r.notifiableId === notifiableId);
|
|
49
|
+
}
|
|
50
|
+
async getUnread(notifiableType, notifiableId) {
|
|
51
|
+
return (await this.getForNotifiable(notifiableType, notifiableId)).filter((r) => !r.readAt);
|
|
52
|
+
}
|
|
53
|
+
async delete(id) {
|
|
54
|
+
this.rows.delete(id);
|
|
55
|
+
}
|
|
56
|
+
all() {
|
|
57
|
+
return [...this.rows.values()].sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.InMemoryStore = InMemoryStore;
|
|
61
|
+
exports.InMemoryStore = InMemoryStore = __decorate([
|
|
62
|
+
(0, common_1.Injectable)()
|
|
63
|
+
], InMemoryStore);
|
|
64
|
+
//# sourceMappingURL=in-memory.store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory.store.js","sourceRoot":"","sources":["../src/in-memory.store.ts"],"names":[],"mappings":";;;;;;;;;AAAA,6CAAyC;AACzC,2CAA4C;AAG5C,yFAAyF;AAElF,IAAM,aAAa,GAAnB,MAAM,aAAa;IACP,IAAI,GAAG,IAAI,GAAG,EAA8B,CAAC;IAE9D,KAAK,CAAC,IAAI,CAAC,KAA4B;QACrC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAuB;YAC9B,EAAE,EAAE,IAAA,wBAAU,GAAE;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;SACf,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YACvB,GAAG,CAAC,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,cAAsB,EAAE,YAAoB;QAC9D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YACrC,IACE,GAAG,CAAC,cAAc,KAAK,cAAc;gBACrC,GAAG,CAAC,YAAY,KAAK,YAAY;gBACjC,CAAC,GAAG,CAAC,MAAM,EACX,CAAC;gBACD,GAAG,CAAC,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACxB,GAAG,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,cAAsB,EACtB,YAAoB;QAEpB,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CACtB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,cAAc,IAAI,CAAC,CAAC,YAAY,KAAK,YAAY,CAC9E,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,cAAsB,EAAE,YAAoB;QAC1D,OAAO,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9F,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC;IAEO,GAAG;QACT,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/F,CAAC;CACF,CAAA;AA5DY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;GACA,aAAa,CA4DzB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './interfaces';
|
|
2
|
+
export { NOTIFICATION_STORE } from './tokens';
|
|
3
|
+
export { DatabaseChannel } from './database.channel';
|
|
4
|
+
export { InMemoryStore } from './in-memory.store';
|
|
5
|
+
export { DatabaseChannelModule, type DatabaseChannelOptions } from './database.module';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.DatabaseChannelModule = exports.InMemoryStore = exports.DatabaseChannel = exports.NOTIFICATION_STORE = void 0;
|
|
18
|
+
__exportStar(require("./interfaces"), exports);
|
|
19
|
+
var tokens_1 = require("./tokens");
|
|
20
|
+
Object.defineProperty(exports, "NOTIFICATION_STORE", { enumerable: true, get: function () { return tokens_1.NOTIFICATION_STORE; } });
|
|
21
|
+
var database_channel_1 = require("./database.channel");
|
|
22
|
+
Object.defineProperty(exports, "DatabaseChannel", { enumerable: true, get: function () { return database_channel_1.DatabaseChannel; } });
|
|
23
|
+
var in_memory_store_1 = require("./in-memory.store");
|
|
24
|
+
Object.defineProperty(exports, "InMemoryStore", { enumerable: true, get: function () { return in_memory_store_1.InMemoryStore; } });
|
|
25
|
+
var database_module_1 = require("./database.module");
|
|
26
|
+
Object.defineProperty(exports, "DatabaseChannelModule", { enumerable: true, get: function () { return database_module_1.DatabaseChannelModule; } });
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,mCAA8C;AAArC,4GAAA,kBAAkB,OAAA;AAC3B,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AACxB,qDAAkD;AAAzC,gHAAA,aAAa,OAAA;AACtB,qDAAuF;AAA9E,wHAAA,qBAAqB,OAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Notifiable, Notification } from '@dudousxd/nestjs-notifications-core';
|
|
2
|
+
/** A persisted notification row, mirroring Laravel's `notifications` table. */
|
|
3
|
+
export interface StoredNotification {
|
|
4
|
+
id: string;
|
|
5
|
+
/** Notification class name (e.g. "InvoicePaid"). */
|
|
6
|
+
type: string;
|
|
7
|
+
/** Notifiable reference type (e.g. "User"). */
|
|
8
|
+
notifiableType: string;
|
|
9
|
+
/** Notifiable reference id. */
|
|
10
|
+
notifiableId: string;
|
|
11
|
+
/** Arbitrary payload returned by `toDatabase()`. */
|
|
12
|
+
data: Record<string, unknown>;
|
|
13
|
+
readAt: Date | null;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
updatedAt: Date;
|
|
16
|
+
}
|
|
17
|
+
/** Data needed to create a {@link StoredNotification} (id/timestamps assigned by the store). */
|
|
18
|
+
export interface NewStoredNotification {
|
|
19
|
+
type: string;
|
|
20
|
+
notifiableType: string;
|
|
21
|
+
notifiableId: string;
|
|
22
|
+
data: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** Persistence abstraction. Implemented by the in-memory store and ORM adapter packages. */
|
|
25
|
+
export interface NotificationStore {
|
|
26
|
+
save(notification: NewStoredNotification): Promise<StoredNotification>;
|
|
27
|
+
markAsRead(id: string): Promise<void>;
|
|
28
|
+
markAllAsRead(notifiableType: string, notifiableId: string): Promise<void>;
|
|
29
|
+
getForNotifiable(notifiableType: string, notifiableId: string): Promise<StoredNotification[]>;
|
|
30
|
+
getUnread(notifiableType: string, notifiableId: string): Promise<StoredNotification[]>;
|
|
31
|
+
delete(id: string): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Implement this on a notification to define its persisted payload. Falls back to
|
|
35
|
+
* `toArray()` (Laravel parity) and finally to a structural copy.
|
|
36
|
+
*/
|
|
37
|
+
export interface DatabaseNotification extends Notification {
|
|
38
|
+
toDatabase?(notifiable: Notifiable): Record<string, unknown>;
|
|
39
|
+
toArray?(notifiable: Notifiable): Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAEpF,+EAA+E;AAC/E,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,gGAAgG;AAChG,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,4FAA4F;AAC5F,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,YAAY,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACvE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,aAAa,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC9F,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACvF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD,UAAU,CAAC,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":""}
|
package/dist/tokens.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,eAAO,MAAM,kBAAkB,eAA+B,CAAC"}
|
package/dist/tokens.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NOTIFICATION_STORE = void 0;
|
|
4
|
+
/** DI token for the {@link NotificationStore} implementation backing the database channel. */
|
|
5
|
+
exports.NOTIFICATION_STORE = Symbol('NOTIFICATION_STORE');
|
|
6
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":";;;AAAA,8FAA8F;AACjF,QAAA,kBAAkB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dudousxd/nestjs-notifications-database",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Database channel for nestjs-notifications — persist notifications for in-app display",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Davide Carvalho",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/DavideCarvalho/nestjs-notifications.git",
|
|
10
|
+
"directory": "packages/database"
|
|
11
|
+
},
|
|
12
|
+
"type": "commonjs",
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
20
|
+
"@dudousxd/nestjs-notifications-core": "^0.1.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@nestjs/common": "^11.0.0",
|
|
24
|
+
"reflect-metadata": "^0.2.2",
|
|
25
|
+
"typescript": "^5.7.2",
|
|
26
|
+
"@dudousxd/nestjs-notifications-core": "^0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc -p tsconfig.json",
|
|
30
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
31
|
+
}
|
|
32
|
+
}
|