@bopen-io/messagebox-server 1.2.1 → 1.2.3

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 (142) hide show
  1. package/out/knexfile.js +25 -0
  2. package/out/knexfile.js.map +1 -0
  3. package/out/src/__tests/compose.test.js +25 -0
  4. package/out/src/__tests/compose.test.js.map +1 -0
  5. package/out/src/app.js +162 -0
  6. package/out/src/app.js.map +1 -0
  7. package/out/src/compose.js +239 -0
  8. package/out/src/compose.js.map +1 -0
  9. package/out/src/config/firebase.js +150 -0
  10. package/out/src/config/firebase.js.map +1 -0
  11. package/out/src/context.js +23 -0
  12. package/out/src/context.js.map +1 -0
  13. package/out/src/index.js +311 -0
  14. package/out/src/index.js.map +1 -0
  15. package/out/src/migrations/2022-12-28-001-initial-migration.js +28 -0
  16. package/out/src/migrations/2022-12-28-001-initial-migration.js.map +1 -0
  17. package/out/src/migrations/2023-01-17-messages-update.js +11 -0
  18. package/out/src/migrations/2023-01-17-messages-update.js.map +1 -0
  19. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js +21 -0
  20. package/out/src/migrations/2024-03-05-001-messageID-upgrade.js.map +1 -0
  21. package/out/src/migrations/2025-01-31-001-notification-permissions.js +59 -0
  22. package/out/src/migrations/2025-01-31-001-notification-permissions.js.map +1 -0
  23. package/out/src/migrations/2025-01-31-002-device-registrations.js +24 -0
  24. package/out/src/migrations/2025-01-31-002-device-registrations.js.map +1 -0
  25. package/out/src/routes/__tests/acknowledgeMessage.test.js +135 -0
  26. package/out/src/routes/__tests/acknowledgeMessage.test.js.map +1 -0
  27. package/out/src/routes/__tests/listMessages.test.js +217 -0
  28. package/out/src/routes/__tests/listMessages.test.js.map +1 -0
  29. package/out/src/routes/__tests/sendMessage.test.js +313 -0
  30. package/out/src/routes/__tests/sendMessage.test.js.map +1 -0
  31. package/out/src/routes/acknowledgeMessage.js +133 -0
  32. package/out/src/routes/acknowledgeMessage.js.map +1 -0
  33. package/out/src/routes/index.js +17 -0
  34. package/out/src/routes/index.js.map +1 -0
  35. package/out/src/routes/listDevices.js +63 -0
  36. package/out/src/routes/listDevices.js.map +1 -0
  37. package/out/src/routes/listMessages.js +176 -0
  38. package/out/src/routes/listMessages.js.map +1 -0
  39. package/out/src/routes/permissions/getPermission.js +138 -0
  40. package/out/src/routes/permissions/getPermission.js.map +1 -0
  41. package/out/src/routes/permissions/getQuote.js +165 -0
  42. package/out/src/routes/permissions/getQuote.js.map +1 -0
  43. package/out/src/routes/permissions/index.js +12 -0
  44. package/out/src/routes/permissions/index.js.map +1 -0
  45. package/out/src/routes/permissions/listPermissions.js +179 -0
  46. package/out/src/routes/permissions/listPermissions.js.map +1 -0
  47. package/out/src/routes/permissions/setPermission.js +137 -0
  48. package/out/src/routes/permissions/setPermission.js.map +1 -0
  49. package/out/src/routes/registerDevice.js +139 -0
  50. package/out/src/routes/registerDevice.js.map +1 -0
  51. package/out/src/routes/sendMessage.js +438 -0
  52. package/out/src/routes/sendMessage.js.map +1 -0
  53. package/out/src/runtimeDeps.js +15 -0
  54. package/out/src/runtimeDeps.js.map +1 -0
  55. package/out/src/swagger.js +48 -0
  56. package/out/src/swagger.js.map +1 -0
  57. package/out/src/telemetry.js +134 -0
  58. package/out/src/telemetry.js.map +1 -0
  59. package/out/src/types/messagePermissions.js +2 -0
  60. package/out/src/types/messagePermissions.js.map +1 -0
  61. package/out/src/types/notifications.js +2 -0
  62. package/out/src/types/notifications.js.map +1 -0
  63. package/out/src/utils/logger.js +85 -0
  64. package/out/src/utils/logger.js.map +1 -0
  65. package/out/src/utils/messagePermissions.js +115 -0
  66. package/out/src/utils/messagePermissions.js.map +1 -0
  67. package/out/src/utils/sendFCMNotification.js +110 -0
  68. package/out/src/utils/sendFCMNotification.js.map +1 -0
  69. package/out/tsconfig.tsbuildinfo +1 -0
  70. package/out/types/jest.config.d.ts +4 -0
  71. package/out/types/jest.config.d.ts.map +1 -0
  72. package/out/types/jest.config.integration.d.ts +5 -0
  73. package/out/types/jest.config.integration.d.ts.map +1 -0
  74. package/out/types/knexfile.d.ts +6 -0
  75. package/out/types/knexfile.d.ts.map +1 -0
  76. package/out/types/src/__tests/compose.test.d.ts +2 -0
  77. package/out/types/src/__tests/compose.test.d.ts.map +1 -0
  78. package/out/types/src/app.d.ts +63 -0
  79. package/out/types/src/app.d.ts.map +1 -0
  80. package/out/types/src/compose.d.ts +22 -0
  81. package/out/types/src/compose.d.ts.map +1 -0
  82. package/out/types/src/config/firebase.d.ts +34 -0
  83. package/out/types/src/config/firebase.d.ts.map +1 -0
  84. package/out/types/src/context.d.ts +23 -0
  85. package/out/types/src/context.d.ts.map +1 -0
  86. package/out/types/src/index.d.ts +43 -0
  87. package/out/types/src/index.d.ts.map +1 -0
  88. package/out/types/src/migrations/2022-12-28-001-initial-migration.d.ts +4 -0
  89. package/out/types/src/migrations/2022-12-28-001-initial-migration.d.ts.map +1 -0
  90. package/out/types/src/migrations/2023-01-17-messages-update.d.ts +4 -0
  91. package/out/types/src/migrations/2023-01-17-messages-update.d.ts.map +1 -0
  92. package/out/types/src/migrations/2024-03-05-001-messageID-upgrade.d.ts +4 -0
  93. package/out/types/src/migrations/2024-03-05-001-messageID-upgrade.d.ts.map +1 -0
  94. package/out/types/src/migrations/2025-01-31-001-notification-permissions.d.ts +4 -0
  95. package/out/types/src/migrations/2025-01-31-001-notification-permissions.d.ts.map +1 -0
  96. package/out/types/src/migrations/2025-01-31-002-device-registrations.d.ts +4 -0
  97. package/out/types/src/migrations/2025-01-31-002-device-registrations.d.ts.map +1 -0
  98. package/out/types/src/routes/__tests/acknowledgeMessage.test.d.ts +2 -0
  99. package/out/types/src/routes/__tests/acknowledgeMessage.test.d.ts.map +1 -0
  100. package/out/types/src/routes/__tests/listMessages.test.d.ts +2 -0
  101. package/out/types/src/routes/__tests/listMessages.test.d.ts.map +1 -0
  102. package/out/types/src/routes/__tests/sendMessage.test.d.ts +2 -0
  103. package/out/types/src/routes/__tests/sendMessage.test.d.ts.map +1 -0
  104. package/out/types/src/routes/acknowledgeMessage.d.ts +100 -0
  105. package/out/types/src/routes/acknowledgeMessage.d.ts.map +1 -0
  106. package/out/types/src/routes/index.d.ts +11 -0
  107. package/out/types/src/routes/index.d.ts.map +1 -0
  108. package/out/types/src/routes/listDevices.d.ts +19 -0
  109. package/out/types/src/routes/listDevices.d.ts.map +1 -0
  110. package/out/types/src/routes/listMessages.d.ts +124 -0
  111. package/out/types/src/routes/listMessages.d.ts.map +1 -0
  112. package/out/types/src/routes/permissions/getPermission.d.ts +46 -0
  113. package/out/types/src/routes/permissions/getPermission.d.ts.map +1 -0
  114. package/out/types/src/routes/permissions/getQuote.d.ts +50 -0
  115. package/out/types/src/routes/permissions/getQuote.d.ts.map +1 -0
  116. package/out/types/src/routes/permissions/index.d.ts +18 -0
  117. package/out/types/src/routes/permissions/index.d.ts.map +1 -0
  118. package/out/types/src/routes/permissions/listPermissions.d.ts +106 -0
  119. package/out/types/src/routes/permissions/listPermissions.d.ts.map +1 -0
  120. package/out/types/src/routes/permissions/setPermission.d.ts +53 -0
  121. package/out/types/src/routes/permissions/setPermission.d.ts.map +1 -0
  122. package/out/types/src/routes/registerDevice.d.ts +67 -0
  123. package/out/types/src/routes/registerDevice.d.ts.map +1 -0
  124. package/out/types/src/routes/sendMessage.d.ts +140 -0
  125. package/out/types/src/routes/sendMessage.d.ts.map +1 -0
  126. package/out/types/src/runtimeDeps.d.ts +17 -0
  127. package/out/types/src/runtimeDeps.d.ts.map +1 -0
  128. package/out/types/src/swagger.d.ts +3 -0
  129. package/out/types/src/swagger.d.ts.map +1 -0
  130. package/out/types/src/telemetry.d.ts +2 -0
  131. package/out/types/src/telemetry.d.ts.map +1 -0
  132. package/out/types/src/types/messagePermissions.d.ts +15 -0
  133. package/out/types/src/types/messagePermissions.d.ts.map +1 -0
  134. package/out/types/src/types/notifications.d.ts +20 -0
  135. package/out/types/src/types/notifications.d.ts.map +1 -0
  136. package/out/types/src/utils/logger.d.ts +17 -0
  137. package/out/types/src/utils/logger.d.ts.map +1 -0
  138. package/out/types/src/utils/messagePermissions.d.ts +29 -0
  139. package/out/types/src/utils/messagePermissions.d.ts.map +1 -0
  140. package/out/types/src/utils/sendFCMNotification.d.ts +22 -0
  141. package/out/types/src/utils/sendFCMNotification.d.ts.map +1 -0
  142. package/package.json +3 -3
@@ -0,0 +1,25 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,25 @@
1
+ /* eslint-env jest */
2
+ import knexLib from 'knex';
3
+ import { createMessageBoxContext, createMessageBoxApp, mountMessageBoxRoutes } from '../compose.js';
4
+ describe('compose API', () => {
5
+ it('createMessageBoxContext requires wallet and knex', () => {
6
+ expect(() => createMessageBoxContext({})).toThrow(/wallet/);
7
+ });
8
+ it('mountMessageBoxRoutes attaches without throwing', () => {
9
+ const knexConfig = { client: 'mysql2', connection: {}, useNullAsDefault: true };
10
+ const knex = knexLib.default?.(knexConfig) ?? knexLib(knexConfig);
11
+ const wallet = {
12
+ getPublicKey: async () => ({ publicKey: '02' + '11'.repeat(32) })
13
+ };
14
+ const app = createMessageBoxApp();
15
+ const ctx = createMessageBoxContext({
16
+ wallet,
17
+ knex,
18
+ enableSwagger: false,
19
+ enableWebSockets: false
20
+ });
21
+ expect(() => { mountMessageBoxRoutes(app, ctx); }).not.toThrow();
22
+ expect(typeof app.use).toBe('function');
23
+ });
24
+ });
25
+ //# sourceMappingURL=compose.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.test.js","sourceRoot":"","sources":["../../../src/__tests/compose.test.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,OAAO,MAAM,MAAM,CAAA;AAC1B,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,eAAe,CAAA;AAEtB,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC,EAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,UAAU,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAA;QAC/E,MAAM,IAAI,GAAI,OAAe,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,IAAK,OAAe,CAAC,UAAU,CAAC,CAAA;QACnF,MAAM,MAAM,GAAG;YACb,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;SAC3D,CAAA;QACR,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAA;QACjC,MAAM,GAAG,GAAG,uBAAuB,CAAC;YAClC,MAAM;YACN,IAAI;YACJ,aAAa,EAAE,KAAK;YACpB,gBAAgB,EAAE,KAAK;SACxB,CAAC,CAAA;QACF,MAAM,CAAC,GAAG,EAAE,GAAG,qBAAqB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;QAC/D,MAAM,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
package/out/src/app.js ADDED
@@ -0,0 +1,162 @@
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 { bindMessageBoxRuntime } from './runtimeDeps.js';
33
+ import * as crypto from 'crypto';
34
+ global.self = { crypto };
35
+ dotenv.config();
36
+ // Create the Express app instance
37
+ export const app = express();
38
+ // Load environment variables
39
+ const { NODE_ENV = 'development', ROUTING_PREFIX = '', SERVER_PRIVATE_KEY, WALLET_STORAGE_URL, BSV_NETWORK = 'mainnet' } = process.env;
40
+ // Enable logger in dev mode or if explicitly enabled
41
+ if (NODE_ENV === 'development' || process.env.LOGGING_ENABLED === 'true') {
42
+ Logger.enable();
43
+ }
44
+ /**
45
+ * Knex instance connected based on environment (development, production, or staging).
46
+ */
47
+ export const knex = knexLib.default?.(NODE_ENV === 'production' || NODE_ENV === 'staging'
48
+ ? knexConfig.production
49
+ : knexConfig.development) ?? knexLib(NODE_ENV === 'production' || NODE_ENV === 'staging'
50
+ ? knexConfig.production
51
+ : knexConfig.development);
52
+ // Wallet initialization logic
53
+ let _wallet;
54
+ let _resolveReady;
55
+ export const walletReady = new Promise((resolve) => {
56
+ _resolveReady = resolve;
57
+ });
58
+ /**
59
+ * @function initializeWallet
60
+ * @description Initializes the WalletClient with a root identity key and storage backend.
61
+ *
62
+ * Loads configuration from the environment and connects to the wallet service.
63
+ *
64
+ * @returns {Promise<void>} Resolves when the wallet is initialized.
65
+ * @throws If SERVER_PRIVATE_KEY is missing or invalid.
66
+ */
67
+ export async function initializeWallet() {
68
+ if (SERVER_PRIVATE_KEY == null || SERVER_PRIVATE_KEY.trim() === '') {
69
+ throw new Error('SERVER_PRIVATE_KEY is not defined in environment variables.');
70
+ }
71
+ _wallet = await Setup.createWalletClientNoEnv({
72
+ chain: BSV_NETWORK === 'testnet' ? 'test' : 'main',
73
+ rootKeyHex: SERVER_PRIVATE_KEY,
74
+ storageUrl: WALLET_STORAGE_URL
75
+ });
76
+ bindMessageBoxRuntime({ knex, wallet: _wallet });
77
+ _resolveReady();
78
+ }
79
+ /**
80
+ * @function getWallet
81
+ * @description Waits for the WalletClient to be ready and returns the instance.
82
+ *
83
+ * @returns {Promise<WalletInterface>} The initialized wallet client
84
+ * @throws {Error} If called before the wallet is initialized
85
+ */
86
+ export async function getWallet() {
87
+ await walletReady;
88
+ if (_wallet == null) {
89
+ throw new Error('Wallet has not been initialized yet.');
90
+ }
91
+ return _wallet;
92
+ }
93
+ // Run on app startup to prep wallet and activate routes
94
+ export const appReady = (async () => {
95
+ await initializeWallet();
96
+ await useRoutes();
97
+ })();
98
+ /**
99
+ * @function useRoutes
100
+ * @description Registers all routes and middleware on the Express app instance.
101
+ *
102
+ * Steps:
103
+ * - Applies JSON body parser
104
+ * - Enables CORS headers for all routes
105
+ * - Waits for WalletClient to initialize
106
+ * - Adds authentication middleware
107
+ * - Mounts pre-auth and post-auth route handlers
108
+ *
109
+ * @returns {Promise<void>} Once all middleware and routes are mounted
110
+ * @throws If wallet is not available when needed
111
+ */
112
+ export async function useRoutes() {
113
+ // Parse incoming JSON bodies with a high limit
114
+ app.use(bodyParser.json({ limit: '1gb', type: 'application/json' }));
115
+ // CORS setup
116
+ app.use((req, res, next) => {
117
+ res.header('Access-Control-Allow-Origin', '*');
118
+ res.header('Access-Control-Allow-Headers', '*');
119
+ res.header('Access-Control-Allow-Methods', '*');
120
+ res.header('Access-Control-Expose-Headers', '*');
121
+ res.header('Access-Control-Allow-Private-Network', 'true');
122
+ if (req.method === 'OPTIONS') {
123
+ res.sendStatus(200);
124
+ }
125
+ else {
126
+ next();
127
+ }
128
+ });
129
+ // Enable Swagger docs
130
+ setupSwagger(app);
131
+ await walletReady;
132
+ if (_wallet == null) {
133
+ throw new Error('Wallet is not initialized for auth middleware');
134
+ }
135
+ app.use(createAuthMiddleware({
136
+ wallet: _wallet,
137
+ logger: console
138
+ }));
139
+ app.use(createPaymentMiddleware({
140
+ wallet: _wallet,
141
+ calculateRequestPrice: async (req) => {
142
+ if (req.url.includes('/sendMessage')) {
143
+ // TODO: Configure a custom price calculation as needed.
144
+ }
145
+ return 0;
146
+ }
147
+ }));
148
+ // Register pre-authentication routes (no auth required)
149
+ preAuth.forEach((route) => {
150
+ app[route.type](`${String(ROUTING_PREFIX)}${String(route.path)}`, route.func);
151
+ });
152
+ // Register post-authentication routes (requires auth header)
153
+ postAuth.forEach((route) => {
154
+ if (route.path === '/sendMessage') {
155
+ app[route.type](`${ROUTING_PREFIX}${route.path}`, sendMessageRoute.func);
156
+ }
157
+ else {
158
+ app[route.type](`${ROUTING_PREFIX}${route.path}`, route.func);
159
+ }
160
+ });
161
+ }
162
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Composable entrypoints for embedding messagebox in a parent app.
3
+ * Standalone binary continues to use index.ts → app.ts as before.
4
+ */
5
+ import express, { Router } from 'express';
6
+ import bodyParser from 'body-parser';
7
+ import { PublicKey } from '@bsv/sdk';
8
+ import { createAuthMiddleware } from '@bsv/auth-express-middleware';
9
+ import { createPaymentMiddleware } from '@bsv/payment-express-middleware';
10
+ import { AuthSocketServer } from '@bsv/authsocket';
11
+ import { preAuth, postAuth } from './routes/index.js';
12
+ import sendMessageRoute from './routes/sendMessage.js';
13
+ import { setupSwagger } from './swagger.js';
14
+ import { Logger } from './utils/logger.js';
15
+ import { bindMessageBoxRuntime } from './runtimeDeps.js';
16
+ export { createMessageBoxContext } from './context.js';
17
+ export function createMessageBoxApp() {
18
+ return express();
19
+ }
20
+ /**
21
+ * Mount messagebox HTTP routes on an Express app.
22
+ * Auth/payment middleware apply only to this router (not the parent app).
23
+ */
24
+ export function mountMessageBoxRoutes(app, ctx) {
25
+ bindMessageBoxRuntime({ knex: ctx.knex, wallet: ctx.wallet });
26
+ const router = Router();
27
+ router.use(bodyParser.json({ limit: '1gb', type: 'application/json' }));
28
+ router.use((req, res, next) => {
29
+ res.header('Access-Control-Allow-Origin', '*');
30
+ res.header('Access-Control-Allow-Headers', '*');
31
+ res.header('Access-Control-Allow-Methods', '*');
32
+ res.header('Access-Control-Expose-Headers', '*');
33
+ res.header('Access-Control-Allow-Private-Network', 'true');
34
+ if (req.method === 'OPTIONS') {
35
+ res.sendStatus(200);
36
+ }
37
+ else {
38
+ next();
39
+ }
40
+ });
41
+ if (ctx.enableSwagger) {
42
+ setupSwagger(app);
43
+ }
44
+ preAuth.forEach((route) => {
45
+ router[route.type](route.path, route.func);
46
+ });
47
+ router.use(createAuthMiddleware({
48
+ wallet: ctx.wallet,
49
+ logger: ctx.logger
50
+ }));
51
+ router.use(createPaymentMiddleware({
52
+ wallet: ctx.wallet,
53
+ calculateRequestPrice: async (req) => await Promise.resolve(ctx.calculateRequestPrice(req))
54
+ }));
55
+ postAuth.forEach((route) => {
56
+ const method = route.type;
57
+ if (route.path === '/sendMessage') {
58
+ router[method](route.path, sendMessageRoute.func);
59
+ }
60
+ else {
61
+ router[method](route.path, route.func);
62
+ }
63
+ });
64
+ const prefix = ctx.routingPrefix ?? '';
65
+ app.use(prefix === '' ? '/' : prefix, router);
66
+ }
67
+ /**
68
+ * Attach authenticated WebSocket handlers. Mirrors standalone index.ts behavior
69
+ * with injected wallet/knex instead of module singletons.
70
+ */
71
+ export function attachMessageBoxWebSockets(httpServer, ctx) {
72
+ if (!ctx.enableWebSockets) {
73
+ return null;
74
+ }
75
+ bindMessageBoxRuntime({ knex: ctx.knex, wallet: ctx.wallet });
76
+ Logger.log('[WEBSOCKET] Initializing WebSocket support...');
77
+ const io = new AuthSocketServer(httpServer, {
78
+ wallet: ctx.wallet,
79
+ cors: {
80
+ origin: '*',
81
+ methods: ['GET', 'POST']
82
+ }
83
+ });
84
+ const knex = ctx.knex;
85
+ const authenticatedSockets = new Map();
86
+ io.on('connection', (socket) => {
87
+ Logger.log('[WEBSOCKET] New connection established.');
88
+ if (typeof socket.identityKey === 'string' && socket.identityKey.trim() !== '') {
89
+ try {
90
+ const parsedIdentityKey = PublicKey.fromString(socket.identityKey);
91
+ Logger.log('[DEBUG] Parsed WebSocket Identity Key Successfully:', parsedIdentityKey.toString());
92
+ authenticatedSockets.set(socket.id, parsedIdentityKey.toString());
93
+ Logger.log('[WEBSOCKET] Identity key stored for socket ID:', socket.id);
94
+ void socket.emit('authenticationSuccess', { status: 'success' });
95
+ }
96
+ catch (error) {
97
+ Logger.error('[ERROR] Failed to parse WebSocket identity key:', error);
98
+ }
99
+ }
100
+ else {
101
+ Logger.warn('[WARN] WebSocket connection received without identity key. Waiting for authentication...');
102
+ let identityKeyHandled = false;
103
+ const authListener = async (data) => {
104
+ if (identityKeyHandled)
105
+ return;
106
+ Logger.log('[WEBSOCKET] Received authentication data:', data);
107
+ if (data?.identityKey != null && data.identityKey.trim().length > 0) {
108
+ try {
109
+ const parsedIdentityKey = PublicKey.fromString(data.identityKey);
110
+ authenticatedSockets.set(socket.id, parsedIdentityKey.toString());
111
+ identityKeyHandled = true;
112
+ await socket.emit('authenticationSuccess', { status: 'success' }).catch(error => {
113
+ Logger.error('[WEBSOCKET ERROR] Failed to send authentication success event:', error);
114
+ });
115
+ }
116
+ catch (error) {
117
+ Logger.error('[ERROR] Failed to parse Identity Key from authenticated event:', error);
118
+ await socket.emit('authenticationFailed', { reason: 'Invalid identity key format' });
119
+ }
120
+ }
121
+ else {
122
+ Logger.warn('[WARN] Invalid or missing identity key in authentication event.');
123
+ await socket.emit('authenticationFailed', { reason: 'Missing identity key' });
124
+ }
125
+ };
126
+ socket.on('authenticated', authListener);
127
+ }
128
+ socket.on('sendMessage', async (data) => {
129
+ if (typeof data !== 'object' || data == null) {
130
+ Logger.error('[WEBSOCKET ERROR] Invalid data object received.');
131
+ await socket.emit('messageFailed', { reason: 'Invalid data object' });
132
+ return;
133
+ }
134
+ const { roomId, message } = data;
135
+ if (!authenticatedSockets.has(socket.id)) {
136
+ Logger.warn('[WEBSOCKET] Unauthorized attempt to send a message.');
137
+ await socket.emit('paymentFailed', { reason: 'Unauthorized: WebSocket not authenticated' });
138
+ return;
139
+ }
140
+ try {
141
+ if (typeof roomId !== 'string' || roomId.trim() === '') {
142
+ await socket.emit('messageFailed', { reason: 'Invalid room ID' });
143
+ return;
144
+ }
145
+ if (typeof message !== 'object' || message == null) {
146
+ await socket.emit('messageFailed', { reason: 'Invalid message object' });
147
+ return;
148
+ }
149
+ if (typeof message.body !== 'string' || message.body.trim() === '') {
150
+ await socket.emit('messageFailed', { reason: 'Invalid message body' });
151
+ return;
152
+ }
153
+ socket.emit(`sendMessageAck-${roomId}`, {
154
+ status: 'success',
155
+ messageId: message.messageId
156
+ }).catch((error) => {
157
+ Logger.error(`[WEBSOCKET ERROR] Failed to emit sendMessageAck-${roomId}:`, error);
158
+ });
159
+ try {
160
+ const parts = roomId.split('-');
161
+ const messageBoxType = parts.length > 1 ? parts[1] : 'default';
162
+ let messageBox = await knex('messageBox')
163
+ .where({ identityKey: message.recipient, type: messageBoxType })
164
+ .first();
165
+ if (messageBox == null) {
166
+ await knex('messageBox').insert({
167
+ identityKey: message.recipient,
168
+ type: messageBoxType,
169
+ created_at: new Date(),
170
+ updated_at: new Date()
171
+ });
172
+ }
173
+ messageBox = await knex('messageBox')
174
+ .where({ identityKey: message.recipient, type: messageBoxType })
175
+ .select('messageBoxId')
176
+ .first();
177
+ const messageBoxId = messageBox?.messageBoxId ?? null;
178
+ const senderKey = authenticatedSockets.get(socket.id) ?? null;
179
+ await knex('messages')
180
+ .insert({
181
+ messageId: message.messageId,
182
+ messageBoxId,
183
+ sender: senderKey,
184
+ recipient: message.recipient,
185
+ body: message.body,
186
+ created_at: new Date(),
187
+ updated_at: new Date()
188
+ })
189
+ .onConflict('messageId')
190
+ .ignore();
191
+ }
192
+ catch (dbError) {
193
+ Logger.error('[WEBSOCKET ERROR] Failed to store message in DB:', dbError);
194
+ await socket.emit('messageFailed', { reason: 'Failed to store message' });
195
+ return;
196
+ }
197
+ io.emit(`sendMessage-${roomId}`, {
198
+ sender: authenticatedSockets.get(socket.id),
199
+ messageId: message.messageId,
200
+ body: message.body
201
+ });
202
+ }
203
+ catch (error) {
204
+ Logger.error('[WEBSOCKET ERROR] Unexpected failure in sendMessage handler:', error);
205
+ await socket.emit('messageFailed', { reason: 'Unexpected error occurred' });
206
+ }
207
+ });
208
+ socket.on('joinRoom', async (roomId) => {
209
+ if (!authenticatedSockets.has(socket.id)) {
210
+ await socket.emit('joinFailed', { reason: 'Unauthorized: WebSocket not authenticated' });
211
+ return;
212
+ }
213
+ if (typeof roomId !== 'string' || roomId.trim() === '') {
214
+ await socket.emit('joinFailed', { reason: 'Invalid room ID' });
215
+ return;
216
+ }
217
+ Logger.log(`[WEBSOCKET] User ${socket.id} joined room ${roomId}`);
218
+ await socket.emit('joinedRoom', { roomId });
219
+ });
220
+ socket.on('leaveRoom', async (roomId) => {
221
+ if (!authenticatedSockets.has(socket.id)) {
222
+ await socket.emit('leaveFailed', { reason: 'Unauthorized: WebSocket not authenticated' });
223
+ return;
224
+ }
225
+ if (typeof roomId !== 'string' || roomId.trim() === '') {
226
+ await socket.emit('leaveFailed', { reason: 'Invalid room ID' });
227
+ return;
228
+ }
229
+ Logger.log(`[WEBSOCKET] User ${socket.id} left room ${roomId}`);
230
+ await socket.emit('leftRoom', { roomId });
231
+ });
232
+ socket.on('disconnect', (reason) => {
233
+ Logger.log(`[WEBSOCKET] Disconnected: ${reason}`);
234
+ authenticatedSockets.delete(socket.id);
235
+ });
236
+ });
237
+ return io;
238
+ }
239
+ //# sourceMappingURL=compose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/compose.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
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
+ import { log } from '../utils/logger.js';
7
+ dotenv.config();
8
+ let firebaseApp = null;
9
+ /**
10
+ * Initialize Firebase Admin SDK.
11
+ * Returns null (and logs a warning) when ENABLE_FIREBASE is not 'true',
12
+ * or when FIREBASE_PROJECT_ID is absent, so the server can run without Firebase.
13
+ */
14
+ export function initializeFirebase() {
15
+ const enableFirebase = process.env.ENABLE_FIREBASE;
16
+ if (enableFirebase !== 'true') {
17
+ log.info({ operation: 'firebase.init', enable_firebase: enableFirebase ?? 'unset' }, 'Firebase disabled, skipping initialization');
18
+ return null;
19
+ }
20
+ if (firebaseApp != null) {
21
+ log.info({ operation: 'firebase.init' }, 'Firebase already initialized');
22
+ return firebaseApp;
23
+ }
24
+ try {
25
+ const serviceAccountJson = process.env.FIREBASE_SERVICE_ACCOUNT_JSON;
26
+ const serviceAccountPath = process.env.FIREBASE_SERVICE_ACCOUNT_PATH;
27
+ const projectId = process.env.FIREBASE_PROJECT_ID;
28
+ if (projectId == null || projectId === '') {
29
+ throw new Error('FIREBASE_PROJECT_ID environment variable is required');
30
+ }
31
+ let firebaseCredential; // Will be assigned based on auth method
32
+ if (serviceAccountJson != null && serviceAccountJson !== '') {
33
+ log.info({ operation: 'firebase.init', credential_source: 'env' }, 'Using Firebase service account from environment variable');
34
+ try {
35
+ log.debug({ operation: 'firebase.init', service_account_json_length: serviceAccountJson.length }, 'Service account JSON length');
36
+ // Debug credential functions
37
+ log.debug({ operation: 'firebase.init', cert_function_type: typeof cert }, 'cert function type');
38
+ log.debug({ operation: 'firebase.init', application_default_function_type: typeof applicationDefault }, 'applicationDefault function type');
39
+ const serviceAccount = JSON.parse(serviceAccountJson);
40
+ log.debug({ operation: 'firebase.init', service_account_keys: Object.keys(serviceAccount ?? {}) }, 'Parsed service account keys');
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
+ log.info({ operation: 'firebase.init' }, 'Firebase credential created successfully');
49
+ }
50
+ catch (parseError) {
51
+ log.error({ operation: 'firebase.init', outcome: 'error', err: parseError }, 'Firebase service account parsing failed');
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
+ log.info({ operation: 'firebase.init', credential_source: 'file' }, '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
+ log.info({ operation: 'firebase.init', credential_source: 'default' }, '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
+ log.info({ operation: 'firebase.init' }, 'Firebase Admin SDK initialized successfully');
76
+ return firebaseApp;
77
+ }
78
+ catch (error) {
79
+ log.error({ operation: 'firebase.init', outcome: 'error', err: error }, 'Firebase initialization failed');
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
+ log.info({ operation: 'firebase.send_notification', message_id: response }, 'Notification sent successfully');
143
+ return { success: true, messageId: response };
144
+ }
145
+ catch (error) {
146
+ log.error({ operation: 'firebase.send_notification', outcome: 'error', err: error }, 'Failed to send notification');
147
+ throw error;
148
+ }
149
+ }
150
+ //# sourceMappingURL=firebase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase.js","sourceRoot":"","sources":["../../../src/config/firebase.ts"],"names":[],"mappings":"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"}