@bopen-io/messagebox-server 1.1.5 → 1.2.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.
Files changed (113) hide show
  1. package/.dockerignore +11 -0
  2. package/.env.example +11 -0
  3. package/.eslintignore +2 -0
  4. package/.gcloudignore +17 -0
  5. package/.gitattributes +2 -0
  6. package/.github/workflows/build-and-push.yml +51 -0
  7. package/.github/workflows/deploy.yaml.example +64 -0
  8. package/.github/workflows/image.yaml +66 -0
  9. package/.vscode/launch.json +67 -0
  10. package/AGENTS.md +92 -0
  11. package/BASELINE.md +55 -0
  12. package/DEPLOYING.md +120 -0
  13. package/Dockerfile +63 -0
  14. package/docker-compose.yml +64 -0
  15. package/jest.config.integration.ts +26 -0
  16. package/jest.config.mjs +42 -0
  17. package/jest.config.ts +35 -0
  18. package/jest.setup.mjs +18 -0
  19. package/nginx.conf +36 -0
  20. package/package.json +65 -51
  21. package/scripts/build.js +19 -0
  22. package/scripts/mkenv.sh +31 -0
  23. package/scripts/start.sh +16 -0
  24. package/src/__tests/compose.test.ts +30 -0
  25. package/src/app.ts +210 -0
  26. package/src/compose.ts +286 -0
  27. package/src/config/firebase.ts +183 -0
  28. package/src/context.ts +49 -0
  29. package/src/index.ts +375 -0
  30. package/src/routes/__tests/acknowledgeMessage.test.ts +158 -0
  31. package/src/routes/__tests/listMessages.test.ts +240 -0
  32. package/src/routes/__tests/sendMessage.test.ts +362 -0
  33. package/src/routes/acknowledgeMessage.ts +153 -0
  34. package/src/routes/index.ts +17 -0
  35. package/src/routes/listDevices.ts +80 -0
  36. package/src/routes/listMessages.ts +195 -0
  37. package/src/routes/permissions/getPermission.ts +152 -0
  38. package/src/routes/permissions/getQuote.ts +192 -0
  39. package/src/routes/permissions/index.ts +12 -0
  40. package/src/routes/permissions/listPermissions.ts +202 -0
  41. package/src/routes/permissions/setPermission.ts +155 -0
  42. package/src/routes/registerDevice.ts +155 -0
  43. package/src/routes/sendMessage.ts +531 -0
  44. package/src/runtimeDeps.ts +29 -0
  45. package/src/swagger.ts +54 -0
  46. package/src/telemetry.ts +158 -0
  47. package/src/types/messagePermissions.ts +18 -0
  48. package/src/types/mock-knex.d.ts +18 -0
  49. package/src/types/notifications.ts +27 -0
  50. package/src/utils/logger.ts +92 -0
  51. package/src/utils/messagePermissions.ts +148 -0
  52. package/src/utils/sendFCMNotification.ts +143 -0
  53. package/tsconfig.json +36 -0
  54. package/tsconfig.types.json +11 -0
  55. package/out/knexfile.js +0 -25
  56. package/out/knexfile.js.map +0 -1
  57. package/out/src/app.js +0 -160
  58. package/out/src/app.js.map +0 -1
  59. package/out/src/config/firebase.js +0 -150
  60. package/out/src/config/firebase.js.map +0 -1
  61. package/out/src/index.js +0 -295
  62. package/out/src/index.js.map +0 -1
  63. package/out/src/migrations/2022-12-28-001-initial-migration.js +0 -28
  64. package/out/src/migrations/2022-12-28-001-initial-migration.js.map +0 -1
  65. package/out/src/migrations/2023-01-17-messages-update.js +0 -11
  66. package/out/src/migrations/2023-01-17-messages-update.js.map +0 -1
  67. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js +0 -21
  68. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js.map +0 -1
  69. package/out/src/migrations/2025-01-31-001-notification-permissions.js +0 -59
  70. package/out/src/migrations/2025-01-31-001-notification-permissions.js.map +0 -1
  71. package/out/src/migrations/2025-01-31-002-device-registrations.js +0 -24
  72. package/out/src/migrations/2025-01-31-002-device-registrations.js.map +0 -1
  73. package/out/src/routes/__tests/acknowledgeMessage.test.js +0 -129
  74. package/out/src/routes/__tests/acknowledgeMessage.test.js.map +0 -1
  75. package/out/src/routes/__tests/listMessages.test.js +0 -211
  76. package/out/src/routes/__tests/listMessages.test.js.map +0 -1
  77. package/out/src/routes/__tests/sendMessage.test.js +0 -307
  78. package/out/src/routes/__tests/sendMessage.test.js.map +0 -1
  79. package/out/src/routes/acknowledgeMessage.js +0 -144
  80. package/out/src/routes/acknowledgeMessage.js.map +0 -1
  81. package/out/src/routes/index.js +0 -17
  82. package/out/src/routes/index.js.map +0 -1
  83. package/out/src/routes/listDevices.js +0 -74
  84. package/out/src/routes/listDevices.js.map +0 -1
  85. package/out/src/routes/listMessages.js +0 -186
  86. package/out/src/routes/listMessages.js.map +0 -1
  87. package/out/src/routes/permissions/getPermission.js +0 -149
  88. package/out/src/routes/permissions/getPermission.js.map +0 -1
  89. package/out/src/routes/permissions/getQuote.js +0 -165
  90. package/out/src/routes/permissions/getQuote.js.map +0 -1
  91. package/out/src/routes/permissions/index.js +0 -12
  92. package/out/src/routes/permissions/index.js.map +0 -1
  93. package/out/src/routes/permissions/listPermissions.js +0 -190
  94. package/out/src/routes/permissions/listPermissions.js.map +0 -1
  95. package/out/src/routes/permissions/setPermission.js +0 -137
  96. package/out/src/routes/permissions/setPermission.js.map +0 -1
  97. package/out/src/routes/registerDevice.js +0 -150
  98. package/out/src/routes/registerDevice.js.map +0 -1
  99. package/out/src/routes/sendMessage.js +0 -451
  100. package/out/src/routes/sendMessage.js.map +0 -1
  101. package/out/src/swagger.js +0 -49
  102. package/out/src/swagger.js.map +0 -1
  103. package/out/src/types/messagePermissions.js +0 -2
  104. package/out/src/types/messagePermissions.js.map +0 -1
  105. package/out/src/types/notifications.js +0 -2
  106. package/out/src/types/notifications.js.map +0 -1
  107. package/out/src/utils/logger.js +0 -24
  108. package/out/src/utils/logger.js.map +0 -1
  109. package/out/src/utils/messagePermissions.js +0 -126
  110. package/out/src/utils/messagePermissions.js.map +0 -1
  111. package/out/src/utils/sendFCMNotification.js +0 -121
  112. package/out/src/utils/sendFCMNotification.js.map +0 -1
  113. package/out/tsconfig.tsbuildinfo +0 -1
package/tsconfig.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": [
4
+ "dom",
5
+ "ESNext"
6
+ ],
7
+ "module": "NodeNext",
8
+ "target": "esnext",
9
+ "moduleResolution": "NodeNext",
10
+ "moduleDetection": "force",
11
+ "rootDir": "./",
12
+ "types": ["node", "jest"],
13
+ "outDir": "./out",
14
+ "strict": true,
15
+ "isolatedModules": true,
16
+ "strictNullChecks": true,
17
+ "skipLibCheck": true,
18
+ "forceConsistentCasingInFileNames": true,
19
+ "incremental": true,
20
+ "sourceMap": true,
21
+ "emitDecoratorMetadata": true,
22
+ "experimentalDecorators": true,
23
+ "resolveJsonModule": true,
24
+ "esModuleInterop": true
25
+ },
26
+ "files": [
27
+ "src/index.ts",
28
+ ],
29
+ "include": [
30
+ "src"
31
+ ],
32
+ "exclude": [
33
+ "out",
34
+ "node_modules"
35
+ ]
36
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "./tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./",
5
+ "outDir": "./out/types",
6
+ "emitDeclarationOnly": true,
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "typeRoots": ["./src/utils/types", "./node_modules/@types"]
10
+ }
11
+ }
package/out/knexfile.js DELETED
@@ -1,25 +0,0 @@
1
- import dotenv from 'dotenv';
2
- dotenv.config();
3
- const connectionConfig = process.env.KNEX_DB_CONNECTION != null && process.env.KNEX_DB_CONNECTION.trim() !== ''
4
- ? JSON.parse(process.env.KNEX_DB_CONNECTION)
5
- : undefined;
6
- const config = {
7
- client: process.env.KNEX_DB_CLIENT ?? 'mysql2',
8
- connection: connectionConfig,
9
- useNullAsDefault: true,
10
- migrations: {
11
- directory: './out/src/migrations'
12
- },
13
- pool: {
14
- min: 0,
15
- max: 7,
16
- idleTimeoutMillis: 15000
17
- }
18
- };
19
- const knexfile = {
20
- development: config,
21
- staging: config,
22
- production: config
23
- };
24
- export default knexfile;
25
- //# sourceMappingURL=knexfile.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"knexfile.js","sourceRoot":"","sources":["../knexfile.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAE3B,MAAM,CAAC,MAAM,EAAE,CAAA;AAEf,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE;IAC7G,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC5C,CAAC,CAAC,SAAS,CAAA;AAEb,MAAM,MAAM,GAAgB;IAC1B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,QAAQ;IAC9C,UAAU,EAAE,gBAAgB;IAC5B,gBAAgB,EAAE,IAAI;IACtB,UAAU,EAAE;QACV,SAAS,EAAE,sBAAsB;KAClC;IACD,IAAI,EAAE;QACJ,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,CAAC;QACN,iBAAiB,EAAE,KAAK;KACzB;CACF,CAAA;AAED,MAAM,QAAQ,GAAmC;IAC/C,WAAW,EAAE,MAAM;IACnB,OAAO,EAAE,MAAM;IACf,UAAU,EAAE,MAAM;CACnB,CAAA;AAED,eAAe,QAAQ,CAAA"}
package/out/src/app.js DELETED
@@ -1,160 +0,0 @@
1
- /**
2
- * @file app.ts
3
- * @description
4
- * Initializes the MessageBoxServer Express app.
5
- *
6
- * Responsibilities:
7
- * - Parses environment variables and loads config
8
- * - Sets up Knex for DB access
9
- * - Initializes WalletClient from the BSV SDK
10
- * - Mounts Express routes (pre-auth and post-auth)
11
- * - Applies auth middleware using wallet identity
12
- *
13
- * This file exports:
14
- * - `app`: the configured Express instance
15
- * - `walletReady`: a promise that resolves once the wallet is ready
16
- * - `getWallet()`: async accessor for the WalletClient
17
- * - `useRoutes()`: middleware + route initialization
18
- * - `appReady`: promise that completes once all setup is done
19
- */
20
- import * as dotenv from 'dotenv';
21
- import express from 'express';
22
- import bodyParser from 'body-parser';
23
- import { preAuth, postAuth } from './routes/index.js';
24
- import { Logger } from './utils/logger.js';
25
- import sendMessageRoute from './routes/sendMessage.js';
26
- import { Setup } from '@bsv/wallet-toolbox';
27
- import knexLib from 'knex';
28
- import knexConfig from '../knexfile.js';
29
- import { createAuthMiddleware } from '@bsv/auth-express-middleware';
30
- import { createPaymentMiddleware } from '@bsv/payment-express-middleware';
31
- import { setupSwagger } from './swagger.js';
32
- import * as crypto from 'crypto';
33
- global.self = { crypto };
34
- dotenv.config();
35
- // Create the Express app instance
36
- export const app = express();
37
- // Load environment variables
38
- const { NODE_ENV = 'development', ROUTING_PREFIX = '', SERVER_PRIVATE_KEY, WALLET_STORAGE_URL, BSV_NETWORK = 'mainnet' } = process.env;
39
- // Enable logger in dev mode or if explicitly enabled
40
- if (NODE_ENV === 'development' || process.env.LOGGING_ENABLED === 'true') {
41
- Logger.enable();
42
- }
43
- /**
44
- * Knex instance connected based on environment (development, production, or staging).
45
- */
46
- export const knex = knexLib.default?.(NODE_ENV === 'production' || NODE_ENV === 'staging'
47
- ? knexConfig.production
48
- : knexConfig.development) ?? knexLib(NODE_ENV === 'production' || NODE_ENV === 'staging'
49
- ? knexConfig.production
50
- : knexConfig.development);
51
- // Wallet initialization logic
52
- let _wallet;
53
- let _resolveReady;
54
- export const walletReady = new Promise((resolve) => {
55
- _resolveReady = resolve;
56
- });
57
- /**
58
- * @function initializeWallet
59
- * @description Initializes the WalletClient with a root identity key and storage backend.
60
- *
61
- * Loads configuration from the environment and connects to the wallet service.
62
- *
63
- * @returns {Promise<void>} Resolves when the wallet is initialized.
64
- * @throws If SERVER_PRIVATE_KEY is missing or invalid.
65
- */
66
- export async function initializeWallet() {
67
- if (SERVER_PRIVATE_KEY == null || SERVER_PRIVATE_KEY.trim() === '') {
68
- throw new Error('SERVER_PRIVATE_KEY is not defined in environment variables.');
69
- }
70
- _wallet = await Setup.createWalletClientNoEnv({
71
- chain: BSV_NETWORK === 'testnet' ? 'test' : 'main',
72
- rootKeyHex: SERVER_PRIVATE_KEY,
73
- storageUrl: WALLET_STORAGE_URL
74
- });
75
- _resolveReady();
76
- }
77
- /**
78
- * @function getWallet
79
- * @description Waits for the WalletClient to be ready and returns the instance.
80
- *
81
- * @returns {Promise<WalletInterface>} The initialized wallet client
82
- * @throws {Error} If called before the wallet is initialized
83
- */
84
- export async function getWallet() {
85
- await walletReady;
86
- if (_wallet == null) {
87
- throw new Error('Wallet has not been initialized yet.');
88
- }
89
- return _wallet;
90
- }
91
- // Run on app startup to prep wallet and activate routes
92
- export const appReady = (async () => {
93
- await initializeWallet();
94
- await useRoutes();
95
- })();
96
- /**
97
- * @function useRoutes
98
- * @description Registers all routes and middleware on the Express app instance.
99
- *
100
- * Steps:
101
- * - Applies JSON body parser
102
- * - Enables CORS headers for all routes
103
- * - Waits for WalletClient to initialize
104
- * - Adds authentication middleware
105
- * - Mounts pre-auth and post-auth route handlers
106
- *
107
- * @returns {Promise<void>} Once all middleware and routes are mounted
108
- * @throws If wallet is not available when needed
109
- */
110
- export async function useRoutes() {
111
- // Parse incoming JSON bodies with a high limit
112
- app.use(bodyParser.json({ limit: '1gb', type: 'application/json' }));
113
- // CORS setup
114
- app.use((req, res, next) => {
115
- res.header('Access-Control-Allow-Origin', '*');
116
- res.header('Access-Control-Allow-Headers', '*');
117
- res.header('Access-Control-Allow-Methods', '*');
118
- res.header('Access-Control-Expose-Headers', '*');
119
- res.header('Access-Control-Allow-Private-Network', 'true');
120
- if (req.method === 'OPTIONS') {
121
- res.sendStatus(200);
122
- }
123
- else {
124
- next();
125
- }
126
- });
127
- // Enable Swagger docs
128
- setupSwagger(app);
129
- await walletReady;
130
- if (_wallet == null) {
131
- throw new Error('Wallet is not initialized for auth middleware');
132
- }
133
- app.use(createAuthMiddleware({
134
- wallet: _wallet,
135
- logger: console
136
- }));
137
- app.use(createPaymentMiddleware({
138
- wallet: _wallet,
139
- calculateRequestPrice: async (req) => {
140
- if (req.url.includes('/sendMessage')) {
141
- // TODO: Configure a custom price calculation as needed.
142
- }
143
- return 0;
144
- }
145
- }));
146
- // Register pre-authentication routes (no auth required)
147
- preAuth.forEach((route) => {
148
- app[route.type](`${String(ROUTING_PREFIX)}${String(route.path)}`, route.func);
149
- });
150
- // Register post-authentication routes (requires auth header)
151
- postAuth.forEach((route) => {
152
- if (route.path === '/sendMessage') {
153
- app[route.type](`${ROUTING_PREFIX}${route.path}`, sendMessageRoute.func);
154
- }
155
- else {
156
- app[route.type](`${ROUTING_PREFIX}${route.path}`, route.func);
157
- }
158
- });
159
- }
160
- //# sourceMappingURL=app.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"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"}
@@ -1,150 +0,0 @@
1
- import { initializeApp, getApps, getApp, cert, applicationDefault } from 'firebase-admin/app';
2
- import { getMessaging } from 'firebase-admin/messaging';
3
- import { getFirestore } from 'firebase-admin/firestore';
4
- import * as path from 'path';
5
- import dotenv from 'dotenv';
6
- dotenv.config();
7
- let firebaseApp = null;
8
- /**
9
- * Initialize Firebase Admin SDK.
10
- * Returns null (and logs a warning) when ENABLE_FIREBASE is not 'true',
11
- * or when FIREBASE_PROJECT_ID is absent, so the server can run without Firebase.
12
- */
13
- export function initializeFirebase() {
14
- const enableFirebase = process.env.ENABLE_FIREBASE;
15
- if (enableFirebase !== 'true') {
16
- console.log(`Firebase is disabled (ENABLE_FIREBASE=${enableFirebase ?? 'unset'}). Skipping initialization.`);
17
- return null;
18
- }
19
- if (firebaseApp != null) {
20
- console.log('Firebase already initialized');
21
- return firebaseApp;
22
- }
23
- try {
24
- const serviceAccountJson = process.env.FIREBASE_SERVICE_ACCOUNT_JSON;
25
- const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;
26
- const projectId = process.env.FIREBASE_PROJECT_ID;
27
- if (projectId == null || projectId === '') {
28
- throw new Error('FIREBASE_PROJECT_ID environment variable is required');
29
- }
30
- let firebaseCredential; // Will be assigned based on auth method
31
- if (serviceAccountJson != null && serviceAccountJson !== '') {
32
- console.log('Using Firebase service account from environment variable');
33
- try {
34
- console.log('Service account JSON length:', serviceAccountJson.length);
35
- console.log('First 100 chars:', serviceAccountJson.substring(0, 100));
36
- // Debug credential functions
37
- console.log('cert function:', typeof cert);
38
- console.log('applicationDefault function:', typeof applicationDefault);
39
- const serviceAccount = JSON.parse(serviceAccountJson);
40
- console.log('Parsed service account keys:', Object.keys(serviceAccount ?? {}));
41
- if (serviceAccount == null || typeof serviceAccount !== 'object') {
42
- throw new Error('Parsed service account is not a valid object');
43
- }
44
- if (serviceAccount.private_key == null || serviceAccount.client_email == null || serviceAccount.project_id == null) {
45
- throw new Error('Service account missing required fields (private_key, client_email, project_id)');
46
- }
47
- firebaseCredential = cert(serviceAccount);
48
- console.log('✅ Firebase credential created successfully');
49
- }
50
- catch (parseError) {
51
- console.error('❌ Firebase service account parsing failed:', parseError);
52
- throw new Error(`Failed to parse FIREBASE_SERVICE_ACCOUNT_JSON: ${(parseError instanceof Error) ? parseError.message : 'Invalid JSON'}`);
53
- }
54
- }
55
- else if (serviceAccountPath != null && serviceAccountPath !== '') {
56
- console.log('Using Firebase service account key file');
57
- const absolutePath = path.resolve(process.cwd(), serviceAccountPath);
58
- // eslint-disable-next-line @typescript-eslint/no-var-requires
59
- firebaseCredential = cert(require(absolutePath));
60
- }
61
- else {
62
- console.log('Using Firebase default credentials');
63
- firebaseCredential = applicationDefault();
64
- }
65
- // Check if Firebase app is already initialized
66
- if (getApps().length === 0) {
67
- firebaseApp = initializeApp({
68
- credential: firebaseCredential,
69
- projectId
70
- });
71
- }
72
- else {
73
- firebaseApp = getApp();
74
- }
75
- console.log('✅ Firebase Admin SDK initialized successfully');
76
- return firebaseApp;
77
- }
78
- catch (error) {
79
- console.error('❌ Firebase initialization failed:', error);
80
- throw error;
81
- }
82
- }
83
- /**
84
- * Get Firebase Messaging instance, or null if Firebase is not initialized.
85
- */
86
- export function getFirebaseMessaging() {
87
- if (firebaseApp == null) {
88
- return null;
89
- }
90
- return getMessaging(firebaseApp);
91
- }
92
- /**
93
- * Get Firestore instance
94
- */
95
- export function getFirebaseFirestore() {
96
- if (firebaseApp == null) {
97
- throw new Error('Firebase not initialized. Call initializeFirebase() first.');
98
- }
99
- return getFirestore(firebaseApp);
100
- }
101
- /**
102
- * Send a push notification via FCM
103
- */
104
- export async function sendNotification(fcmToken, payload) {
105
- try {
106
- const messaging = getFirebaseMessaging();
107
- if (messaging == null) {
108
- throw new Error('Firebase Messaging is not initialized (ENABLE_FIREBASE != true)');
109
- }
110
- const message = {
111
- token: fcmToken,
112
- notification: {
113
- title: payload.title,
114
- body: payload.body,
115
- ...(payload.icon && { imageUrl: payload.icon }),
116
- },
117
- data: payload.data || {},
118
- android: {
119
- priority: "high",
120
- notification: {
121
- clickAction: "OPEN_ACTIVITY_1",
122
- ...(payload.badge && { notificationCount: payload.badge }),
123
- },
124
- },
125
- apns: {
126
- headers: {
127
- "apns-priority": "10",
128
- },
129
- payload: {
130
- aps: {
131
- alert: {
132
- title: payload.title,
133
- body: payload.body,
134
- },
135
- sound: "default",
136
- badge: payload.badge || 1,
137
- },
138
- },
139
- },
140
- };
141
- const response = await messaging.send(message);
142
- console.log("✅ Notification sent successfully:", response);
143
- return { success: true, messageId: response };
144
- }
145
- catch (error) {
146
- console.error("❌ Failed to send notification:", error);
147
- throw error;
148
- }
149
- }
150
- //# sourceMappingURL=firebase.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firebase.js","sourceRoot":"","sources":["../../../src/config/firebase.ts"],"names":[],"mappings":"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"}