@vex-chat/spire 0.7.4 → 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.
Files changed (202) hide show
  1. package/README.md +82 -26
  2. package/dist/ClientManager.d.ts +24 -25
  3. package/dist/ClientManager.js +232 -509
  4. package/dist/ClientManager.js.map +1 -0
  5. package/dist/Database.d.ts +49 -41
  6. package/dist/Database.js +698 -716
  7. package/dist/Database.js.map +1 -0
  8. package/dist/Spire.d.ts +23 -15
  9. package/dist/Spire.js +518 -218
  10. package/dist/Spire.js.map +1 -0
  11. package/dist/__tests__/Database.spec.js +113 -73
  12. package/dist/__tests__/Database.spec.js.map +1 -0
  13. package/dist/db/schema.d.ts +134 -0
  14. package/dist/db/schema.js +2 -0
  15. package/dist/db/schema.js.map +1 -0
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +3 -5
  18. package/dist/index.js.map +1 -0
  19. package/dist/middleware/validate.d.ts +12 -0
  20. package/dist/middleware/validate.js +35 -0
  21. package/dist/middleware/validate.js.map +1 -0
  22. package/dist/migrations/2026-04-06_initial-schema.d.ts +3 -0
  23. package/dist/migrations/2026-04-06_initial-schema.js +192 -0
  24. package/dist/migrations/2026-04-06_initial-schema.js.map +1 -0
  25. package/dist/run.js +26 -21
  26. package/dist/run.js.map +1 -0
  27. package/dist/server/avatar.d.ts +3 -4
  28. package/dist/server/avatar.js +85 -67
  29. package/dist/server/avatar.js.map +1 -0
  30. package/dist/server/errors.d.ts +59 -0
  31. package/dist/server/errors.js +94 -0
  32. package/dist/server/errors.js.map +1 -0
  33. package/dist/server/file.d.ts +3 -4
  34. package/dist/server/file.js +101 -61
  35. package/dist/server/file.js.map +1 -0
  36. package/dist/server/index.d.ts +9 -6
  37. package/dist/server/index.js +595 -70
  38. package/dist/server/index.js.map +1 -0
  39. package/dist/server/invite.d.ts +4 -5
  40. package/dist/server/invite.js +21 -103
  41. package/dist/server/invite.js.map +1 -0
  42. package/dist/server/openapi.d.ts +2 -0
  43. package/dist/server/openapi.js +40 -0
  44. package/dist/server/openapi.js.map +1 -0
  45. package/dist/server/permissions.d.ts +16 -0
  46. package/dist/server/permissions.js +22 -0
  47. package/dist/server/permissions.js.map +1 -0
  48. package/dist/server/rateLimit.d.ts +28 -0
  49. package/dist/server/rateLimit.js +58 -0
  50. package/dist/server/rateLimit.js.map +1 -0
  51. package/dist/server/user.d.ts +4 -7
  52. package/dist/server/user.js +66 -76
  53. package/dist/server/user.js.map +1 -0
  54. package/dist/server/utils.d.ts +35 -7
  55. package/dist/server/utils.js +50 -6
  56. package/dist/server/utils.js.map +1 -0
  57. package/dist/types/express.d.ts +20 -0
  58. package/dist/types/express.js +2 -0
  59. package/dist/types/express.js.map +1 -0
  60. package/dist/utils/createLogger.js +13 -19
  61. package/dist/utils/createLogger.js.map +1 -0
  62. package/dist/utils/createUint8UUID.js +6 -10
  63. package/dist/utils/createUint8UUID.js.map +1 -0
  64. package/dist/utils/jwtSecret.d.ts +7 -0
  65. package/dist/utils/jwtSecret.js +15 -0
  66. package/dist/utils/jwtSecret.js.map +1 -0
  67. package/dist/utils/loadEnv.js +7 -22
  68. package/dist/utils/loadEnv.js.map +1 -0
  69. package/dist/utils/msgpack.d.ts +2 -0
  70. package/dist/utils/msgpack.js +4 -0
  71. package/dist/utils/msgpack.js.map +1 -0
  72. package/package.json +91 -63
  73. package/src/ClientManager.ts +434 -0
  74. package/src/Database.ts +925 -0
  75. package/src/Spire.ts +878 -0
  76. package/src/__tests__/Database.spec.ts +167 -0
  77. package/src/ambient-modules.d.ts +1 -0
  78. package/src/db/schema.ts +165 -0
  79. package/src/index.ts +3 -0
  80. package/src/middleware/validate.ts +38 -0
  81. package/src/migrations/2026-04-06_initial-schema.ts +218 -0
  82. package/src/run.ts +37 -0
  83. package/src/server/avatar.ts +141 -0
  84. package/src/server/errors.ts +133 -0
  85. package/src/server/file.ts +172 -0
  86. package/src/server/index.ts +855 -0
  87. package/src/server/invite.ts +65 -0
  88. package/src/server/openapi.ts +51 -0
  89. package/src/server/permissions.ts +40 -0
  90. package/src/server/rateLimit.ts +86 -0
  91. package/src/server/user.ts +125 -0
  92. package/src/server/utils.ts +59 -0
  93. package/src/types/express.ts +23 -0
  94. package/src/utils/createLogger.ts +47 -0
  95. package/src/utils/createUint8UUID.ts +9 -0
  96. package/src/utils/jwtSecret.ts +16 -0
  97. package/src/utils/loadEnv.ts +15 -0
  98. package/src/utils/msgpack.ts +4 -0
  99. package/avatars/169d76cb-6e7c-4e24-8224-017673eed8ff +0 -0
  100. package/avatars/1cae8d0b-0c6b-4c73-b25c-2d2349a57122 +0 -0
  101. package/avatars/1d87bc2b-71fc-4818-8004-40d04093e5fc +0 -0
  102. package/avatars/1f2c3d62-8b4d-465a-9895-51a24caef00d +0 -0
  103. package/avatars/245ee7fc-1004-41ab-adab-a04c9ceb9d7a +0 -0
  104. package/avatars/2465c28c-bdaf-4fa2-b42a-d054f04dc39b +0 -0
  105. package/avatars/3900a674-a2dd-4996-a61d-8c29b3270f41 +0 -0
  106. package/avatars/3c3b9c77-ea50-45e7-bb25-65d6f3d2a219 +0 -0
  107. package/avatars/414a2ff4-ad2f-4a7d-aa27-3b09ad3522b2 +0 -0
  108. package/avatars/522fe504-f0ad-4ed4-9dc6-e5dc2338e531 +0 -0
  109. package/avatars/53e5eb29-e7d1-4d58-add9-d44f39f0cfb7 +0 -0
  110. package/avatars/54d3f757-1038-41c8-bfb9-efd37b6e8ebe +0 -0
  111. package/avatars/623e86d7-c49c-46f6-9b76-ca70c9dbc43b +0 -0
  112. package/avatars/66e2abae-60f5-4dd1-b9fb-297a4bedfeb0 +0 -0
  113. package/avatars/6f37980e-f6fa-4d6d-9206-24050b403f45 +0 -0
  114. package/avatars/80138ece-eb5c-4b20-817b-903d6b0f54ae +0 -0
  115. package/avatars/841c77d3-37c4-431b-be22-672888062874 +0 -0
  116. package/avatars/88051a61-2bda-4750-95a3-5fb0b4918149 +0 -0
  117. package/avatars/89540973-c421-4bf1-8b89-9f1eaa51c1b5 +0 -0
  118. package/avatars/8a802fad-8c99-4942-8f80-47cec600149c +0 -0
  119. package/avatars/90531d8a-907a-4a1a-ac45-c85e4acb0df9 +0 -0
  120. package/avatars/9b7d0da9-b8d6-4801-b128-9993f79f464a +0 -0
  121. package/avatars/9bc456f1-c4c4-48a1-b9e6-fd44dd744a72 +0 -0
  122. package/avatars/9cf878bf-7430-49ec-a47a-78f3c93793dd +0 -0
  123. package/avatars/9ee82847-6ad3-45e5-92b9-f474a6c54d96 +0 -0
  124. package/avatars/ab44c857-d81d-4c88-85db-32f9532e5376 +0 -0
  125. package/avatars/b396a8d2-dc14-48d2-aac4-3755dc637051 +0 -0
  126. package/avatars/b6ac11c5-a8b2-4e0a-995a-9c87f1e58787 +0 -0
  127. package/avatars/b79d6855-b738-434c-be32-809637e62b9b +0 -0
  128. package/avatars/bbcd0188-d6a5-48ae-90fb-be5ff30599ab +0 -0
  129. package/avatars/bc7a9e0e-4720-4a6e-a90d-c11fec94d380 +0 -0
  130. package/avatars/c1c4889f-8383-4041-8bdd-9fded4046f37 +0 -0
  131. package/avatars/c4c7203c-d93a-4749-ade2-17053acf1d2a +0 -0
  132. package/avatars/ca974a70-0a23-4668-8b80-c4304dc7f793 +0 -0
  133. package/avatars/cf119a0d-eb3f-4bed-905b-f14a876c3535 +0 -0
  134. package/avatars/d464b03d-30c2-49e3-a666-80aefa8a1b35 +0 -0
  135. package/avatars/da0eee89-82f0-4d45-ab48-7d2786b634c5 +0 -0
  136. package/avatars/de4c77a5-68e9-4bb2-b40d-d964bf377d61 +0 -0
  137. package/avatars/dea95395-7d0b-42aa-a9ed-40c7d4fb4c48 +0 -0
  138. package/avatars/edb30749-59ba-4aa2-9c52-0fb22048f4cf +0 -0
  139. package/avatars/f17c245a-af7d-445b-9365-49f7f54b1eeb +0 -0
  140. package/avatars/f1ee6a35-b262-4dbf-99f5-3d011e3b98ec +0 -0
  141. package/avatars/f802bdd0-345d-41f6-9184-0f30e1258fb3 +0 -0
  142. package/dist/migrations/20210103192527_users.d.ts +0 -3
  143. package/dist/migrations/20210103192527_users.js +0 -30
  144. package/dist/migrations/20210103193502_mail.d.ts +0 -3
  145. package/dist/migrations/20210103193502_mail.js +0 -35
  146. package/dist/migrations/20210103193525_preKeys.d.ts +0 -3
  147. package/dist/migrations/20210103193525_preKeys.js +0 -30
  148. package/dist/migrations/20210103193553_oneTimeKeys.d.ts +0 -3
  149. package/dist/migrations/20210103193553_oneTimeKeys.js +0 -30
  150. package/dist/migrations/20210103193615_servers.d.ts +0 -3
  151. package/dist/migrations/20210103193615_servers.js +0 -28
  152. package/dist/migrations/20210103193729_channels.d.ts +0 -3
  153. package/dist/migrations/20210103193729_channels.js +0 -28
  154. package/dist/migrations/20210103193749_permissions.d.ts +0 -3
  155. package/dist/migrations/20210103193749_permissions.js +0 -30
  156. package/dist/migrations/20210103193801_files.d.ts +0 -3
  157. package/dist/migrations/20210103193801_files.js +0 -28
  158. package/files/00ea7368-45a7-4f6a-a199-974da14be1a0 +0 -0
  159. package/files/039503d2-a170-4962-b921-c97994ba64ff +0 -0
  160. package/files/14b6fa02-4cbb-40df-be4f-a07187cb619e +0 -0
  161. package/files/15c04cb1-dc6a-4f19-aa6f-4a3b92d05bf7 +0 -0
  162. package/files/2a8d411c-8b92-4532-b84d-d64c638d6293 +0 -0
  163. package/files/37de2cd3-08a8-4044-9c37-e13386765f3d +0 -0
  164. package/files/42452029-284e-4c81-9f18-feb6ce309eed +0 -0
  165. package/files/43d09f2f-29c8-415f-8c4a-23f2a32eb79e +0 -0
  166. package/files/52992923-33ab-44a1-8118-605e9b4856a7 +0 -0
  167. package/files/53180681-36e2-49c0-8382-94dca0da09bf +0 -0
  168. package/files/5a56cd7b-1d04-4619-b60f-1e5515b9164a +0 -0
  169. package/files/5ced7676-20c4-4219-a4f2-70a25eb7eea8 +0 -0
  170. package/files/60e787ff-8ec5-444d-b963-0aaf5313b53e +0 -0
  171. package/files/67a17729-fcb7-4339-9499-1fc08fea72ca +0 -0
  172. package/files/68d09565-908d-4a67-8f09-e183f8708eb4 +0 -0
  173. package/files/70e587c5-56e8-47f0-bd36-691efcb0cc2e +0 -4
  174. package/files/7a227619-b715-4e2c-a79d-b2158d56a799 +0 -0
  175. package/files/7e3cc3ea-b706-4835-994d-65d33acaf369 +0 -0
  176. package/files/816f72a0-65dc-40c1-8862-1d22065cca3c +0 -0
  177. package/files/8bf84972-5086-4631-a752-093d7b1a098b +0 -0
  178. package/files/8c46e3bc-3f2e-441d-b8cc-17428fc3d219 +0 -0
  179. package/files/8eb83364-8826-4eee-895a-ba5cd3ab85e9 +0 -0
  180. package/files/8faefaea-14e3-49e4-ac74-9710622bfae9 +0 -0
  181. package/files/91af08c2-9dca-41f4-b6c6-b7bf33505df9 +0 -0
  182. package/files/9349dffa-35dd-49a0-a651-10b438038f95 +0 -0
  183. package/files/b0a12a41-6283-4f27-b2c8-66774991d96c +0 -0
  184. package/files/b28afb08-d18b-48a8-93c3-6a59c66d8fee +0 -0
  185. package/files/be60fe01-1578-4363-a908-41500092b77d +0 -0
  186. package/files/cf7b90e3-734a-4453-9ff3-9a331404b5ef +0 -0
  187. package/files/d1be30aa-8ff4-41c1-b360-f65922029047 +0 -0
  188. package/files/d2d31a57-a413-443c-9b97-fa9ca394ef0b +0 -0
  189. package/files/d357f223-b786-478d-a113-b53cb62acdab +0 -0
  190. package/files/d4a69ee0-05c4-4ff0-8753-624cdd0f24e9 +0 -0
  191. package/files/d57f411b-1874-4f00-a6b0-2f86de6b229d +0 -0
  192. package/files/d85aaa33-7f70-4a70-b3d2-cad667beb38c +0 -0
  193. package/files/db2fc236-dbe0-4d24-bfaf-884829fd090a +0 -0
  194. package/files/df2e20ec-6dcc-4402-94ee-7d1163f84197 +0 -0
  195. package/files/e0880ab5-6d49-4dc0-a5ec-0d3793a8a7b8 +0 -0
  196. package/files/e59ee9c6-5aea-48ea-b3d9-94a324dc2260 +0 -0
  197. package/files/e6d7aad6-4220-4ce7-85f8-89d0b1f0cc89 +0 -0
  198. package/files/f0bfc98c-3534-459d-931a-7c6e77bde153 +0 -0
  199. package/files/f8443740-050c-4714-9bf6-334783ae6ffd +0 -0
  200. package/files/fc405ae7-f9fb-455d-ac8c-0ca0d88d4115 +0 -0
  201. package/jest.config.js +0 -13
  202. package/spire.sqlite +0 -0
@@ -1,7 +1,35 @@
1
- import { XTypes } from "@vex-chat/types";
2
- export interface ICensoredUser {
3
- userID: string;
4
- username: string;
5
- lastSeen: Date;
6
- }
7
- export declare const censorUser: (user: XTypes.SQL.IUser) => ICensoredUser;
1
+ import type { Device, User, UserRecord } from "@vex-chat/types";
2
+ import type { Request } from "express";
3
+ /**
4
+ * Strips password fields from a DB user record, returning the
5
+ * public-safe User shape.
6
+ */
7
+ export declare const censorUser: (user: UserRecord) => User;
8
+ /**
9
+ * Safely extract the authenticated device from a request.
10
+ * Throws if the device is not set (i.e. checkDevice middleware did
11
+ * not run or the token was not a device token).
12
+ *
13
+ * Throws `AppError(401)` — the central error handler turns this into
14
+ * a JSON 401 response. No stack trace or raw Error leaks.
15
+ */
16
+ export declare function getDevice(req: Request): Device;
17
+ /**
18
+ * Safely extract a required route parameter.
19
+ *
20
+ * Throws `AppError(400)` if the parameter is missing or is an array
21
+ * (which shouldn't happen for well-wired routes, but defensively
22
+ * checked). The error message deliberately does NOT include the
23
+ * user-supplied value — CWE-79 / CWE-116 fix for the earlier
24
+ * `"Missing route parameter: " + name` concatenation pattern.
25
+ */
26
+ export declare function getParam(req: Request, name: string): string;
27
+ /**
28
+ * Safely extract the authenticated user from a request.
29
+ * Throws if the user is not set (i.e. protect middleware was not
30
+ * applied to this route).
31
+ *
32
+ * Throws `AppError(401)` — the central error handler turns this into
33
+ * a JSON 401 response.
34
+ */
35
+ export declare function getUser(req: Request): User;
@@ -1,11 +1,55 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.censorUser = void 0;
4
- const censorUser = (user) => {
1
+ import { AppError } from "./errors.js";
2
+ /**
3
+ * Strips password fields from a DB user record, returning the
4
+ * public-safe User shape.
5
+ */
6
+ export const censorUser = (user) => {
5
7
  return {
8
+ lastSeen: user.lastSeen,
6
9
  userID: user.userID,
7
10
  username: user.username,
8
- lastSeen: user.lastSeen,
9
11
  };
10
12
  };
11
- exports.censorUser = censorUser;
13
+ /**
14
+ * Safely extract the authenticated device from a request.
15
+ * Throws if the device is not set (i.e. checkDevice middleware did
16
+ * not run or the token was not a device token).
17
+ *
18
+ * Throws `AppError(401)` — the central error handler turns this into
19
+ * a JSON 401 response. No stack trace or raw Error leaks.
20
+ */
21
+ export function getDevice(req) {
22
+ if (!req.device)
23
+ throw new AppError(401, "Not authenticated");
24
+ return req.device;
25
+ }
26
+ /**
27
+ * Safely extract a required route parameter.
28
+ *
29
+ * Throws `AppError(400)` if the parameter is missing or is an array
30
+ * (which shouldn't happen for well-wired routes, but defensively
31
+ * checked). The error message deliberately does NOT include the
32
+ * user-supplied value — CWE-79 / CWE-116 fix for the earlier
33
+ * `"Missing route parameter: " + name` concatenation pattern.
34
+ */
35
+ export function getParam(req, name) {
36
+ const value = req.params[name];
37
+ if (!value || Array.isArray(value)) {
38
+ throw new AppError(400, "Missing or invalid route parameter");
39
+ }
40
+ return value;
41
+ }
42
+ /**
43
+ * Safely extract the authenticated user from a request.
44
+ * Throws if the user is not set (i.e. protect middleware was not
45
+ * applied to this route).
46
+ *
47
+ * Throws `AppError(401)` — the central error handler turns this into
48
+ * a JSON 401 response.
49
+ */
50
+ export function getUser(req) {
51
+ if (!req.user)
52
+ throw new AppError(401, "Not authenticated");
53
+ return req.user;
54
+ }
55
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAgB,EAAQ,EAAE;IACjD,OAAO;QACH,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KAC1B,CAAC;AACN,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY;IAClC,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IAC9D,OAAO,GAAG,CAAC,MAAM,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAY,EAAE,IAAY;IAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,oCAAoC,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,GAAY;IAChC,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IAC5D,OAAO,GAAG,CAAC,IAAI,CAAC;AACpB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Device, User } from "@vex-chat/types";
2
+ /**
3
+ * Augment Express's global Request interface with the properties
4
+ * set by checkAuth and checkDevice middleware.
5
+ *
6
+ * The global Express.Request is merged into express-serve-static-core's
7
+ * Request via `extends Express.Request`, so properties added here are
8
+ * available on `req` in all route handlers.
9
+ */
10
+ declare global {
11
+ namespace Express {
12
+ interface Request {
13
+ bearerToken?: string;
14
+ device?: Device;
15
+ exp?: number;
16
+ user?: User;
17
+ }
18
+ }
19
+ }
20
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../src/types/express.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,CAAC"}
@@ -1,26 +1,20 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createLogger = void 0;
7
- const winston_1 = __importDefault(require("winston"));
1
+ import winston from "winston";
8
2
  /**
9
3
  * @ignore
10
4
  */
11
- function createLogger(logName, logLevel) {
12
- const logger = winston_1.default.createLogger({
13
- level: logLevel || "error",
14
- format: winston_1.default.format.combine(winston_1.default.format.timestamp({
15
- format: "YYYY-MM-DD HH:mm:ss",
16
- }), winston_1.default.format.errors({ stack: true }), winston_1.default.format.splat(), winston_1.default.format.json()),
5
+ export function createLogger(logName, logLevel) {
6
+ const logger = winston.createLogger({
17
7
  defaultMeta: { service: "vex-" + logName },
8
+ format: winston.format.combine(winston.format.timestamp({
9
+ format: "YYYY-MM-DD HH:mm:ss",
10
+ }), winston.format.errors({ stack: true }), winston.format.splat(), winston.format.json()),
11
+ level: logLevel || "error",
18
12
  transports: [
19
13
  //
20
14
  // - Write all logs with level `error` and below to `error.log`
21
15
  // - Write all logs with level `info` and below to `combined.log`
22
16
  //
23
- new winston_1.default.transports.File({
17
+ new winston.transports.File({
24
18
  filename: "vex:" + logName + ".log",
25
19
  level: "error",
26
20
  }),
@@ -30,12 +24,12 @@ function createLogger(logName, logLevel) {
30
24
  // If we're not in production then log to the `console` with the format:
31
25
  // `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
32
26
  //
33
- if (process.env.NODE_ENV !== "production" &&
34
- process.env.NODE_ENV !== "test") {
35
- logger.add(new winston_1.default.transports.Console({
36
- format: winston_1.default.format.combine(winston_1.default.format.colorize(), winston_1.default.format.simple()),
27
+ if (process.env["NODE_ENV"] !== "production" &&
28
+ process.env["NODE_ENV"] !== "test") {
29
+ logger.add(new winston.transports.Console({
30
+ format: winston.format.combine(winston.format.colorize(), winston.format.simple()),
37
31
  }));
38
32
  }
39
33
  return logger;
40
34
  }
41
- exports.createLogger = createLogger;
35
+ //# sourceMappingURL=createLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createLogger.js","sourceRoot":"","sources":["../../src/utils/createLogger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,QAAiB;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;QAChC,WAAW,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE;QAC1C,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAC1B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;YACrB,MAAM,EAAE,qBAAqB;SAChC,CAAC,EACF,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EACtC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EACtB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CACxB;QACD,KAAK,EAAE,QAAQ,IAAI,OAAO;QAC1B,UAAU,EAAE;YACR,EAAE;YACF,+DAA+D;YAC/D,iEAAiE;YACjE,EAAE;YACF,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;gBACxB,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM;gBACnC,KAAK,EAAE,OAAO;aACjB,CAAC;SACL;KACJ,CAAC,CAAC;IACH,EAAE;IACF,wEAAwE;IACxE,gEAAgE;IAChE,EAAE;IACF,IACI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,YAAY;QACxC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,MAAM,EACpC,CAAC;QACC,MAAM,CAAC,GAAG,CACN,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;YAC3B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,EACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAC1B;SACJ,CAAC,CACL,CAAC;IACN,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -1,12 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uuidToUint8 = exports.createUint8UUID = void 0;
4
- const uuid_1 = require("uuid");
5
- function createUint8UUID() {
6
- return uuidToUint8(uuid_1.v4());
1
+ import { parse as uuidParse } from "uuid";
2
+ export function createUint8UUID() {
3
+ return uuidToUint8(crypto.randomUUID());
7
4
  }
8
- exports.createUint8UUID = createUint8UUID;
9
- function uuidToUint8(uuid) {
10
- return new Uint8Array(uuid_1.parse(uuid));
5
+ export function uuidToUint8(uuid) {
6
+ return new Uint8Array(uuidParse(uuid));
11
7
  }
12
- exports.uuidToUint8 = uuidToUint8;
8
+ //# sourceMappingURL=createUint8UUID.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createUint8UUID.js","sourceRoot":"","sources":["../../src/utils/createUint8UUID.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,MAAM,UAAU,eAAe;IAC3B,OAAO,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACpC,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Returns the JWT signing secret.
3
+ *
4
+ * Prefers JWT_SECRET (dedicated HMAC key) over SPK (NaCl server signing key).
5
+ * Falls back to SPK for backward compat with existing deployments.
6
+ */
7
+ export declare function getJwtSecret(): string;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Returns the JWT signing secret.
3
+ *
4
+ * Prefers JWT_SECRET (dedicated HMAC key) over SPK (NaCl server signing key).
5
+ * Falls back to SPK for backward compat with existing deployments.
6
+ */
7
+ export function getJwtSecret() {
8
+ const secret = process.env["JWT_SECRET"] ?? process.env["SPK"];
9
+ if (!secret) {
10
+ throw new Error("Neither JWT_SECRET nor SPK is set. " +
11
+ "Set JWT_SECRET (preferred) or SPK in your environment.");
12
+ }
13
+ return secret;
14
+ }
15
+ //# sourceMappingURL=jwtSecret.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwtSecret.js","sourceRoot":"","sources":["../../src/utils/jwtSecret.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACX,qCAAqC;YACjC,wDAAwD,CAC/D,CAAC;IACN,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
@@ -1,28 +1,13 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadEnv = void 0;
4
- const dotenv_1 = require("dotenv");
5
- /*
6
- Populate process.env with vars from .env and verify required vars are present.
7
- Thanks Z for this function.
8
- */
9
- function loadEnv() {
10
- dotenv_1.config();
11
- const requiredEnvVars = [
12
- // "SQL_HOST",
13
- // "SQL_USER",
14
- // "SQL_PASSWORD",
15
- // "SQL_DB_NAME",
16
- // "SQL_PORT",
17
- "CANARY",
18
- "DB_TYPE",
19
- "SPK",
20
- ];
1
+ import { config } from "dotenv";
2
+ /* Populate process.env with vars from .env and verify required vars are present. */
3
+ export function loadEnv() {
4
+ config();
5
+ const requiredEnvVars = ["CANARY", "DB_TYPE", "SPK"];
21
6
  for (const required of requiredEnvVars) {
22
7
  if (process.env[required] === undefined) {
23
- console.warn(`Required environment variable '${required}' is not set. Please consult the README.`);
8
+ process.stderr.write(`Required environment variable '${required}' is not set. Please consult the README.\n`);
24
9
  process.exit(1);
25
10
  }
26
11
  }
27
12
  }
28
- exports.loadEnv = loadEnv;
13
+ //# sourceMappingURL=loadEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadEnv.js","sourceRoot":"","sources":["../../src/utils/loadEnv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,oFAAoF;AACpF,MAAM,UAAU,OAAO;IACnB,MAAM,EAAE,CAAC;IACT,MAAM,eAAe,GAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAC/D,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAChB,kCAAkC,QAAQ,4CAA4C,CACzF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Packr } from "msgpackr";
2
+ export declare const msgpack: Packr;
@@ -0,0 +1,4 @@
1
+ import { Packr } from "msgpackr";
2
+ // Standard msgpack encoder/decoder configured for broad compatibility.
3
+ export const msgpack = new Packr({ moreTypes: false, useRecords: false });
4
+ //# sourceMappingURL=msgpack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"msgpack.js","sourceRoot":"","sources":["../../src/utils/msgpack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,uEAAuE;AACvE,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,80 +1,108 @@
1
1
  {
2
2
  "name": "@vex-chat/spire",
3
- "version": "0.7.4",
3
+ "version": "1.0.0",
4
4
  "description": "Vex server implementation in NodeJS.",
5
- "main": "./dist/index.js",
5
+ "type": "module",
6
+ "files": [
7
+ "dist",
8
+ "src",
9
+ "LICENSE"
10
+ ],
6
11
  "author": "Extra <extrahash@protonmail.com>",
7
12
  "license": "AGPL-3.0-or-later",
13
+ "engines": {
14
+ "node": ">=24.0.0",
15
+ "npm": ">=10.0.0"
16
+ },
17
+ "packageManager": "npm@10.9.2",
18
+ "publishConfig": {
19
+ "access": "public",
20
+ "registry": "https://registry.npmjs.org/"
21
+ },
8
22
  "scripts": {
9
- "start": "node ./dist/run.js",
23
+ "preinstall": "npx only-allow npm",
24
+ "start": "node --experimental-strip-types src/run.ts",
10
25
  "restart": "pm2 restart spire && pm2 logs spire",
11
- "build": "node ./node_modules/typescript/bin/tsc",
12
- "prettier": "node ./node_modules/prettier/bin-prettier.js '**/*.{ts,tsx,json,md}' --tab-width 4 --trailing-comma es5 --ignore-path .gitignore --arrow-parens always --write",
13
- "lint": "./node_modules/tslint/bin/tslint src/**/*.ts{,x}",
14
- "lint-fix": "./node_modules/tslint/bin/tslint src/**/*.ts{,x} --fix",
15
- "api-knex": "TS_NODE_COMPILER_OPTIONS='{ \"module\": \"commonjs\" }' knex --knexfile=./src/knexfile.ts",
16
- "test": "jest",
17
- "prepublish": "yarn build"
26
+ "build": "tsc",
27
+ "format": "prettier --write .",
28
+ "format:check": "prettier --check .",
29
+ "lint": "eslint src/",
30
+ "lint:fix": "eslint src/ --fix",
31
+ "prepare": "husky",
32
+ "test": "vitest run",
33
+ "gen-spk": "node scripts/gen-spk.js",
34
+ "docs": "node ./scripts/generate-docs.js",
35
+ "license:check": "node scripts/fix-license-checker.mjs && npx @onebeyond/license-checker scan --allowOnly MIT MIT-0 ISC BSD-2-Clause BSD-3-Clause Apache-2.0 0BSD MPL-2.0 CC0-1.0 CC-BY-3.0 CC-BY-4.0 Unlicense BlueOak-1.0.0 Python-2.0 Zlib PSF-2.0 Artistic-2.0 AGPL-3.0-or-later WTFPL \"(MIT AND CC-BY-3.0)\" --ignoreRootPackageLicense --disableReport",
36
+ "service:status-monitor": "node ./services/status-monitor/index.js",
37
+ "service:status-monitor:clear-history": "node ./services/status-monitor/clear-history.js",
38
+ "service:deploy-hook": "node ./services/deploy-hook/index.js",
39
+ "monitor": "node ./services/status-monitor/index.js"
18
40
  },
19
41
  "devDependencies": {
20
- "husky": "^3.1.0",
21
- "jest": "^26.6.3",
22
- "lint-staged": "^9.5.0",
23
- "prettier": "^1.19.1",
24
- "ts-jest": "^26.4.4",
25
- "ts-node": "^9.1.1",
26
- "tslint": "^5.20.1",
27
- "tslint-config-prettier": "^1.18.0",
28
- "typescript": "^4.1.3"
42
+ "@changesets/cli": "2.30.0",
43
+ "@onebeyond/license-checker": "2.2.0",
44
+ "@types/better-sqlite3": "7.6.13",
45
+ "@types/cors": "2.8.19",
46
+ "@types/express": "5.0.6",
47
+ "@types/jsonwebtoken": "9.0.10",
48
+ "@types/morgan": "1.9.10",
49
+ "@types/multer": "2.1.0",
50
+ "@types/node": "25.6.0",
51
+ "@types/uuid": "10.0.0",
52
+ "@types/ws": "8.18.1",
53
+ "@vitest/eslint-plugin": "1.6.15",
54
+ "eslint": "10.2.0",
55
+ "eslint-config-prettier": "10.1.8",
56
+ "eslint-plugin-n": "17.24.0",
57
+ "eslint-plugin-perfectionist": "5.8.0",
58
+ "husky": "9.1.7",
59
+ "lint-staged": "16.4.0",
60
+ "prettier": "3.8.2",
61
+ "type-coverage": "2.29.7",
62
+ "typedoc": "0.28.18",
63
+ "typescript": "6.0.2",
64
+ "typescript-eslint": "8.58.1",
65
+ "vitest": "4.1.4"
66
+ },
67
+ "typeCoverage": {
68
+ "atLeast": 95,
69
+ "ignoreCatch": true
29
70
  },
30
71
  "lint-staged": {
31
- "src/**/*.{ts}": [
32
- "./node_modules/tslint/bin/tslint -c tslint.json --fix",
33
- "git add"
72
+ "*.ts": [
73
+ "eslint --fix",
74
+ "prettier --write"
34
75
  ]
35
76
  },
36
- "husky": {
37
- "hooks": {
38
- "pre-commit": "yarn prettier; git add --all; lint-staged",
39
- "pre-push": "git diff HEAD --quiet && npm test"
40
- }
77
+ "overrides": {
78
+ "@types/ws": "8.18.1",
79
+ "@types/readable-stream": "4.0.11",
80
+ "lodash": "4.18.1",
81
+ "minimatch": "10.2.5"
41
82
  },
42
83
  "dependencies": {
43
- "@extrahash/sleep": "^1.0.0",
44
- "@types/cookie-parser": "^1.4.2",
45
- "@types/cors": "^2.8.8",
46
- "@types/express": "^4.17.9",
47
- "@types/express-ws": "^3.0.0",
48
- "@types/jsonwebtoken": "^8.5.0",
49
- "@types/morgan": "^1.9.2",
50
- "@types/msgpack-lite": "^0.1.7",
51
- "@types/multer": "^1.4.5",
52
- "@types/parse-duration": "^0.3.0",
53
- "@types/uuid": "^8.3.0",
54
- "@types/ws": "^7.4.0",
55
- "@vex-chat/crypto": "^0.7.15",
56
- "@vex-chat/types": "^0.10.9",
57
- "chalk": "^4.1.0",
58
- "cookie-parser": "^1.4.5",
59
- "cors": "^2.8.5",
60
- "dotenv": "^8.2.0",
61
- "express": "^4.17.1",
62
- "express-ws": "^4.0.0",
63
- "file-type": "^16.1.0",
64
- "helmet": "^4.2.0",
65
- "jsonwebtoken": "^8.5.1",
66
- "knex": "^0.21.12",
67
- "morgan": "^1.10.0",
68
- "msgpack-lite": "^0.1.26",
69
- "multer": "^1.4.2",
70
- "mysql": "^2.18.1",
71
- "parse-duration": "^0.4.4",
72
- "pbkdf2": "^3.1.1",
73
- "sqlite": "^4.0.17",
74
- "sqlite3": "^5.0.0",
75
- "tweetnacl": "^1.0.3",
76
- "uuid": "^8.3.1",
77
- "winston": "^3.3.3",
78
- "ws": "^7.4.0"
84
+ "@asyncapi/web-component": "2.6.5",
85
+ "@scalar/express-api-reference": "0.9.7",
86
+ "@vex-chat/crypto": "2.0.0",
87
+ "@vex-chat/types": "2.0.0",
88
+ "better-sqlite3": "11.10.0",
89
+ "cors": "2.8.6",
90
+ "dotenv": "17.4.1",
91
+ "express": "5.2.1",
92
+ "express-rate-limit": "8.3.2",
93
+ "file-type": "22.0.1",
94
+ "helmet": "8.1.0",
95
+ "jsonwebtoken": "9.0.3",
96
+ "kysely": "0.28.16",
97
+ "morgan": "1.10.1",
98
+ "msgpackr": "1.11.8",
99
+ "multer": "2.1.1",
100
+ "parse-duration": "2.1.6",
101
+ "picocolors": "1.1.1",
102
+ "tweetnacl": "1.0.3",
103
+ "uuid": "8.3.2",
104
+ "winston": "3.19.0",
105
+ "ws": "8.20.0",
106
+ "zod": "4.3.6"
79
107
  }
80
108
  }