@enbox/dwn-server 0.0.2 → 0.0.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 (146) hide show
  1. package/README.md +13 -13
  2. package/dist/esm/src/config.d.ts +2 -6
  3. package/dist/esm/src/config.d.ts.map +1 -1
  4. package/dist/esm/src/config.js +4 -8
  5. package/dist/esm/src/config.js.map +1 -1
  6. package/dist/esm/src/connection/connection-manager.d.ts +9 -9
  7. package/dist/esm/src/connection/connection-manager.d.ts.map +1 -1
  8. package/dist/esm/src/connection/connection-manager.js +5 -3
  9. package/dist/esm/src/connection/connection-manager.js.map +1 -1
  10. package/dist/esm/src/connection/socket-connection.d.ts +18 -17
  11. package/dist/esm/src/connection/socket-connection.d.ts.map +1 -1
  12. package/dist/esm/src/connection/socket-connection.js +26 -35
  13. package/dist/esm/src/connection/socket-connection.js.map +1 -1
  14. package/dist/esm/src/dwn-error.js.map +1 -1
  15. package/dist/esm/src/dwn-server.d.ts +5 -6
  16. package/dist/esm/src/dwn-server.d.ts.map +1 -1
  17. package/dist/esm/src/dwn-server.js +3 -14
  18. package/dist/esm/src/dwn-server.js.map +1 -1
  19. package/dist/esm/src/http-api.d.ts +9 -11
  20. package/dist/esm/src/http-api.d.ts.map +1 -1
  21. package/dist/esm/src/http-api.js +450 -375
  22. package/dist/esm/src/http-api.js.map +1 -1
  23. package/dist/esm/src/json-rpc-handlers/dwn/process-message.d.ts.map +1 -1
  24. package/dist/esm/src/json-rpc-handlers/dwn/process-message.js +3 -3
  25. package/dist/esm/src/json-rpc-handlers/dwn/process-message.js.map +1 -1
  26. package/dist/esm/src/json-rpc-handlers/subscription/close.d.ts.map +1 -1
  27. package/dist/esm/src/json-rpc-handlers/subscription/close.js.map +1 -1
  28. package/dist/esm/src/json-rpc-socket.d.ts +1 -1
  29. package/dist/esm/src/json-rpc-socket.d.ts.map +1 -1
  30. package/dist/esm/src/json-rpc-socket.js +1 -1
  31. package/dist/esm/src/json-rpc-socket.js.map +1 -1
  32. package/dist/esm/src/lib/json-rpc-router.d.ts +3 -4
  33. package/dist/esm/src/lib/json-rpc-router.d.ts.map +1 -1
  34. package/dist/esm/src/lib/json-rpc-router.js.map +1 -1
  35. package/dist/esm/src/lib/json-rpc.d.ts.map +1 -1
  36. package/dist/esm/src/lib/json-rpc.js.map +1 -1
  37. package/dist/esm/src/main.js +0 -0
  38. package/dist/esm/src/metrics.d.ts +1 -1
  39. package/dist/esm/src/metrics.js.map +1 -1
  40. package/dist/esm/src/registration/proof-of-work-manager.d.ts +1 -1
  41. package/dist/esm/src/registration/proof-of-work-manager.d.ts.map +1 -1
  42. package/dist/esm/src/registration/proof-of-work-manager.js +3 -3
  43. package/dist/esm/src/registration/proof-of-work-manager.js.map +1 -1
  44. package/dist/esm/src/registration/registration-manager.d.ts +3 -3
  45. package/dist/esm/src/registration/registration-manager.d.ts.map +1 -1
  46. package/dist/esm/src/registration/registration-manager.js +6 -6
  47. package/dist/esm/src/registration/registration-manager.js.map +1 -1
  48. package/dist/esm/src/registration/registration-store.d.ts +1 -1
  49. package/dist/esm/src/registration/registration-store.d.ts.map +1 -1
  50. package/dist/esm/src/registration/registration-store.js.map +1 -1
  51. package/dist/esm/src/storage.d.ts +2 -2
  52. package/dist/esm/src/storage.d.ts.map +1 -1
  53. package/dist/esm/src/storage.js +5 -4
  54. package/dist/esm/src/storage.js.map +1 -1
  55. package/dist/esm/src/web5-connect/sql-ttl-cache.d.ts.map +1 -1
  56. package/dist/esm/src/web5-connect/sql-ttl-cache.js +3 -2
  57. package/dist/esm/src/web5-connect/sql-ttl-cache.js.map +1 -1
  58. package/dist/esm/src/web5-connect/web5-connect-server.d.ts.map +1 -1
  59. package/dist/esm/src/web5-connect/web5-connect-server.js +2 -2
  60. package/dist/esm/src/web5-connect/web5-connect-server.js.map +1 -1
  61. package/dist/esm/src/ws-api.d.ts +2 -4
  62. package/dist/esm/src/ws-api.d.ts.map +1 -1
  63. package/dist/esm/src/ws-api.js +6 -17
  64. package/dist/esm/src/ws-api.js.map +1 -1
  65. package/dist/esm/tests/common-scenario-validator.d.ts.map +1 -1
  66. package/dist/esm/tests/common-scenario-validator.js +2 -3
  67. package/dist/esm/tests/common-scenario-validator.js.map +1 -1
  68. package/dist/esm/tests/connection/connection-manager.spec.js +11 -9
  69. package/dist/esm/tests/connection/connection-manager.spec.js.map +1 -1
  70. package/dist/esm/tests/connection/socket-connection.spec.js +40 -18
  71. package/dist/esm/tests/connection/socket-connection.spec.js.map +1 -1
  72. package/dist/esm/tests/cors/http-api.browser.js +1 -1
  73. package/dist/esm/tests/cors/http-api.browser.js.map +1 -1
  74. package/dist/esm/tests/dwn-process-message.spec.js +4 -4
  75. package/dist/esm/tests/dwn-process-message.spec.js.map +1 -1
  76. package/dist/esm/tests/dwn-server.spec.js +8 -9
  77. package/dist/esm/tests/dwn-server.spec.js.map +1 -1
  78. package/dist/esm/tests/http-api.spec.js +92 -85
  79. package/dist/esm/tests/http-api.spec.js.map +1 -1
  80. package/dist/esm/tests/json-rpc-socket.spec.js +11 -9
  81. package/dist/esm/tests/json-rpc-socket.spec.js.map +1 -1
  82. package/dist/esm/tests/plugins/data-store-sqlite.d.ts +2 -2
  83. package/dist/esm/tests/plugins/data-store-sqlite.js +2 -2
  84. package/dist/esm/tests/plugins/event-log-sqlite.d.ts +2 -2
  85. package/dist/esm/tests/plugins/event-log-sqlite.js +2 -2
  86. package/dist/esm/tests/plugins/event-stream-in-memory.d.ts +2 -2
  87. package/dist/esm/tests/plugins/event-stream-in-memory.d.ts.map +1 -1
  88. package/dist/esm/tests/plugins/event-stream-in-memory.js +1 -1
  89. package/dist/esm/tests/plugins/event-stream-in-memory.js.map +1 -1
  90. package/dist/esm/tests/plugins/message-store-sqlite.d.ts +2 -2
  91. package/dist/esm/tests/plugins/message-store-sqlite.d.ts.map +1 -1
  92. package/dist/esm/tests/plugins/message-store-sqlite.js +2 -2
  93. package/dist/esm/tests/plugins/message-store-sqlite.js.map +1 -1
  94. package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts +2 -2
  95. package/dist/esm/tests/plugins/resumable-task-store-sqlite.d.ts.map +1 -1
  96. package/dist/esm/tests/plugins/resumable-task-store-sqlite.js +2 -2
  97. package/dist/esm/tests/plugins/resumable-task-store-sqlite.js.map +1 -1
  98. package/dist/esm/tests/process-handler.spec.js +6 -6
  99. package/dist/esm/tests/process-handler.spec.js.map +1 -1
  100. package/dist/esm/tests/registration/proof-of-work-manager.spec.js +3 -4
  101. package/dist/esm/tests/registration/proof-of-work-manager.spec.js.map +1 -1
  102. package/dist/esm/tests/rpc-subscribe-close.spec.js +1 -1
  103. package/dist/esm/tests/rpc-subscribe-close.spec.js.map +1 -1
  104. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js +11 -10
  105. package/dist/esm/tests/scenarios/dynamic-plugin-loading.spec.js.map +1 -1
  106. package/dist/esm/tests/scenarios/registration.spec.js +16 -12
  107. package/dist/esm/tests/scenarios/registration.spec.js.map +1 -1
  108. package/dist/esm/tests/scenarios/web5-connect.spec.js +12 -8
  109. package/dist/esm/tests/scenarios/web5-connect.spec.js.map +1 -1
  110. package/dist/esm/tests/test-dwn.d.ts.map +1 -1
  111. package/dist/esm/tests/test-dwn.js +9 -15
  112. package/dist/esm/tests/test-dwn.js.map +1 -1
  113. package/dist/esm/tests/utils.d.ts +3 -6
  114. package/dist/esm/tests/utils.d.ts.map +1 -1
  115. package/dist/esm/tests/utils.js +9 -18
  116. package/dist/esm/tests/utils.js.map +1 -1
  117. package/dist/esm/tests/ws-api.spec.js +28 -23
  118. package/dist/esm/tests/ws-api.spec.js.map +1 -1
  119. package/package.json +25 -44
  120. package/src/config.ts +15 -19
  121. package/src/connection/connection-manager.ts +18 -12
  122. package/src/connection/socket-connection.ts +52 -57
  123. package/src/dwn-error.ts +2 -2
  124. package/src/dwn-server.ts +17 -30
  125. package/src/http-api.ts +499 -396
  126. package/src/json-rpc-handlers/dwn/process-message.ts +9 -10
  127. package/src/json-rpc-handlers/subscription/close.ts +4 -4
  128. package/src/json-rpc-socket.ts +3 -2
  129. package/src/lib/json-rpc-router.ts +5 -6
  130. package/src/lib/json-rpc.ts +6 -6
  131. package/src/metrics.ts +7 -7
  132. package/src/process-handlers.ts +5 -5
  133. package/src/registration/proof-of-work-manager.ts +11 -10
  134. package/src/registration/registration-manager.ts +23 -21
  135. package/src/registration/registration-store.ts +8 -7
  136. package/src/storage.ts +15 -13
  137. package/src/web5-connect/sql-ttl-cache.ts +5 -4
  138. package/src/web5-connect/web5-connect-server.ts +9 -8
  139. package/src/ws-api.ts +11 -26
  140. package/dist/cjs/index.js +0 -6811
  141. package/dist/cjs/package.json +0 -1
  142. package/dist/esm/src/lib/http-server-shutdown-handler.d.ts +0 -10
  143. package/dist/esm/src/lib/http-server-shutdown-handler.d.ts.map +0 -1
  144. package/dist/esm/src/lib/http-server-shutdown-handler.js +0 -65
  145. package/dist/esm/src/lib/http-server-shutdown-handler.js.map +0 -1
  146. package/src/lib/http-server-shutdown-handler.ts +0 -79
@@ -1,7 +1,6 @@
1
1
  import type { GenericMessage } from '@enbox/dwn-sdk-js';
2
2
  import { DwnInterfaceName, DwnMethodName } from '@enbox/dwn-sdk-js';
3
3
 
4
- import type { Readable as IsomorphicReadable } from 'readable-stream';
5
4
  import log from 'loglevel';
6
5
  import { v4 as uuidv4 } from 'uuid';
7
6
 
@@ -28,7 +27,7 @@ export const handleDwnProcessMessage: JsonRpcHandler = async (
28
27
 
29
28
  try {
30
29
  // RecordsWrite is only supported on 'http' to support data stream for large data
31
- // TODO: https://github.com/TBD54566975/dwn-server/issues/108
30
+ // TODO: https://github.com/enboxorg/enbox/issues/108
32
31
  if (
33
32
  transport !== 'http' &&
34
33
  message.descriptor.interface === DwnInterfaceName.Records &&
@@ -38,11 +37,11 @@ export const handleDwnProcessMessage: JsonRpcHandler = async (
38
37
  requestId,
39
38
  JsonRpcErrorCodes.InvalidParams,
40
39
  `RecordsWrite is not supported via ${context.transport}`
41
- )
40
+ );
42
41
  return { jsonRpcResponse };
43
42
  }
44
43
 
45
- // subscribe methods must come with a subscriptionRequest context
44
+ // subscribe methods must come with a subscriptionRequest context
46
45
  if (message.descriptor.method === DwnMethodName.Subscribe && subscriptionRequest === undefined) {
47
46
  const jsonRpcResponse = createJsonRpcErrorResponse(
48
47
  requestId,
@@ -58,7 +57,7 @@ export const handleDwnProcessMessage: JsonRpcHandler = async (
58
57
  requestId,
59
58
  JsonRpcErrorCodes.InvalidParams,
60
59
  `subscriptions are not supported via ${context.transport}`
61
- )
60
+ );
62
61
  return { jsonRpcResponse };
63
62
  }
64
63
 
@@ -70,12 +69,12 @@ export const handleDwnProcessMessage: JsonRpcHandler = async (
70
69
  requestId,
71
70
  JsonRpcErrorCodes.InvalidParams,
72
71
  `the subscribe id: ${subscriptionRequest.id} is in use by an active subscription`
73
- )
72
+ );
74
73
  return { jsonRpcResponse };
75
74
  }
76
75
 
77
76
  const reply = await dwn.processMessage(target, message, {
78
- dataStream: dataStream as IsomorphicReadable,
77
+ dataStream,
79
78
  subscriptionHandler: subscriptionRequest?.subscriptionHandler,
80
79
  });
81
80
 
@@ -83,7 +82,7 @@ export const handleDwnProcessMessage: JsonRpcHandler = async (
83
82
  const { entry } = reply;
84
83
  // RecordsRead or MessagesRead messages optionally return data as a stream to accommodate large amounts of data
85
84
  // we remove the data stream from the reply that will be serialized and return it as a separate property in the response payload.
86
- let recordDataStream: IsomorphicReadable;
85
+ let recordDataStream: ReadableStream<Uint8Array>;
87
86
  if (entry !== undefined && entry.data !== undefined) {
88
87
  recordDataStream = entry.data;
89
88
  delete reply.entry.data; // not serializable via JSON
@@ -97,9 +96,9 @@ export const handleDwnProcessMessage: JsonRpcHandler = async (
97
96
  const subscriptionReply: JsonRpcSubscription = {
98
97
  id: subscriptionRequest.id,
99
98
  close,
100
- }
99
+ };
101
100
  await socketConnection.addSubscription(subscriptionReply);
102
- delete reply.subscription.close // delete the close method from the reply as it's not JSON serializable and has a held reference.
101
+ delete reply.subscription.close; // delete the close method from the reply as it's not JSON serializable and has a held reference.
103
102
  }
104
103
 
105
104
  const jsonRpcResponse = createJsonRpcSuccessResponse(requestId, { reply });
@@ -1,12 +1,12 @@
1
1
  import { v4 as uuidv4 } from 'uuid';
2
2
 
3
- import { DwnServerErrorCode } from '../../dwn-error.js';
4
3
  import type {
5
4
  HandlerResponse,
6
5
  JsonRpcHandler,
7
6
  } from '../../lib/json-rpc-router.js';
8
-
9
7
  import type { JsonRpcId, JsonRpcResponse } from '../../lib/json-rpc.js';
8
+
9
+ import { DwnServerErrorCode } from '../../dwn-error.js';
10
10
  import {
11
11
  createJsonRpcErrorResponse,
12
12
  createJsonRpcSuccessResponse,
@@ -43,7 +43,7 @@ export const handleSubscriptionsClose: JsonRpcHandler = async (
43
43
  // closing the subscription and cleaning up the reference within the given connection.
44
44
  await socketConnection.closeSubscription(id);
45
45
  jsonRpcResponse = createJsonRpcSuccessResponse(requestId, { reply: { status: 200, detail: 'Accepted' } });
46
- } catch(error) {
46
+ } catch (error) {
47
47
  if (error.code === DwnServerErrorCode.ConnectionSubscriptionJsonRpcIdNotFound) {
48
48
  jsonRpcResponse = createJsonRpcErrorResponse(requestId, JsonRpcErrorCodes.InvalidParams, `subscription ${id} does not exist.`);
49
49
  } else {
@@ -56,4 +56,4 @@ export const handleSubscriptionsClose: JsonRpcHandler = async (
56
56
  }
57
57
 
58
58
  return { jsonRpcResponse } as HandlerResponse;
59
- }
59
+ };
@@ -2,8 +2,9 @@ import log from 'loglevel';
2
2
  import { v4 as uuidv4 } from 'uuid';
3
3
  import WebSocket from 'ws';
4
4
 
5
- import type { JsonRpcId, JsonRpcRequest, JsonRpcResponse } from "./lib/json-rpc.js";
6
- import { createJsonRpcSubscriptionRequest } from "./lib/json-rpc.js";
5
+ import type { JsonRpcId, JsonRpcRequest, JsonRpcResponse } from './lib/json-rpc.js';
6
+
7
+ import { createJsonRpcSubscriptionRequest } from './lib/json-rpc.js';
7
8
 
8
9
  // These were arbitrarily chosen, but can be modified via connect options
9
10
  const CONNECT_TIMEOUT = 3_000;
@@ -1,8 +1,7 @@
1
1
  import type { Dwn, MessageSubscriptionHandler } from '@enbox/dwn-sdk-js';
2
2
 
3
- import type { Readable } from 'node:stream';
4
-
5
3
  import type { JsonRpcId, JsonRpcRequest, JsonRpcResponse } from './json-rpc.js';
4
+
6
5
  import type { SocketConnection } from '../connection/socket-connection.js';
7
6
 
8
7
  export type RequestContext = {
@@ -12,17 +11,17 @@ export type RequestContext = {
12
11
  socketConnection?: SocketConnection;
13
12
  subscriptionRequest?: {
14
13
  /** The JsonRpcId of the subscription handler */
15
- id: JsonRpcId;
14
+ id: JsonRpcId;
16
15
  /** The `MessageEvent` handler associated with a subscription request, only used in `ws` requests */
17
16
  subscriptionHandler: MessageSubscriptionHandler;
18
17
  }
19
- /** The `Readable` stream associated with a `RecordsWrite` request only used in `http` requests */
20
- dataStream?: Readable;
18
+ /** The `ReadableStream` associated with a `RecordsWrite` request only used in `http` requests */
19
+ dataStream?: ReadableStream<Uint8Array>;
21
20
  };
22
21
 
23
22
  export type HandlerResponse = {
24
23
  jsonRpcResponse: JsonRpcResponse;
25
- dataStream?: Readable;
24
+ dataStream?: ReadableStream<Uint8Array>;
26
25
  };
27
26
 
28
27
  export type JsonRpcHandler = (
@@ -91,15 +91,15 @@ export const createJsonRpcSubscriptionRequest = (
91
91
  subscriptionId?: JsonRpcId
92
92
  ): JsonRpcRequest => {
93
93
  return {
94
- jsonrpc: '2.0',
94
+ jsonrpc : '2.0',
95
95
  id,
96
96
  method,
97
97
  params,
98
- subscription: {
98
+ subscription : {
99
99
  id: subscriptionId,
100
100
  }
101
- }
102
- }
101
+ };
102
+ };
103
103
 
104
104
  export const createJsonRpcRequest = (
105
105
  id: JsonRpcId,
@@ -119,8 +119,8 @@ export const createJsonRpcSuccessResponse = (
119
119
  result?: any,
120
120
  ): JsonRpcSuccessResponse => {
121
121
  return {
122
- jsonrpc: '2.0',
122
+ jsonrpc : '2.0',
123
123
  id,
124
- result: result ?? null,
124
+ result : result ?? null,
125
125
  };
126
126
  };
package/src/metrics.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import { Counter, Histogram } from 'prom-client';
2
2
 
3
3
  export const requestCounter = new Counter({
4
- name: 'dwn_requests_total',
5
- help: 'all dwn requests processed',
6
- labelNames: ['method', 'status', 'error'],
4
+ name : 'dwn_requests_total',
5
+ help : 'all dwn requests processed',
6
+ labelNames : ['method', 'status', 'error'],
7
7
  });
8
8
 
9
9
  export const responseHistogram = new Histogram({
10
- name: 'http_response',
11
- help: 'response histogram',
12
- buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
13
- labelNames: ['route', 'code'],
10
+ name : 'http_response',
11
+ help : 'response histogram',
12
+ buckets : [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
13
+ labelNames : ['route', 'code'],
14
14
  });
@@ -51,11 +51,11 @@ export const setProcessHandlers = (dwnServer: DwnServer): ProcessHandlers => {
51
51
  };
52
52
 
53
53
  export const removeProcessHandlers = (handlers: ProcessHandlers): void => {
54
- const {
55
- unhandledRejectionHandler,
56
- uncaughtExceptionHandler,
57
- sigintHandler,
58
- sigtermHandler
54
+ const {
55
+ unhandledRejectionHandler,
56
+ uncaughtExceptionHandler,
57
+ sigintHandler,
58
+ sigtermHandler
59
59
  } = handlers;
60
60
 
61
61
  process.removeListener('unhandledRejection', unhandledRejectionHandler);
@@ -1,6 +1,7 @@
1
- import { DwnServerError, DwnServerErrorCode } from "../dwn-error.js";
2
- import type { ProofOfWorkChallengeModel } from "./proof-of-work-types.js";
3
- import { ProofOfWork } from "./proof-of-work.js";
1
+ import type { ProofOfWorkChallengeModel } from './proof-of-work-types.js';
2
+
3
+ import { ProofOfWork } from './proof-of-work.js';
4
+ import { DwnServerError, DwnServerErrorCode } from '../dwn-error.js';
4
5
 
5
6
  /**
6
7
  * Manages proof-of-work challenge difficulty and lifecycle based on solve rate.
@@ -18,7 +19,7 @@ export class ProofOfWorkManager {
18
19
  };
19
20
 
20
21
  // There is opportunity to improve implementation here.
21
- // TODO: https://github.com/TBD54566975/dwn-server/issues/101
22
+ // TODO: https://github.com/enboxorg/enbox/issues/101
22
23
  private proofOfWorkOfLastMinute: Map<string, number> = new Map(); // proofOfWorkId -> timestamp of proof-of-work
23
24
 
24
25
  // Seed to generate the challenge nonce from, this allows all DWN instances in a cluster to generate the same challenge.
@@ -122,8 +123,8 @@ export class ProofOfWorkManager {
122
123
 
123
124
  public getProofOfWorkChallenge(): ProofOfWorkChallengeModel {
124
125
  return {
125
- challengeNonce: this.challengeNonces.currentChallengeNonce,
126
- maximumAllowedHashValue: ProofOfWorkManager.bigIntToHexString(this.currentMaximumAllowedHashValue),
126
+ challengeNonce : this.challengeNonces.currentChallengeNonce,
127
+ maximumAllowedHashValue : ProofOfWorkManager.bigIntToHexString(this.currentMaximumAllowedHashValue),
127
128
  };
128
129
  }
129
130
 
@@ -228,7 +229,7 @@ export class ProofOfWorkManager {
228
229
  /**
229
230
  * Refreshes the difficulty by changing the max hash value.
230
231
  * The higher the number, the easier. Scale 1 (hardest) to 2^256 (easiest), represented in HEX.
231
- *
232
+ *
232
233
  * If solve rate rate is higher than expected, the difficulty will increase rapidly.
233
234
  * If solve rate is lower than expected, the difficulty will decrease gradually.
234
235
  * The difficulty will never be lower than the initial difficulty.
@@ -247,16 +248,16 @@ export class ProofOfWorkManager {
247
248
  // and harder difficulty is represented by a smaller max allowed hash value.
248
249
  if (latestSolveCountPerMinute > this.desiredSolveCountPerMinute) {
249
250
  // if solve rate is higher than desired, make difficulty harder by making the max allowed hash value smaller
250
-
251
+
251
252
  const currentSolveRateInFractionOfDesiredSolveRate = latestSolveCountPerMinute / this.desiredSolveCountPerMinute;
252
253
  const newMaximumAllowedHashValueAsBigIntPriorToMultiplierAdjustment
253
- = (this.currentMaximumAllowedHashValueAsBigInt * BigInt(scaleFactor)) /
254
+ = (this.currentMaximumAllowedHashValueAsBigInt * BigInt(scaleFactor)) /
254
255
  (BigInt(Math.floor(currentSolveRateInFractionOfDesiredSolveRate * this.difficultyIncreaseMultiplier * scaleFactor)));
255
256
 
256
257
  const hashValueDecreaseAmountPriorToEvaluationFrequencyAdjustment
257
258
  = (this.currentMaximumAllowedHashValueAsBigInt - newMaximumAllowedHashValueAsBigIntPriorToMultiplierAdjustment) *
258
259
  (BigInt(Math.floor(this.difficultyIncreaseMultiplier * scaleFactor)) / BigInt(scaleFactor));
259
-
260
+
260
261
  // Adjustment based on the reevaluation frequency to provide more-or-less consistent behavior regardless of the reevaluation frequency.
261
262
  const hashValueDecreaseAmount = hashValueDecreaseAmountPriorToEvaluationFrequencyAdjustment / BigInt(difficultyEvaluationsPerMinute);
262
263
 
@@ -1,12 +1,14 @@
1
- import { ProofOfWorkManager } from "./proof-of-work-manager.js";
2
- import { ProofOfWork } from "./proof-of-work.js";
3
- import { RegistrationStore } from "./registration-store.js";
4
- import type { RegistrationData, RegistrationRequest } from "./registration-types.js";
5
- import type { ProofOfWorkChallengeModel } from "./proof-of-work-types.js";
6
- import { DwnServerError, DwnServerErrorCode } from "../dwn-error.js";
7
- import type { ActiveTenantCheckResult, TenantGate } from "@enbox/dwn-sdk-js";
8
- import { getDialectFromUrl } from "../storage.js";
9
- import { readFileSync } from "fs";
1
+ import type { ProofOfWorkChallengeModel } from './proof-of-work-types.js';
2
+ import type { ActiveTenantCheckResult, TenantGate } from '@enbox/dwn-sdk-js';
3
+ import type { RegistrationData, RegistrationRequest } from './registration-types.js';
4
+
5
+ import { readFileSync } from 'fs';
6
+
7
+ import { getDialectFromUrl } from '../storage.js';
8
+ import { ProofOfWork } from './proof-of-work.js';
9
+ import { ProofOfWorkManager } from './proof-of-work-manager.js';
10
+ import { RegistrationStore } from './registration-store.js';
11
+ import { DwnServerError, DwnServerErrorCode } from '../dwn-error.js';
10
12
 
11
13
  /**
12
14
  * The RegistrationManager is responsible for managing the registration of tenants.
@@ -27,7 +29,7 @@ export class RegistrationManager implements TenantGate {
27
29
  }
28
30
 
29
31
  /**
30
- * The terms-of-service hash.
32
+ * The terms-of-service hash.
31
33
  */
32
34
  public getTermsOfServiceHash(): string | undefined {
33
35
  return this.termsOfServiceHash;
@@ -45,7 +47,7 @@ export class RegistrationManager implements TenantGate {
45
47
  * Creates a new RegistrationManager instance.
46
48
  * @param input.registrationStoreUrl - The URL of the registration store.
47
49
  * Set to `undefined` or empty string if tenant registration is not required (ie. DWN is open for all).
48
- *
50
+ *
49
51
  */
50
52
  public static async create(input: {
51
53
  registrationStoreUrl?: string,
@@ -70,17 +72,17 @@ export class RegistrationManager implements TenantGate {
70
72
 
71
73
  // Initialize and start ProofOfWorkManager.
72
74
  registrationManager.proofOfWorkManager = await ProofOfWorkManager.create({
73
- autoStart: true,
74
- desiredSolveCountPerMinute: 10,
75
- initialMaximumAllowedHashValue: input.proofOfWorkInitialMaximumAllowedHash,
76
- challengeSeed: input.proofOfWorkChallengeNonceSeed,
75
+ autoStart : true,
76
+ desiredSolveCountPerMinute : 10,
77
+ initialMaximumAllowedHashValue : input.proofOfWorkInitialMaximumAllowedHash,
78
+ challengeSeed : input.proofOfWorkChallengeNonceSeed,
77
79
  });
78
80
 
79
81
  // Initialize RegistrationStore.
80
82
  const sqlDialect = getDialectFromUrl(new URL(registrationStoreUrl));
81
83
  const registrationStore = await RegistrationStore.create(sqlDialect);
82
84
  registrationManager.registrationStore = registrationStore;
83
-
85
+
84
86
  return registrationManager;
85
87
  }
86
88
 
@@ -136,18 +138,18 @@ export class RegistrationManager implements TenantGate {
136
138
 
137
139
  if (tenantRegistration === undefined) {
138
140
  return {
139
- isActiveTenant: false,
140
- detail: 'Not a registered tenant.'
141
+ isActiveTenant : false,
142
+ detail : 'Not a registered tenant.'
141
143
  };
142
144
  }
143
145
 
144
146
  if (tenantRegistration.termsOfServiceHash !== this.termsOfServiceHash) {
145
147
  return {
146
- isActiveTenant: false,
147
- detail: 'Agreed terms-of-service is outdated.'
148
+ isActiveTenant : false,
149
+ detail : 'Agreed terms-of-service is outdated.'
148
150
  };
149
151
  }
150
152
 
151
- return { isActiveTenant: true }
153
+ return { isActiveTenant: true };
152
154
  }
153
155
  }
@@ -1,6 +1,7 @@
1
- import { Kysely } from 'kysely';
2
- import type { RegistrationData } from './registration-types.js';
3
1
  import type { Dialect } from '@enbox/dwn-sql-store';
2
+ import type { RegistrationData } from './registration-types.js';
3
+
4
+ import { Kysely } from 'kysely';
4
5
 
5
6
  /**
6
7
  * The RegistrationStore is responsible for storing and retrieving tenant registration information.
@@ -27,11 +28,11 @@ export class RegistrationStore {
27
28
 
28
29
  private async initialize(): Promise<void> {
29
30
  await this.db.schema
30
- .createTable(RegistrationStore.registeredTenantTableName)
31
- .ifNotExists()
32
- .addColumn('did', 'text', (column) => column.primaryKey())
33
- .addColumn('termsOfServiceHash', 'text')
34
- .execute();
31
+ .createTable(RegistrationStore.registeredTenantTableName)
32
+ .ifNotExists()
33
+ .addColumn('did', 'text', (column) => column.primaryKey())
34
+ .addColumn('termsOfServiceHash', 'text')
35
+ .execute();
35
36
  }
36
37
 
37
38
  /**
package/src/storage.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import type { Dialect } from '@enbox/dwn-sql-store';
1
2
  import type { DidResolver } from '@enbox/dids';
3
+ import type { DwnServerConfig } from './config.js';
2
4
  import type {
3
5
  DataStore,
4
6
  DwnConfig,
@@ -8,14 +10,13 @@ import type {
8
10
  ResumableTaskStore,
9
11
  TenantGate,
10
12
  } from '@enbox/dwn-sdk-js';
11
- import type { Dialect } from '@enbox/dwn-sql-store';
12
- import type { DwnServerConfig } from './config.js';
13
13
 
14
14
  import * as fs from 'fs';
15
15
  import Cursor from 'pg-cursor';
16
- import Database from 'better-sqlite3';
17
- import pg from 'pg';
18
16
  import { createPool as MySQLCreatePool } from 'mysql2';
17
+ import pg from 'pg';
18
+
19
+ import { createBunSqliteDatabase } from '@enbox/dwn-sql-store';
19
20
  import { PluginLoader } from './plugin-loader.js';
20
21
 
21
22
  import {
@@ -51,10 +52,10 @@ export enum BackendTypes {
51
52
  export type DwnStore = DataStore | EventLog | MessageStore | ResumableTaskStore;
52
53
 
53
54
  export async function getDwnConfig(
54
- config : DwnServerConfig,
55
+ config : DwnServerConfig,
55
56
  options : {
56
57
  didResolver? : DidResolver,
57
- tenantGate? : TenantGate,
58
+ tenantGate? : TenantGate,
58
59
  eventStream? : EventStream,
59
60
  }
60
61
  ): Promise<DwnConfig> {
@@ -78,8 +79,8 @@ function getLevelStore(
78
79
  });
79
80
  case StoreType.MessageStore:
80
81
  return new MessageStoreLevel({
81
- blockstoreLocation: storeURI.host + storeURI.pathname + '/MESSAGESTORE',
82
- indexLocation: storeURI.host + storeURI.pathname + '/INDEX',
82
+ blockstoreLocation : storeURI.host + storeURI.pathname + '/MESSAGESTORE',
83
+ indexLocation : storeURI.host + storeURI.pathname + '/INDEX',
83
84
  });
84
85
  case StoreType.EventLog:
85
86
  return new EventLogLevel({
@@ -131,7 +132,7 @@ async function getStore(storeConfigString: string, storeType: StoreType): Promis
131
132
  return await loadStoreFromFilePath(storeConfigString, storeType);
132
133
  }
133
134
  // else treat the `storeConfigString` as a connection string
134
-
135
+
135
136
  const storeURI = new URL(storeConfigString);
136
137
 
137
138
  switch (storeURI.protocol.slice(0, -1)) {
@@ -171,7 +172,7 @@ async function loadStoreFromFilePath(
171
172
 
172
173
  export function getDialectFromUrl(connectionUrl: URL): Dialect {
173
174
  switch (connectionUrl.protocol.slice(0, -1)) {
174
- case BackendTypes.SQLITE:
175
+ case BackendTypes.SQLITE: {
175
176
  const path = connectionUrl.host + connectionUrl.pathname;
176
177
  console.log('SQL-lite relative path:', path ? path : undefined); // NOTE, using ? for lose equality comparison
177
178
 
@@ -184,16 +185,17 @@ export function getDialectFromUrl(connectionUrl: URL): Dialect {
184
185
  const dbPath = path || ':memory:';
185
186
 
186
187
  return new SqliteDialect({
187
- database: async () => new Database(dbPath),
188
+ database: async () => createBunSqliteDatabase(dbPath),
188
189
  });
190
+ }
189
191
  case BackendTypes.MYSQL:
190
192
  return new MysqlDialect({
191
193
  pool: async () => MySQLCreatePool(connectionUrl.toString()),
192
194
  });
193
195
  case BackendTypes.POSTGRES:
194
196
  return new PostgresDialect({
195
- pool: async () => new pg.Pool({ connectionString: connectionUrl.toString() }),
196
- cursor: Cursor,
197
+ pool : async () => new pg.Pool({ connectionString: connectionUrl.toString() }),
198
+ cursor : Cursor,
197
199
  });
198
200
  }
199
201
  }
@@ -39,9 +39,9 @@ export class SqlTtlCache {
39
39
  // 512 chars to accommodate potentially large `state` in Web5 Connect flow
40
40
  .addColumn('key', 'varchar(512)', (column) => column.primaryKey())
41
41
  .addColumn('value', 'text', (column) => column.notNull())
42
- .addColumn('expiry', 'integer', (column) => column.notNull())
42
+ .addColumn('expiry', 'bigint', (column) => column.notNull())
43
43
  .execute();
44
-
44
+
45
45
  await this.db.schema
46
46
  .createIndex('index_expiry')
47
47
  // .ifNotExists() // intentionally kept commented out code to show that it is not supported by all dialects (ie. MySQL)
@@ -97,7 +97,8 @@ export class SqlTtlCache {
97
97
  const entry = result[0];
98
98
 
99
99
  // if the entry is expired, don't return it and delete it
100
- if (Date.now() >= entry.expiry) {
100
+ const expiry = typeof entry.expiry === 'string' ? parseInt(entry.expiry, 10) : entry.expiry;
101
+ if (Date.now() >= expiry) {
101
102
  this.delete(key); // no need to await
102
103
  return undefined;
103
104
  }
@@ -129,7 +130,7 @@ export class SqlTtlCache {
129
130
  interface CacheEntry {
130
131
  key: string;
131
132
  value: string;
132
- expiry: number;
133
+ expiry: number | string; // bigint is returned as string by PostgreSQL driver
133
134
  }
134
135
 
135
136
  interface CacheDatabase {
@@ -1,16 +1,17 @@
1
- import { getDialectFromUrl } from "../storage.js";
2
1
  import { CryptoUtils } from '@enbox/crypto';
3
- import { SqlTtlCache } from "./sql-ttl-cache.js";
2
+
3
+ import { getDialectFromUrl } from '../storage.js';
4
+ import { SqlTtlCache } from './sql-ttl-cache.js';
4
5
 
5
6
  /**
6
7
  * The Web5 Connect Request object.
7
8
  */
8
- export type Web5ConnectRequest = any; // TODO: define type in common repo for reuse (https://github.com/TBD54566975/dwn-server/issues/138)
9
+ export type Web5ConnectRequest = any; // TODO: define type in common repo for reuse (https://github.com/enboxorg/enbox/issues/138)
9
10
 
10
11
  /**
11
12
  * The Web5 Connect Response object, which is also an OIDC ID token
12
13
  */
13
- export type Web5ConnectResponse = any; // TODO: define type in common repo for reuse (https://github.com/TBD54566975/dwn-server/issues/138)
14
+ export type Web5ConnectResponse = any; // TODO: define type in common repo for reuse (https://github.com/enboxorg/enbox/issues/138)
14
15
 
15
16
  /**
16
17
  * The result of the setWeb5ConnectRequest() method.
@@ -25,7 +26,7 @@ export type SetWeb5ConnectRequestResult = {
25
26
  * The time in seconds that the Request URI is valid for.
26
27
  */
27
28
  expires_in: number;
28
- }
29
+ };
29
30
 
30
31
  /**
31
32
  * The Web5 Connect Server is responsible for handling the Web5 Connect flow.
@@ -69,13 +70,13 @@ export class Web5ConnectServer {
69
70
  // Generate a request URI
70
71
  const requestId = CryptoUtils.randomUuid();
71
72
  const request_uri = `${this.baseUrl}/connect/authorize/${requestId}.jwt`;
72
-
73
+
73
74
  // Store the Request Object.
74
75
  this.cache.insert(`request:${requestId}`, request, Web5ConnectServer.ttlInSeconds);
75
-
76
+
76
77
  return {
77
78
  request_uri,
78
- expires_in : Web5ConnectServer.ttlInSeconds,
79
+ expires_in: Web5ConnectServer.ttlInSeconds,
79
80
  };
80
81
  }
81
82
 
package/src/ws-api.ts CHANGED
@@ -1,45 +1,30 @@
1
-
2
- import type {
3
- Dwn,
4
- } from '@enbox/dwn-sdk-js';
5
-
6
- import type { Server } from 'http';
7
-
8
- import { WebSocketServer } from 'ws';
1
+ import type { Dwn } from '@enbox/dwn-sdk-js';
2
+ import type { ServerWebSocket } from 'bun';
9
3
 
10
4
  import type { ConnectionManager } from './connection/connection-manager.js';
5
+ import type { HttpApi, WsData } from './http-api.js';
6
+
11
7
  import { InMemoryConnectionManager } from './connection/connection-manager.js';
12
8
 
13
9
  export class WsApi {
14
- #wsServer: WebSocketServer;
15
10
  dwn: Dwn;
16
- #connectionManager: ConnectionManager
11
+ #connectionManager: ConnectionManager;
17
12
 
18
- constructor(server: Server, dwn: Dwn, connectionManager?: ConnectionManager) {
13
+ constructor(httpApi: HttpApi, dwn: Dwn, connectionManager?: ConnectionManager) {
19
14
  this.dwn = dwn;
20
15
  this.#connectionManager = connectionManager || new InMemoryConnectionManager(dwn);
21
- this.#wsServer = new WebSocketServer({ server });
22
- }
23
-
24
- get server(): WebSocketServer {
25
- return this.#wsServer;
26
- }
27
16
 
28
- /**
29
- * Handler for starting a WebSocket.
30
- * Sets listeners for `connection`, `close` events.
31
- */
32
- #setupWebSocket(): void {
33
- this.#wsServer.on('connection', (socket, request) => this.#connectionManager.connect(socket, request));
34
- this.#wsServer.on('close', () => this.#connectionManager.closeAll());
17
+ // Wire up the WebSocket open event from Bun.serve() to the connection manager.
18
+ httpApi.onWebSocketConnection = (ws: ServerWebSocket<WsData>): void => {
19
+ this.#connectionManager.connect(ws);
20
+ };
35
21
  }
36
22
 
37
23
  start(): void {
38
- this.#setupWebSocket();
24
+ // No additional setup needed — Bun.serve() handles WebSocket lifecycle.
39
25
  }
40
26
 
41
27
  async close(): Promise<void> {
42
- this.#wsServer.close();
43
28
  await this.#connectionManager.closeAll();
44
29
  }
45
30
  }