db-data-gd-uploader 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Saud Ahmad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # GD Uploader šŸ“¦
2
+
3
+ **Professional Database Backup System with Google Drive Integration**
4
+
5
+ Export MongoDB/any database to Excel and upload to Google Drive automatically - no manual intervention required!
6
+
7
+ [![npm version](https://img.shields.io/npm/v/db-data-gd-uploader.svg)](https://npmjs.org/package/db-data-gd-uploader)
8
+ [![Node.js Version](https://img.shields.io/node/v/db-data-gd-uploader.svg)](https://nodejs.org/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
+ [![GitHub](https://img.shields.io/badge/GitHub-Saud--web--dev-blue)](https://github.com/Saud-web-dev/GD-module)
11
+
12
+ ## ✨ Features
13
+
14
+ - šŸ—„ļø **Multi-Database Support** - Extract from MongoDB, any database with Node drivers
15
+ - šŸ“Š **Excel Export** - Professional formatted Excel files with headers, styling, borders
16
+ - ā˜ļø **Google Drive Upload** - Automatic upload using Service Account (no OAuth needed)
17
+ - šŸ” **Secure** - Service Account authentication, no personal credentials exposed
18
+ - šŸŽÆ **Zero Config** - Works out of the box with minimal setup
19
+ - ⚔ **Fast** - Streams large datasets efficiently
20
+ - šŸ“… **Scheduled Backups** - Built-in scheduler for automated backups
21
+
22
+ ## šŸš€ Quick Start
23
+
24
+ ### Installation
25
+
26
+ ```bash
27
+ npm install db-data-gd-uploader
28
+ ```
29
+
30
+ ### Setup (One-time)
31
+
32
+ 1. **Create Google Cloud Service Account**
33
+ ```bash
34
+ # Go to Google Cloud Console
35
+ # Create service account → Generate JSON key
36
+ # Save to: config/service-account.json
37
+ ```
38
+
39
+ 2. **Share Folder with Service Account**
40
+ - Go to Google Drive
41
+ - Create folder for backups
42
+ - Right-click → Share
43
+ - Add Service Account email: `your-account@project.iam.gserviceaccount.com`
44
+ - Give Editor permission
45
+
46
+ 3. **Set Environment Variables**
47
+ ```bash
48
+ cp .env.example .env
49
+ ```
50
+
51
+ ```env
52
+ MONGODB_URI=mongodb://localhost:27017/your-db
53
+ GOOGLE_DRIVE_FOLDER_ID=your-folder-id
54
+ ```
55
+
56
+ ### Usage
57
+
58
+ #### Basic Backup
59
+
60
+ ```javascript
61
+ import { createAndUploadCompleteBackup } from 'db-data-gd-uploader'
62
+
63
+ const result = await createAndUploadCompleteBackup({
64
+ uploadToDrive: true,
65
+ workbookName: 'my-backup'
66
+ })
67
+
68
+ console.log(result)
69
+ // Output:
70
+ // {
71
+ // uploaded: true,
72
+ // fileName: 'my-backup.xlsx',
73
+ // databases: ['stc_db', 'test'],
74
+ // collections: [...],
75
+ // totalRecords: 1000,
76
+ // driveFile: { id: '...', webViewLink: '...' }
77
+ // }
78
+ ```
79
+
80
+ #### Upload Excel to Drive
81
+
82
+ ```javascript
83
+ import { uploadExcelToGoogleDrive } from 'db-data-gd-uploader/drive'
84
+
85
+ const result = await uploadExcelToGoogleDrive({
86
+ buffer: excelBuffer,
87
+ fileName: 'data-export.xlsx',
88
+ folderId: 'optional-folder-id'
89
+ })
90
+ ```
91
+
92
+ #### Generate Excel
93
+
94
+ ```javascript
95
+ import { createExcelWorkbook } from 'db-data-gd-uploader/excel'
96
+
97
+ const workbook = await createExcelWorkbook([
98
+ {
99
+ modelName: 'users',
100
+ collectionName: 'users',
101
+ database: 'mydb',
102
+ data: [
103
+ { _id: 1, name: 'John', email: 'john@example.com' },
104
+ { _id: 2, name: 'Jane', email: 'jane@example.com' }
105
+ ]
106
+ }
107
+ ], {
108
+ workbookName: 'users-export'
109
+ })
110
+ ```
111
+
112
+ #### Extract Data from Database
113
+
114
+ ```javascript
115
+ import { extractAllDatabasesCollections } from 'db-data-gd-uploader/extract'
116
+
117
+ const data = await extractAllDatabasesCollections(
118
+ 'mongodb://localhost:27017/mydb',
119
+ ['admin', 'config', 'local'] // Excluded databases
120
+ )
121
+
122
+ console.log(data)
123
+ // [
124
+ // { database: 'mydb', collectionName: 'users', data: [...] },
125
+ // { database: 'mydb', collectionName: 'products', data: [...] }
126
+ // ]
127
+ ```
128
+
129
+ ## šŸ“‹ API Reference
130
+
131
+ ### `createAndUploadCompleteBackup(options)`
132
+
133
+ Main function - extracts all databases, creates Excel, uploads to Drive.
134
+
135
+ **Options:**
136
+ - `uploadToDrive` (boolean) - Upload to Google Drive? Default: `true`
137
+ - `workbookName` (string) - Excel file name. Default: `complete-backup-YYYY-MM-DD`
138
+ - `folderId` (string) - Google Drive folder ID. Default: from `.env`
139
+ - `excludedDatabases` (array) - Skip these databases. Default: `['admin', 'config', 'local']`
140
+
141
+ **Returns:** Promise<Object>
142
+ - `uploaded` (boolean)
143
+ - `fileName` (string)
144
+ - `databases` (array)
145
+ - `collections` (array)
146
+ - `totalRecords` (number)
147
+ - `driveFile` (object) - Google Drive file info
148
+
149
+ ---
150
+
151
+ ### `uploadExcelToGoogleDrive(options)`
152
+
153
+ Upload Excel file to Google Drive.
154
+
155
+ **Options:**
156
+ - `buffer` (Buffer) - Excel file buffer **[required]**
157
+ - `fileName` (string) - File name **[required]**
158
+ - `contentType` (string) - MIME type. Default: Excel
159
+ - `folderId` (string) - Google Drive folder ID
160
+
161
+ **Returns:** Promise<Object>
162
+ - `id` (string) - Google Drive file ID
163
+ - `webViewLink` (string) - Shareable link
164
+ - `status` (string) - 'uploaded' or 'local_only'
165
+
166
+ ---
167
+
168
+ ### `createExcelWorkbook(data, options)`
169
+
170
+ Create formatted Excel workbook.
171
+
172
+ **Parameters:**
173
+ - `data` (array) - Collection data with structure: `{ modelName, collectionName, database, data }`
174
+ - `options.workbookName` (string) - Workbook name
175
+
176
+ **Returns:** Promise<Object>
177
+ - `buffer` (Buffer) - Excel file binary
178
+ - `fileName` (string)
179
+ - `contentType` (string)
180
+
181
+ ---
182
+
183
+ ### `extractAllDatabasesCollections(mongoUri, excludedDatabases)`
184
+
185
+ Extract all collections from all databases.
186
+
187
+ **Parameters:**
188
+ - `mongoUri` (string) - MongoDB connection string
189
+ - `excludedDatabases` (array) - Databases to skip
190
+
191
+ **Returns:** Promise<Array>
192
+ - `[{ database, collectionName, documentCount, data }]`
193
+
194
+ ## šŸ”§ Environment Variables
195
+
196
+ ```env
197
+ # MongoDB
198
+ MONGODB_URI=mongodb://localhost:27017/mydb
199
+
200
+ # Google Drive
201
+ GOOGLE_DRIVE_FOLDER_ID=your-folder-id
202
+
203
+ # Service Account (or use config/service-account.json)
204
+ GOOGLE_SERVICE_ACCOUNT_JSON={"type":"service_account",...}
205
+
206
+ # Optional: Scheduler settings
207
+ BACKUP_SCHEDULE_TIME=02:00 # 2 AM daily
208
+ ```
209
+
210
+ ## šŸ“ Project Structure
211
+
212
+ ```
213
+ gd-uploader/
214
+ ā”œā”€ā”€ src/
215
+ │ ā”œā”€ā”€ index.js # Main entry point
216
+ │ ā”œā”€ā”€ services/
217
+ │ │ ā”œā”€ā”€ backupService.js # Main backup logic
218
+ │ │ ā”œā”€ā”€ googleDrive.js # Google Drive operations
219
+ │ │ └── googleAuth.js # Authentication
220
+ │ ā”œā”€ā”€ utils/
221
+ │ │ ā”œā”€ā”€ excelFormatter.js # Excel generation
222
+ │ │ └── dataExtract.js # Database extraction
223
+ │ └── scripts/
224
+ │ └── backup.js # CLI script
225
+ ā”œā”€ā”€ config/
226
+ │ └── service-account.json # Google Service Account
227
+ ā”œā”€ā”€ .env.example
228
+ ā”œā”€ā”€ package.json
229
+ └── README.md
230
+ ```
231
+
232
+ ## šŸ” Security
233
+
234
+ - āœ… No personal Google credentials stored
235
+ - āœ… Service Account uses read-only for data extraction
236
+ - āœ… All sensitive data in `.env` (not committed)
237
+ - āœ… No hardcoded credentials
238
+
239
+ ## šŸ› Troubleshooting
240
+
241
+ ### "Service Account has no storage quota"
242
+ **Solution:** Use Shared Drive or share personal folder with Service Account email
243
+
244
+ ### "MONGODB_URI is required"
245
+ **Solution:** Set `MONGODB_URI` in `.env` or environment variables
246
+
247
+ ### "Invalid GOOGLE_SERVICE_ACCOUNT_JSON"
248
+ **Solution:** Place valid JSON in `config/service-account.json` or `.env`
249
+
250
+ ## šŸ“¦ Publishing to npm
251
+
252
+ ```bash
253
+ # 1. Login to npm
254
+ npm login
255
+
256
+ # 2. Update version in package.json
257
+ npm version patch # or minor/major
258
+
259
+ # 3. Publish
260
+ npm publish
261
+
262
+ # 4. Check
263
+ npm info gd-uploader
264
+ ```
265
+
266
+ ## šŸ“„ License
267
+
268
+ MIT Ā© [Saud Ahmad]
269
+
270
+ ## šŸ¤ Contributing
271
+
272
+ Contributions welcome! Please feel free to submit a Pull Request.
273
+
274
+ ## šŸ“§ Support
275
+
276
+ For issues and questions: https://github.com/Saud-web-dev/GD-module/issues
@@ -0,0 +1,13 @@
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "gd-uploader-saud",
4
+ "private_key_id": "f4b306f4f39ddea962be2c18f62754210a881a47",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCw6mu1O1DwPkUL\nzgiK/BXB3UbZRqNzERnp5LdeY1TBWknnvm0GnWoNQjFSVKq38KjSG0ekJ4eIYy+N\nqLFd+o460LuYkORBJQSN3OxXQym/aV3e12fcgWyncAKxyF+4KJtMWI7ir2ih9BcS\nkQ+bDX82LGZeG9uCu51FzG5jKFJ/JueTjSG0DZamFvaXZU4P+fYe+m5r4cFMt8yL\nLFbkoh+Pn8yEY2tKKyTdmA4oX74g0cB8JaNo6Y72TgPsX7aVU7MWlB3LCykFRcj3\nkVvsPJZLRiWGPSjM/F4YWE/MltJ4zrvk1rPr8HHpxGwaV3+8ZRj7D1S8f5Mfk6MW\ngSadzunxAgMBAAECggEAA1uGgBpftzqygX57FAZOp4h2O2Mx+UBfzQa6e8L/TSZc\nv2/fCkshoZ4NNeiwtWf1IQ1EFhmvaymU3HzzRD9+CKi37aSbpBdlH/bpSGitmbfd\noqJD1xu2GHr+WhjupS77kalSVBUUd8YcS7hGuGBuXUFV3CWymOMQTBK3csvWipGo\nLsZj3n+FWuasqbHstE7RR8rac+EgMq4PrYfOFlu3on4542HRAiQDUNjbyt6Mt+xZ\ns8B8NoyNlZxD5/26olQrqBQMo5rt87tT+oEE7doxaxqiUyd7eyZEQ7UoQ1Cv+U6/\nxMJVYze7xBJ5qqexJhTl4ANRxT9Qd2dJJcOJzQiKbwKBgQDkfts7Z83krHWld6cV\n9UexJJkqiovE4QRk2mfFq5KrqzBDM+EYlugH2OzNPyrqKyj/Cmjk2hwSxbnkyO38\nZCeylUFVfd/v36nkYUzZ3gR8B9en7OaaEMS4VIgpyPwxrvNlmS0O51Jt0s6k2eib\natCApfXF/eMCdjwF7IchxGx5LwKBgQDGNh6u+WDXx+j+OTFPgANqXGa3ls3BEqsw\nAmGrv2xBIGTkZBbNInV7LaW8cvbSZN+k8Zel30fpHt/JbzjmexqQi8/7qFl7MNun\n45jXjghkJhjvtib/Xt9FCCLXhH7wmGRYzhElJCqF9wjnxBoatdXybV/wnXE+Hxd2\nCHURuBnG3wKBgQDDopmyUz5F/CL+eWPluQyY7uz1L4pcFwzcDOOsqyn5Makw4Mpp\nc0tW7LRTRzJHLIz9ULxetSA0MnbnG+InptkWXhSCTjPd/XJIx8Y1A5JzX4OVk5Ad\neR31dOrgW+UR5Okgo/WgPQ6mWUf0fV5bMykx/OZhju8+vFzH9av9jWASoQKBgQCE\ndR5EJ/sDuGCHo4jEa/PcXCt4fJq7b9JenvjOYXnie9dwmUJzi5ee3X5oVRuEtkyO\nWbTR8EiKDUvXvS/1NkcmWYh/0J0bqibgJ0S4p/4LjzoS11NwTOI/q5Q9GhoKhoxo\nnCzw+R5BsDiPSYl4WBPFkjoO/efzb6uqATTaxoDTWQKBgQC7BMJ4Bq2IQtpZzXp4\nkafOraq47O8xXE5V9jg6wlLEw2zWWK9wRGy+ByC7Cx8H5dGRq8z87lUCAIE4SJnr\n8YUWkWhxcOJ/PIj+qkWZUq3HewjzeZRFFFlIwCYK7qM9yPkrMZWmx6ZIY6ILkgMW\nRux3wxiq+cjEs55QGtxqBgmciA==\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "gd-uploader@gd-uploader-saud.iam.gserviceaccount.com",
7
+ "client_id": "111930094607475043849",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gd-uploader%40gd-uploader-saud.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "db-data-gd-uploader",
3
+ "version": "1.0.0",
4
+ "description": "Professional Database Backup System with Google Drive Integration. Export MongoDB/any database to Excel and upload to Google Drive automatically.",
5
+ "keywords": [
6
+ "database",
7
+ "backup",
8
+ "google-drive",
9
+ "mongodb",
10
+ "excel",
11
+ "export",
12
+ "cloud-storage",
13
+ "db-export",
14
+ "data-backup"
15
+ ],
16
+ "license": "MIT",
17
+ "author": "Saud Ahmad",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/Saud-web-dev/GD-module.git"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/Saud-web-dev/GD-module/issues"
24
+ },
25
+ "homepage": "https://github.com/Saud-web-dev/GD-module#readme",
26
+ "type": "module",
27
+ "main": "src/index.js",
28
+ "exports": {
29
+ ".": "./src/index.js",
30
+ "./backup": "./src/services/backupService.js",
31
+ "./drive": "./src/services/googleDrive.js",
32
+ "./excel": "./src/utils/excelFormatter.js",
33
+ "./extract": "./src/utils/dataExtract.js"
34
+ },
35
+ "engines": {
36
+ "node": ">=16.0.0"
37
+ },
38
+ "scripts": {
39
+ "start": "node src/server.js",
40
+ "dev": "nodemon src/server.js",
41
+ "backup": "node src/scripts/backup.js",
42
+ "scheduler": "node src/scripts/scheduler.js",
43
+ "lint": "node --check src/index.js src/services/*.js src/utils/*.js",
44
+ "test": "node --check src/server.js && node --check src/app.js && node --check src/config/database.js && node --check src/services/backupService.js",
45
+ "prepublishOnly": "npm run lint && npm run test"
46
+ },
47
+ "dependencies": {
48
+ "cookie-parser": "^1.4.7",
49
+ "cors": "^2.8.6",
50
+ "dotenv": "^17.4.2",
51
+ "exceljs": "^4.4.0",
52
+ "express": "^5.2.1",
53
+ "googleapis": "^180.0.0",
54
+ "jsonwebtoken": "^9.0.3",
55
+ "mongoose": "^9.10.0"
56
+ },
57
+ "devDependencies": {
58
+ "nodemon": "^3.1.14"
59
+ },
60
+ "files": [
61
+ "src/",
62
+ "config/",
63
+ "README.md",
64
+ "LICENSE"
65
+ ]
66
+ }
package/src/app.js ADDED
@@ -0,0 +1,69 @@
1
+ import cors from 'cors'
2
+ import express from 'express'
3
+ import mongoose from 'mongoose'
4
+ import { join } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+ import config from './config/environment.js'
7
+ import authRoutes from './routes/authRoutes.js'
8
+ import backupRoutes from './routes/backupRoutes.js'
9
+ import { getDatabaseStatus } from './config/database.js'
10
+
11
+ const __dirname = join(fileURLToPath(import.meta.url), '..')
12
+
13
+ export function createApp() {
14
+ const app = express()
15
+
16
+ // Middleware
17
+ app.use(cors({ origin: config.frontendUrl }))
18
+ app.use(express.json())
19
+
20
+ // Health check endpoint
21
+ app.get('/api/health', (_request, response) => {
22
+ response.json({
23
+ ok: true,
24
+ database: getDatabaseStatus(),
25
+ environment: config.nodeEnv,
26
+ timestamp: new Date().toISOString(),
27
+ })
28
+ })
29
+
30
+ // Routes
31
+ app.use('/auth', authRoutes)
32
+ app.use('/api', backupRoutes)
33
+
34
+ // Download endpoint
35
+ app.get('/download/:fileName', (request, response) => {
36
+ const { fileName } = request.params
37
+ const filePath = join(__dirname, '..', 'exports', fileName)
38
+
39
+ // Security: prevent path traversal
40
+ if (!filePath.startsWith(join(__dirname, '..', 'exports'))) {
41
+ return response.status(400).json({ message: 'Invalid file' })
42
+ }
43
+
44
+ response.download(filePath, fileName, (err) => {
45
+ if (err) {
46
+ console.error('Download error:', err)
47
+ response.status(500).json({ message: 'Download failed' })
48
+ }
49
+ })
50
+ })
51
+
52
+ // 404 handler
53
+ app.use((_request, response) => {
54
+ response.status(404).json({ message: 'Route not found' })
55
+ })
56
+
57
+ // Error handler
58
+ app.use((error, _request, response, _next) => {
59
+ console.error('Server error:', error)
60
+ response.status(500).json({
61
+ message: 'Internal server error',
62
+ error: config.nodeEnv === 'development' ? error.message : undefined,
63
+ })
64
+ })
65
+
66
+ return app
67
+ }
68
+
69
+ export default createApp
@@ -0,0 +1,38 @@
1
+ import mongoose from 'mongoose'
2
+
3
+ export async function connectDatabase() {
4
+ if (!process.env.MONGODB_URI) {
5
+ throw new Error('MONGODB_URI is required')
6
+ }
7
+
8
+ try {
9
+ await mongoose.connect(process.env.MONGODB_URI, {
10
+ maxPoolSize: 10,
11
+ serverSelectionTimeoutMS: 5000,
12
+ })
13
+ console.log('āœ… MongoDB connected successfully')
14
+ return mongoose.connection
15
+ } catch (error) {
16
+ console.error('āŒ MongoDB connection failed:', error.message)
17
+ throw error
18
+ }
19
+ }
20
+
21
+ export async function disconnectDatabase() {
22
+ try {
23
+ await mongoose.disconnect()
24
+ console.log('āœ… MongoDB disconnected')
25
+ } catch (error) {
26
+ console.error('āŒ Disconnect error:', error.message)
27
+ }
28
+ }
29
+
30
+ export function getDatabaseStatus() {
31
+ const states = {
32
+ 0: 'disconnected',
33
+ 1: 'connected',
34
+ 2: 'connecting',
35
+ 3: 'disconnecting',
36
+ }
37
+ return states[mongoose.connection.readyState] || 'unknown'
38
+ }
@@ -0,0 +1,55 @@
1
+ import dotenv from 'dotenv'
2
+
3
+ dotenv.config()
4
+
5
+ export const config = {
6
+ port: Number(process.env.PORT || 5000),
7
+ nodeEnv: process.env.NODE_ENV || 'development',
8
+ mongoUri: process.env.MONGODB_URI,
9
+ frontendUrl: process.env.FRONTEND_URL || 'http://localhost:5173',
10
+
11
+ // Google OAuth
12
+ googleOAuth: {
13
+ clientId: process.env.GOOGLE_OAUTH_CLIENT_ID,
14
+ clientSecret: process.env.GOOGLE_OAUTH_CLIENT_SECRET,
15
+ redirectUri: process.env.GOOGLE_OAUTH_REDIRECT_URI,
16
+ },
17
+
18
+ // Google Drive
19
+ googleDrive: {
20
+ folderId: process.env.GOOGLE_DRIVE_FOLDER_ID,
21
+ tokensPath: process.env.GOOGLE_TOKENS_PATH || './google-tokens.json',
22
+ },
23
+
24
+ // Backup Configuration
25
+ backup: {
26
+ enabled: process.env.ENABLE_AUTO_BACKUP === 'true',
27
+ intervalMinutes: parseInt(process.env.BACKUP_INTERVAL_MINUTES || '60'),
28
+ excludedDatabases: ['admin', 'config', 'local'],
29
+ },
30
+ }
31
+
32
+ // Validate required configuration
33
+ function validateConfig() {
34
+ const required = ['mongoUri', 'googleOAuth.clientId', 'googleOAuth.clientSecret']
35
+ const missing = []
36
+
37
+ for (const key of required) {
38
+ const keys = key.split('.')
39
+ let value = config
40
+ for (const k of keys) {
41
+ value = value?.[k]
42
+ }
43
+ if (!value) {
44
+ missing.push(key)
45
+ }
46
+ }
47
+
48
+ if (missing.length > 0) {
49
+ console.warn(`āš ļø Missing configuration: ${missing.join(', ')}`)
50
+ }
51
+ }
52
+
53
+ validateConfig()
54
+
55
+ export default config
package/src/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * GD Uploader - Google Drive Backup & Export Module
3
+ * Complete database backup, Excel generation, and Google Drive upload
4
+ */
5
+
6
+ export { createAndUploadCompleteBackup } from './services/backupService.js'
7
+ export { uploadExcelToGoogleDrive, listDriveFiles, deleteOldBackups } from './services/googleDrive.js'
8
+ export { createExcelWorkbook } from './utils/excelFormatter.js'
9
+ export { extractAllDatabasesCollections, extractSpecificDatabases } from './utils/dataExtract.js'
10
+ export { getAuthStatus } from './services/googleAuth.js'
11
+
12
+ // Version info
13
+ export const version = '1.0.0'
14
+ export const name = 'gd-uploader'
@@ -0,0 +1,15 @@
1
+ import express from 'express'
2
+
3
+ const router = express.Router()
4
+
5
+ /**
6
+ * Health check endpoint
7
+ */
8
+ router.get('/status', (_request, response) => {
9
+ response.json({
10
+ message: 'Service Account authentication enabled',
11
+ authenticated: true
12
+ })
13
+ })
14
+
15
+ export default router
@@ -0,0 +1,38 @@
1
+ import express from 'express'
2
+ import mongoose from 'mongoose'
3
+ import { createAndUploadCompleteBackup } from '../services/backupService.js'
4
+ import { getBackupStatus } from '../services/backupScheduler.js'
5
+
6
+ const router = express.Router()
7
+
8
+ /**
9
+ * Complete backup - Extract ALL databases and collections
10
+ * Direct upload to Google Drive (Service Account)
11
+ */
12
+ router.post('/exports', async (request, response) => {
13
+ try {
14
+ if (mongoose.connection.readyState !== 1) {
15
+ return response.status(503).json({ message: 'Database is not connected' })
16
+ }
17
+
18
+ const result = await createAndUploadCompleteBackup({
19
+ uploadToDrive: true,
20
+ workbookName: request.body?.workbookName,
21
+ folderId: request.body?.folderId,
22
+ excludedDatabases: request.body?.excludedDatabases || ['admin', 'config', 'local'],
23
+ })
24
+ return response.status(201).json({ message: 'Backup created and uploaded successfully', ...result })
25
+ } catch (error) {
26
+ console.error('Backup failed:', error)
27
+ return response.status(500).json({ message: error.message || 'Backup failed' })
28
+ }
29
+ })
30
+
31
+ /**
32
+ * Get backup status
33
+ */
34
+ router.get('/backup/status', (_request, response) => {
35
+ response.json(getBackupStatus())
36
+ })
37
+
38
+ export default router
@@ -0,0 +1,44 @@
1
+ import '../config/environment.js'
2
+ import { connectDatabase, disconnectDatabase } from '../config/database.js'
3
+ import { createAndUploadCompleteBackup } from '../services/backupService.js'
4
+
5
+ async function runBackup() {
6
+ try {
7
+ console.log('šŸš€ Starting manual backup...')
8
+ console.log(`ā° ${new Date().toLocaleString()}`)
9
+ console.log('─'.repeat(50))
10
+
11
+ await connectDatabase()
12
+
13
+ const result = await createAndUploadCompleteBackup({
14
+ uploadToDrive: true,
15
+ excludedDatabases: ['admin', 'config', 'local'],
16
+ })
17
+
18
+ console.log('─'.repeat(50))
19
+ console.log('\nšŸ“Š BACKUP SUMMARY:')
20
+ console.log(` Databases: ${result.databases.join(', ')}`)
21
+ console.log(` Collections: ${result.collections.length}`)
22
+ console.log(` Total Records: ${result.totalRecords}`)
23
+ console.log(` File Name: ${result.fileName}`)
24
+ console.log(` Upload Status: ${result.uploadStatus}`)
25
+
26
+ if (result.uploaded && result.driveFile) {
27
+ console.log(`\nāœ… Successfully uploaded to Google Drive!`)
28
+ console.log(` Link: ${result.driveFile.webViewLink}`)
29
+ } else if (result.driveFile?.localPath) {
30
+ console.log(`\nāš ļø File saved locally (Drive upload failed)`)
31
+ console.log(` Path: ${result.driveFile.localPath}`)
32
+ }
33
+
34
+ console.log('\nāœ… Backup completed successfully!')
35
+ } catch (error) {
36
+ console.error('\nāŒ Backup failed:')
37
+ console.error(` Error: ${error.message}`)
38
+ process.exit(1)
39
+ } finally {
40
+ await disconnectDatabase()
41
+ }
42
+ }
43
+
44
+ runBackup()
@@ -0,0 +1,15 @@
1
+ import { connectDatabase } from '../config/database.js'
2
+ import config from '../config/environment.js'
3
+ import { startBackupScheduler } from '../services/backupScheduler.js'
4
+
5
+ async function startScheduler() {
6
+ try {
7
+ await connectDatabase()
8
+ startBackupScheduler(config.backup.intervalMinutes)
9
+ } catch (error) {
10
+ console.error('āŒ Scheduler startup failed:', error.message)
11
+ process.exit(1)
12
+ }
13
+ }
14
+
15
+ startScheduler()