@allmightypush/push-storage-mongo 1.0.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/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # @allmightypush/push-storage-mongo
2
+
3
+ MongoDB storage adapter for the push notification library.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @allmightypush/push-storage-mongo @allmightypush/push-core mongodb
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { MongoDBStorageAdapter } from '@allmightypush/push-storage-mongo';
15
+ import { PushCore } from '@allmightypush/push-core';
16
+
17
+ const storage = new MongoDBStorageAdapter({
18
+ uri: 'mongodb://localhost:27017',
19
+ database: 'push_notifications',
20
+ });
21
+
22
+ const pushCore = new PushCore();
23
+ pushCore.configure({
24
+ storageAdapter: storage,
25
+ // ... other configuration
26
+ });
27
+ ```
28
+
29
+ ## Configuration Options
30
+
31
+ ```typescript
32
+ interface MongoDBStorageOptions {
33
+ // Connection URI (required)
34
+ uri: string;
35
+
36
+ // Database name (required)
37
+ database: string;
38
+
39
+ // MongoDB client options (optional)
40
+ clientOptions?: MongoClientOptions;
41
+
42
+ // Whether to create indexes automatically (default: true)
43
+ autoCreateIndexes?: boolean;
44
+ }
45
+ ```
46
+
47
+ ## Database Schema
48
+
49
+ The adapter creates two collections:
50
+
51
+ ### subscriptions
52
+
53
+ ```javascript
54
+ {
55
+ id: String (UUID),
56
+ endpoint: String,
57
+ keys: {
58
+ p256dh: String,
59
+ auth: String
60
+ },
61
+ userId: String,
62
+ createdAt: Date,
63
+ updatedAt: Date,
64
+ lastUsedAt: Date,
65
+ failedCount: Number,
66
+ status: String, // 'active', 'blocked', or 'expired'
67
+ expiresAt: Date,
68
+ metadata: Object
69
+ }
70
+
71
+ // Indexes
72
+ db.subscriptions.createIndex({ userId: 1 });
73
+ db.subscriptions.createIndex({ status: 1 });
74
+ db.subscriptions.createIndex({ endpoint: 1 }, { unique: true });
75
+ ```
76
+
77
+ ### retry_queue
78
+
79
+ ```javascript
80
+ {
81
+ id: String (UUID),
82
+ subscriptionId: String,
83
+ payload: Object,
84
+ attempt: Number,
85
+ nextRetryAt: Date,
86
+ lastError: String,
87
+ createdAt: Date
88
+ }
89
+
90
+ // Indexes
91
+ db.retry_queue.createIndex({ nextRetryAt: 1 });
92
+ db.retry_queue.createIndex({ subscriptionId: 1 });
93
+ ```
94
+
95
+ ## Features
96
+
97
+ - ✅ Full StorageAdapter interface implementation
98
+ - ✅ Connection pooling built into MongoDB driver
99
+ - ✅ Flexible document storage
100
+ - ✅ Automatic index creation
101
+ - ✅ Unique endpoint constraint
102
+ - ✅ UUID identifiers
103
+ - ✅ Timestamp tracking
104
+
105
+ ## Connection Options
106
+
107
+ You can pass MongoDB client options:
108
+
109
+ ```typescript
110
+ const storage = new MongoDBStorageAdapter({
111
+ uri: 'mongodb://localhost:27017',
112
+ database: 'push_notifications',
113
+ clientOptions: {
114
+ maxPoolSize: 10,
115
+ minPoolSize: 2,
116
+ serverSelectionTimeoutMS: 5000,
117
+ socketTimeoutMS: 45000,
118
+ },
119
+ });
120
+ ```
121
+
122
+ ## MongoDB Atlas
123
+
124
+ Works seamlessly with MongoDB Atlas:
125
+
126
+ ```typescript
127
+ const storage = new MongoDBStorageAdapter({
128
+ uri: 'mongodb+srv://username:password@cluster.mongodb.net/?retryWrites=true&w=majority',
129
+ database: 'push_notifications',
130
+ });
131
+ ```
132
+
133
+ ## Replica Sets
134
+
135
+ Supports MongoDB replica sets:
136
+
137
+ ```typescript
138
+ const storage = new MongoDBStorageAdapter({
139
+ uri: 'mongodb://host1:27017,host2:27017,host3:27017/push_notifications?replicaSet=myReplicaSet',
140
+ database: 'push_notifications',
141
+ });
142
+ ```
143
+
144
+ ## Indexes
145
+
146
+ Indexes are created automatically by default. To create them manually:
147
+
148
+ ```typescript
149
+ const storage = new MongoDBStorageAdapter({
150
+ uri: 'mongodb://localhost:27017',
151
+ database: 'push_notifications',
152
+ autoCreateIndexes: false,
153
+ });
154
+
155
+ await storage.migrate();
156
+ ```
157
+
158
+ ## Graceful Shutdown
159
+
160
+ Always close the adapter when shutting down:
161
+
162
+ ```typescript
163
+ await storage.close();
164
+ ```
165
+
166
+ ## License
167
+
168
+ MIT
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongoDBStorageAdapter = void 0;
4
+ const mongodb_1 = require("mongodb");
5
+ const push_core_1 = require("@allmightypush/push-core");
6
+ const crypto_1 = require("crypto");
7
+ class MongoDBStorageAdapter {
8
+ constructor(options) {
9
+ this.options = options;
10
+ this.closed = false;
11
+ this.connected = false;
12
+ this.client = new mongodb_1.MongoClient(options.uri, options.clientOptions);
13
+ }
14
+ async connect() {
15
+ if (this.connected) {
16
+ return;
17
+ }
18
+ try {
19
+ await this.client.connect();
20
+ this.db = this.client.db(this.options.database);
21
+ this.subscriptions = this.db.collection('subscriptions');
22
+ this.retryQueue = this.db.collection('retry_queue');
23
+ this.connected = true;
24
+ if (this.options.autoCreateIndexes !== false) {
25
+ await this.createIndexes();
26
+ }
27
+ }
28
+ catch (error) {
29
+ throw new push_core_1.StorageError(`Failed to connect to MongoDB: ${error.message}`);
30
+ }
31
+ }
32
+ async createIndexes() {
33
+ try {
34
+ await this.subscriptions.createIndex({ userId: 1 });
35
+ await this.subscriptions.createIndex({ status: 1 });
36
+ await this.subscriptions.createIndex({ endpoint: 1 }, { unique: true });
37
+ await this.retryQueue.createIndex({ nextRetryAt: 1 });
38
+ await this.retryQueue.createIndex({ subscriptionId: 1 });
39
+ }
40
+ catch (error) {
41
+ throw new push_core_1.StorageError(`Failed to create indexes: ${error.message}`);
42
+ }
43
+ }
44
+ async migrate() {
45
+ await this.connect();
46
+ await this.createIndexes();
47
+ }
48
+ async createSubscription(data) {
49
+ await this.connect();
50
+ this.ensureNotClosed();
51
+ try {
52
+ const id = (0, crypto_1.randomUUID)();
53
+ const now = new Date();
54
+ const subscription = {
55
+ id,
56
+ endpoint: data.endpoint,
57
+ keys: data.keys,
58
+ userId: data.userId,
59
+ createdAt: now,
60
+ updatedAt: now,
61
+ failedCount: 0,
62
+ status: 'active',
63
+ expiresAt: data.expiresAt,
64
+ metadata: data.metadata,
65
+ };
66
+ await this.subscriptions.insertOne(subscription);
67
+ return subscription;
68
+ }
69
+ catch (error) {
70
+ if (error.code === 11000) {
71
+ throw new push_core_1.StorageError('Subscription with this endpoint already exists');
72
+ }
73
+ throw new push_core_1.StorageError(`Failed to create subscription: ${error.message}`);
74
+ }
75
+ }
76
+ async getSubscriptionById(id) {
77
+ await this.connect();
78
+ this.ensureNotClosed();
79
+ try {
80
+ const doc = await this.subscriptions.findOne({ id });
81
+ if (!doc) {
82
+ return null;
83
+ }
84
+ return this.docToSubscription(doc);
85
+ }
86
+ catch (error) {
87
+ throw new push_core_1.StorageError(`Failed to get subscription: ${error.message}`);
88
+ }
89
+ }
90
+ async findSubscriptions(filter) {
91
+ await this.connect();
92
+ this.ensureNotClosed();
93
+ try {
94
+ const query = {};
95
+ if (filter.userId) {
96
+ query.userId = filter.userId;
97
+ }
98
+ if (filter.status) {
99
+ query.status = filter.status;
100
+ }
101
+ if (filter.ids && filter.ids.length > 0) {
102
+ query.id = { $in: filter.ids };
103
+ }
104
+ const docs = await this.subscriptions.find(query).toArray();
105
+ return docs.map((doc) => this.docToSubscription(doc));
106
+ }
107
+ catch (error) {
108
+ throw new push_core_1.StorageError(`Failed to find subscriptions: ${error.message}`);
109
+ }
110
+ }
111
+ async updateSubscription(id, updates) {
112
+ await this.connect();
113
+ this.ensureNotClosed();
114
+ try {
115
+ const updateDoc = {
116
+ $set: {
117
+ ...updates,
118
+ updatedAt: new Date(),
119
+ },
120
+ };
121
+ const result = await this.subscriptions.findOneAndUpdate({ id }, updateDoc, { returnDocument: 'after' });
122
+ if (!result) {
123
+ throw new push_core_1.StorageError(`Subscription not found: ${id}`);
124
+ }
125
+ return this.docToSubscription(result);
126
+ }
127
+ catch (error) {
128
+ throw new push_core_1.StorageError(`Failed to update subscription: ${error.message}`);
129
+ }
130
+ }
131
+ async deleteSubscription(id) {
132
+ await this.connect();
133
+ this.ensureNotClosed();
134
+ try {
135
+ await this.subscriptions.deleteOne({ id });
136
+ await this.retryQueue.deleteMany({ subscriptionId: id });
137
+ }
138
+ catch (error) {
139
+ throw new push_core_1.StorageError(`Failed to delete subscription: ${error.message}`);
140
+ }
141
+ }
142
+ async enqueueRetry(retry) {
143
+ await this.connect();
144
+ this.ensureNotClosed();
145
+ try {
146
+ const id = retry.id || (0, crypto_1.randomUUID)();
147
+ await this.retryQueue.insertOne({
148
+ id,
149
+ subscriptionId: retry.subscriptionId,
150
+ payload: retry.payload,
151
+ attempt: retry.attempt,
152
+ nextRetryAt: retry.nextRetryAt,
153
+ lastError: retry.lastError,
154
+ createdAt: new Date(),
155
+ });
156
+ }
157
+ catch (error) {
158
+ throw new push_core_1.StorageError(`Failed to enqueue retry: ${error.message}`);
159
+ }
160
+ }
161
+ async dequeueRetry(limit) {
162
+ await this.connect();
163
+ this.ensureNotClosed();
164
+ try {
165
+ const docs = await this.retryQueue
166
+ .find({ nextRetryAt: { $lte: new Date() } })
167
+ .sort({ nextRetryAt: 1 })
168
+ .limit(limit)
169
+ .toArray();
170
+ return docs.map((doc) => this.docToRetryEntry(doc));
171
+ }
172
+ catch (error) {
173
+ throw new push_core_1.StorageError(`Failed to dequeue retry: ${error.message}`);
174
+ }
175
+ }
176
+ async ackRetry(retryId) {
177
+ await this.connect();
178
+ this.ensureNotClosed();
179
+ try {
180
+ await this.retryQueue.deleteOne({ id: retryId });
181
+ }
182
+ catch (error) {
183
+ throw new push_core_1.StorageError(`Failed to acknowledge retry: ${error.message}`);
184
+ }
185
+ }
186
+ async getQueueStats() {
187
+ await this.connect();
188
+ this.ensureNotClosed();
189
+ try {
190
+ const pending = await this.retryQueue.countDocuments({
191
+ nextRetryAt: { $lte: new Date() },
192
+ });
193
+ return {
194
+ pending,
195
+ processing: 0,
196
+ failed: 0,
197
+ };
198
+ }
199
+ catch (error) {
200
+ throw new push_core_1.StorageError(`Failed to get queue stats: ${error.message}`);
201
+ }
202
+ }
203
+ async close() {
204
+ if (!this.closed) {
205
+ await this.client.close();
206
+ this.closed = true;
207
+ this.connected = false;
208
+ }
209
+ }
210
+ docToSubscription(doc) {
211
+ return {
212
+ id: doc.id,
213
+ endpoint: doc.endpoint,
214
+ keys: doc.keys,
215
+ userId: doc.userId,
216
+ createdAt: doc.createdAt instanceof Date ? doc.createdAt : new Date(doc.createdAt),
217
+ updatedAt: doc.updatedAt instanceof Date ? doc.updatedAt : new Date(doc.updatedAt),
218
+ lastUsedAt: doc.lastUsedAt ? (doc.lastUsedAt instanceof Date ? doc.lastUsedAt : new Date(doc.lastUsedAt)) : undefined,
219
+ failedCount: doc.failedCount,
220
+ status: doc.status,
221
+ expiresAt: doc.expiresAt ? (doc.expiresAt instanceof Date ? doc.expiresAt : new Date(doc.expiresAt)) : undefined,
222
+ metadata: doc.metadata,
223
+ };
224
+ }
225
+ docToRetryEntry(doc) {
226
+ return {
227
+ id: doc.id,
228
+ subscriptionId: doc.subscriptionId,
229
+ payload: doc.payload,
230
+ attempt: doc.attempt,
231
+ nextRetryAt: doc.nextRetryAt instanceof Date ? doc.nextRetryAt : new Date(doc.nextRetryAt),
232
+ lastError: doc.lastError,
233
+ createdAt: doc.createdAt instanceof Date ? doc.createdAt : new Date(doc.createdAt),
234
+ };
235
+ }
236
+ ensureNotClosed() {
237
+ if (this.closed) {
238
+ throw new push_core_1.StorageError('Storage adapter is closed');
239
+ }
240
+ }
241
+ }
242
+ exports.MongoDBStorageAdapter = MongoDBStorageAdapter;
243
+ exports.default = MongoDBStorageAdapter;
244
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ import { MongoClient } from 'mongodb';
2
+ import { StorageError, } from '@allmightypush/push-core';
3
+ import { randomUUID } from 'crypto';
4
+ export class MongoDBStorageAdapter {
5
+ constructor(options) {
6
+ this.options = options;
7
+ this.closed = false;
8
+ this.connected = false;
9
+ this.client = new MongoClient(options.uri, options.clientOptions);
10
+ }
11
+ async connect() {
12
+ if (this.connected) {
13
+ return;
14
+ }
15
+ try {
16
+ await this.client.connect();
17
+ this.db = this.client.db(this.options.database);
18
+ this.subscriptions = this.db.collection('subscriptions');
19
+ this.retryQueue = this.db.collection('retry_queue');
20
+ this.connected = true;
21
+ if (this.options.autoCreateIndexes !== false) {
22
+ await this.createIndexes();
23
+ }
24
+ }
25
+ catch (error) {
26
+ throw new StorageError(`Failed to connect to MongoDB: ${error.message}`);
27
+ }
28
+ }
29
+ async createIndexes() {
30
+ try {
31
+ await this.subscriptions.createIndex({ userId: 1 });
32
+ await this.subscriptions.createIndex({ status: 1 });
33
+ await this.subscriptions.createIndex({ endpoint: 1 }, { unique: true });
34
+ await this.retryQueue.createIndex({ nextRetryAt: 1 });
35
+ await this.retryQueue.createIndex({ subscriptionId: 1 });
36
+ }
37
+ catch (error) {
38
+ throw new StorageError(`Failed to create indexes: ${error.message}`);
39
+ }
40
+ }
41
+ async migrate() {
42
+ await this.connect();
43
+ await this.createIndexes();
44
+ }
45
+ async createSubscription(data) {
46
+ await this.connect();
47
+ this.ensureNotClosed();
48
+ try {
49
+ const id = randomUUID();
50
+ const now = new Date();
51
+ const subscription = {
52
+ id,
53
+ endpoint: data.endpoint,
54
+ keys: data.keys,
55
+ userId: data.userId,
56
+ createdAt: now,
57
+ updatedAt: now,
58
+ failedCount: 0,
59
+ status: 'active',
60
+ expiresAt: data.expiresAt,
61
+ metadata: data.metadata,
62
+ };
63
+ await this.subscriptions.insertOne(subscription);
64
+ return subscription;
65
+ }
66
+ catch (error) {
67
+ if (error.code === 11000) {
68
+ throw new StorageError('Subscription with this endpoint already exists');
69
+ }
70
+ throw new StorageError(`Failed to create subscription: ${error.message}`);
71
+ }
72
+ }
73
+ async getSubscriptionById(id) {
74
+ await this.connect();
75
+ this.ensureNotClosed();
76
+ try {
77
+ const doc = await this.subscriptions.findOne({ id });
78
+ if (!doc) {
79
+ return null;
80
+ }
81
+ return this.docToSubscription(doc);
82
+ }
83
+ catch (error) {
84
+ throw new StorageError(`Failed to get subscription: ${error.message}`);
85
+ }
86
+ }
87
+ async findSubscriptions(filter) {
88
+ await this.connect();
89
+ this.ensureNotClosed();
90
+ try {
91
+ const query = {};
92
+ if (filter.userId) {
93
+ query.userId = filter.userId;
94
+ }
95
+ if (filter.status) {
96
+ query.status = filter.status;
97
+ }
98
+ if (filter.ids && filter.ids.length > 0) {
99
+ query.id = { $in: filter.ids };
100
+ }
101
+ const docs = await this.subscriptions.find(query).toArray();
102
+ return docs.map((doc) => this.docToSubscription(doc));
103
+ }
104
+ catch (error) {
105
+ throw new StorageError(`Failed to find subscriptions: ${error.message}`);
106
+ }
107
+ }
108
+ async updateSubscription(id, updates) {
109
+ await this.connect();
110
+ this.ensureNotClosed();
111
+ try {
112
+ const updateDoc = {
113
+ $set: {
114
+ ...updates,
115
+ updatedAt: new Date(),
116
+ },
117
+ };
118
+ const result = await this.subscriptions.findOneAndUpdate({ id }, updateDoc, { returnDocument: 'after' });
119
+ if (!result) {
120
+ throw new StorageError(`Subscription not found: ${id}`);
121
+ }
122
+ return this.docToSubscription(result);
123
+ }
124
+ catch (error) {
125
+ throw new StorageError(`Failed to update subscription: ${error.message}`);
126
+ }
127
+ }
128
+ async deleteSubscription(id) {
129
+ await this.connect();
130
+ this.ensureNotClosed();
131
+ try {
132
+ await this.subscriptions.deleteOne({ id });
133
+ await this.retryQueue.deleteMany({ subscriptionId: id });
134
+ }
135
+ catch (error) {
136
+ throw new StorageError(`Failed to delete subscription: ${error.message}`);
137
+ }
138
+ }
139
+ async enqueueRetry(retry) {
140
+ await this.connect();
141
+ this.ensureNotClosed();
142
+ try {
143
+ const id = retry.id || randomUUID();
144
+ await this.retryQueue.insertOne({
145
+ id,
146
+ subscriptionId: retry.subscriptionId,
147
+ payload: retry.payload,
148
+ attempt: retry.attempt,
149
+ nextRetryAt: retry.nextRetryAt,
150
+ lastError: retry.lastError,
151
+ createdAt: new Date(),
152
+ });
153
+ }
154
+ catch (error) {
155
+ throw new StorageError(`Failed to enqueue retry: ${error.message}`);
156
+ }
157
+ }
158
+ async dequeueRetry(limit) {
159
+ await this.connect();
160
+ this.ensureNotClosed();
161
+ try {
162
+ const docs = await this.retryQueue
163
+ .find({ nextRetryAt: { $lte: new Date() } })
164
+ .sort({ nextRetryAt: 1 })
165
+ .limit(limit)
166
+ .toArray();
167
+ return docs.map((doc) => this.docToRetryEntry(doc));
168
+ }
169
+ catch (error) {
170
+ throw new StorageError(`Failed to dequeue retry: ${error.message}`);
171
+ }
172
+ }
173
+ async ackRetry(retryId) {
174
+ await this.connect();
175
+ this.ensureNotClosed();
176
+ try {
177
+ await this.retryQueue.deleteOne({ id: retryId });
178
+ }
179
+ catch (error) {
180
+ throw new StorageError(`Failed to acknowledge retry: ${error.message}`);
181
+ }
182
+ }
183
+ async getQueueStats() {
184
+ await this.connect();
185
+ this.ensureNotClosed();
186
+ try {
187
+ const pending = await this.retryQueue.countDocuments({
188
+ nextRetryAt: { $lte: new Date() },
189
+ });
190
+ return {
191
+ pending,
192
+ processing: 0,
193
+ failed: 0,
194
+ };
195
+ }
196
+ catch (error) {
197
+ throw new StorageError(`Failed to get queue stats: ${error.message}`);
198
+ }
199
+ }
200
+ async close() {
201
+ if (!this.closed) {
202
+ await this.client.close();
203
+ this.closed = true;
204
+ this.connected = false;
205
+ }
206
+ }
207
+ docToSubscription(doc) {
208
+ return {
209
+ id: doc.id,
210
+ endpoint: doc.endpoint,
211
+ keys: doc.keys,
212
+ userId: doc.userId,
213
+ createdAt: doc.createdAt instanceof Date ? doc.createdAt : new Date(doc.createdAt),
214
+ updatedAt: doc.updatedAt instanceof Date ? doc.updatedAt : new Date(doc.updatedAt),
215
+ lastUsedAt: doc.lastUsedAt ? (doc.lastUsedAt instanceof Date ? doc.lastUsedAt : new Date(doc.lastUsedAt)) : undefined,
216
+ failedCount: doc.failedCount,
217
+ status: doc.status,
218
+ expiresAt: doc.expiresAt ? (doc.expiresAt instanceof Date ? doc.expiresAt : new Date(doc.expiresAt)) : undefined,
219
+ metadata: doc.metadata,
220
+ };
221
+ }
222
+ docToRetryEntry(doc) {
223
+ return {
224
+ id: doc.id,
225
+ subscriptionId: doc.subscriptionId,
226
+ payload: doc.payload,
227
+ attempt: doc.attempt,
228
+ nextRetryAt: doc.nextRetryAt instanceof Date ? doc.nextRetryAt : new Date(doc.nextRetryAt),
229
+ lastError: doc.lastError,
230
+ createdAt: doc.createdAt instanceof Date ? doc.createdAt : new Date(doc.createdAt),
231
+ };
232
+ }
233
+ ensureNotClosed() {
234
+ if (this.closed) {
235
+ throw new StorageError('Storage adapter is closed');
236
+ }
237
+ }
238
+ }
239
+ export default MongoDBStorageAdapter;
240
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { MongoClientOptions } from 'mongodb';
2
+ import { StorageAdapter, Subscription, CreateSubscriptionData, SubscriptionFilter, RetryEntry, QueueStats } from '@allmightypush/push-core';
3
+ export interface MongoDBStorageOptions {
4
+ uri: string;
5
+ database: string;
6
+ clientOptions?: MongoClientOptions;
7
+ autoCreateIndexes?: boolean;
8
+ }
9
+ export declare class MongoDBStorageAdapter implements StorageAdapter {
10
+ private options;
11
+ private client;
12
+ private db;
13
+ private subscriptions;
14
+ private retryQueue;
15
+ private closed;
16
+ private connected;
17
+ constructor(options: MongoDBStorageOptions);
18
+ private connect;
19
+ private createIndexes;
20
+ migrate(): Promise<void>;
21
+ createSubscription(data: CreateSubscriptionData): Promise<Subscription>;
22
+ getSubscriptionById(id: string): Promise<Subscription | null>;
23
+ findSubscriptions(filter: SubscriptionFilter): Promise<Subscription[]>;
24
+ updateSubscription(id: string, updates: Partial<Subscription>): Promise<Subscription>;
25
+ deleteSubscription(id: string): Promise<void>;
26
+ enqueueRetry(retry: RetryEntry): Promise<void>;
27
+ dequeueRetry(limit: number): Promise<RetryEntry[]>;
28
+ ackRetry(retryId: string): Promise<void>;
29
+ getQueueStats(): Promise<QueueStats>;
30
+ close(): Promise<void>;
31
+ private docToSubscription;
32
+ private docToRetryEntry;
33
+ private ensureNotClosed;
34
+ }
35
+ export default MongoDBStorageAdapter;
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAA+B,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EACL,cAAc,EACd,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,EAClB,UAAU,EACV,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAMlC,MAAM,WAAW,qBAAqB;IAEpC,GAAG,EAAE,MAAM,CAAC;IAEZ,QAAQ,EAAE,MAAM,CAAC;IAEjB,aAAa,CAAC,EAAE,kBAAkB,CAAC;IAEnC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAKD,qBAAa,qBAAsB,YAAW,cAAc;IAQ9C,OAAO,CAAC,OAAO;IAP3B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,SAAS,CAAkB;gBAEf,OAAO,EAAE,qBAAqB;YAOpC,OAAO;YAwBP,aAAa;IAkBrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQxB,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC;IAmCvE,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAoB7D,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IA8BtE,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IA+BrF,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB7C,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB9C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAoBlD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxC,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC;IAsBpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,eAAe;CAKxB;AAED,eAAe,qBAAqB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@allmightypush/push-storage-mongo",
3
+ "version": "1.0.0",
4
+ "description": "MongoDB storage adapter for push notification library",
5
+ "main": "dist/cjs/index.js",
6
+ "module": "dist/esm/index.js",
7
+ "types": "dist/types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "require": "./dist/cjs/index.js",
11
+ "import": "./dist/esm/index.js",
12
+ "types": "./dist/types/index.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "npm run build:cjs && npm run build:esm && npm run build:types",
20
+ "build:cjs": "tsc -p tsconfig.cjs.json",
21
+ "build:esm": "tsc -p tsconfig.esm.json",
22
+ "build:types": "tsc -p tsconfig.types.json",
23
+ "test": "jest --passWithNoTests",
24
+ "test:watch": "jest --watch",
25
+ "test:coverage": "jest --coverage --passWithNoTests",
26
+ "clean": "rm -rf dist"
27
+ },
28
+ "keywords": [
29
+ "push",
30
+ "notification",
31
+ "storage",
32
+ "mongodb",
33
+ "mongo"
34
+ ],
35
+ "author": "Samtes64",
36
+ "license": "MIT",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/Samtes64/all-mighty-push.git",
40
+ "directory": "packages/push-storage-mongo"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/Samtes64/all-mighty-push/issues"
44
+ },
45
+ "homepage": "https://github.com/Samtes64/all-mighty-push/tree/main/packages/push-storage-mongo#readme",
46
+ "dependencies": {
47
+ "@allmightypush/push-core": "^1.0.0",
48
+ "mongodb": "^6.3.0"
49
+ },
50
+ "engines": {
51
+ "node": ">=16.0.0"
52
+ }
53
+ }