serverless-ircd 0.5.0 → 0.7.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 (394) hide show
  1. package/.github/workflows/ci.yml +40 -3
  2. package/.github/workflows/deploy-aws.yml +1 -2
  3. package/.github/workflows/deploy-cf-tcp.yml +1 -5
  4. package/.github/workflows/deploy-cf.yml +1 -2
  5. package/.gitmodules +3 -0
  6. package/CHANGELOG.md +474 -0
  7. package/README.md +219 -22
  8. package/apps/aws-stack/README.md +33 -0
  9. package/apps/aws-stack/package.json +1 -1
  10. package/apps/aws-stack/src/aws-stack.ts +74 -9
  11. package/apps/aws-stack/tests/coverage-command.test.ts +155 -0
  12. package/apps/aws-stack/tests/stack.test.ts +2 -2
  13. package/apps/aws-stack/tests/synth-no-bundle.test.ts +129 -0
  14. package/apps/aws-stack/tests/vitest.setup.ts +18 -0
  15. package/apps/aws-stack/vitest.config.ts +3 -0
  16. package/apps/cf-tcp-container/package.json +1 -1
  17. package/apps/cf-tcp-container/src/config-loader.ts +6 -7
  18. package/apps/cf-tcp-container/src/container-server.ts +3 -0
  19. package/apps/cf-tcp-container/tests/config-loader.test.ts +10 -3
  20. package/apps/cf-tcp-container/wrangler.toml +1 -1
  21. package/apps/cf-worker/package.json +2 -1
  22. package/apps/cf-worker/src/origin-allowlist.ts +99 -0
  23. package/apps/cf-worker/src/worker.ts +89 -9
  24. package/apps/cf-worker/tests/fixtures/web-dist/app/index.html +18 -0
  25. package/apps/cf-worker/tests/fixtures/web-dist/index.html +18 -0
  26. package/apps/cf-worker/tests/origin-allowlist.test.ts +101 -0
  27. package/apps/cf-worker/tests/smoke.test.ts +28 -2
  28. package/apps/cf-worker/tests/ws-origin.test.ts +89 -0
  29. package/apps/cf-worker/vitest.config.ts +1 -1
  30. package/apps/cf-worker/wrangler.test.toml +23 -0
  31. package/apps/cf-worker/wrangler.toml +59 -3
  32. package/apps/local-cli/package.json +1 -1
  33. package/apps/local-cli/src/config-loader.ts +6 -6
  34. package/apps/local-cli/src/main.ts +20 -0
  35. package/apps/local-cli/src/server.ts +9 -7
  36. package/apps/local-cli/tests/e2e.test.ts +112 -28
  37. package/apps/local-cli/tests/tcp.test.ts +71 -19
  38. package/apps/local-cli/tests/ws-subprotocol.test.ts +12 -7
  39. package/apps/web/landing/index.html +217 -0
  40. package/apps/web/package.json +28 -0
  41. package/apps/web/scripts/build.mjs +125 -0
  42. package/apps/web/src/build-env.ts +43 -0
  43. package/apps/web/src/config-schema.ts +138 -0
  44. package/apps/web/static/config.json +28 -0
  45. package/apps/web/static/config.prod.json +28 -0
  46. package/apps/web/static/config.staging.json +28 -0
  47. package/apps/web/tests/build-env.test.ts +63 -0
  48. package/apps/web/tests/build-smoke.test.ts +103 -0
  49. package/apps/web/tests/config-schema.test.ts +432 -0
  50. package/apps/web/tests/workspace.test.ts +12 -0
  51. package/apps/web/tsconfig.json +10 -0
  52. package/apps/web/upstream/.browserslistrc +3 -0
  53. package/apps/web/upstream/.editorconfig +9 -0
  54. package/apps/web/upstream/.eslintignore +3 -0
  55. package/apps/web/upstream/.eslintrc.js +90 -0
  56. package/apps/web/upstream/.github/FUNDING.yml +12 -0
  57. package/apps/web/upstream/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  58. package/apps/web/upstream/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  59. package/apps/web/upstream/.github/workflows/push.yml +26 -0
  60. package/apps/web/upstream/.github/workflows/release.yml +33 -0
  61. package/apps/web/upstream/.github/workflows/release_manual.yml +55 -0
  62. package/apps/web/upstream/.prettierrc.js +9 -0
  63. package/apps/web/upstream/.stylelintignore +5 -0
  64. package/apps/web/upstream/.stylelintrc.js +21 -0
  65. package/apps/web/upstream/LICENSE +201 -0
  66. package/apps/web/upstream/README.md +76 -0
  67. package/apps/web/upstream/babel.config.js +25 -0
  68. package/apps/web/upstream/crowdin.yml +3 -0
  69. package/apps/web/upstream/index.html +35 -0
  70. package/apps/web/upstream/jest.config.js +7 -0
  71. package/apps/web/upstream/jsdoc.json +22 -0
  72. package/apps/web/upstream/package.json +80 -0
  73. package/apps/web/upstream/scripts/pre-commit +43 -0
  74. package/apps/web/upstream/src/components/App.vue +516 -0
  75. package/apps/web/upstream/src/components/AppSettings.vue +587 -0
  76. package/apps/web/upstream/src/components/AutoComplete.vue +284 -0
  77. package/apps/web/upstream/src/components/Avatar.vue +105 -0
  78. package/apps/web/upstream/src/components/AwayStatusIndicator.vue +77 -0
  79. package/apps/web/upstream/src/components/BufferKey.vue +121 -0
  80. package/apps/web/upstream/src/components/BufferSettings.vue +97 -0
  81. package/apps/web/upstream/src/components/Captcha.vue +85 -0
  82. package/apps/web/upstream/src/components/ChannelBanlist.vue +96 -0
  83. package/apps/web/upstream/src/components/ChannelInfo.vue +159 -0
  84. package/apps/web/upstream/src/components/ChannelInvitelist.vue +276 -0
  85. package/apps/web/upstream/src/components/ChannelList.vue +345 -0
  86. package/apps/web/upstream/src/components/Container.vue +401 -0
  87. package/apps/web/upstream/src/components/ContainerHeader.vue +522 -0
  88. package/apps/web/upstream/src/components/ControlInput.vue +1016 -0
  89. package/apps/web/upstream/src/components/LoadingAnimation.vue +104 -0
  90. package/apps/web/upstream/src/components/MediaViewer.vue +199 -0
  91. package/apps/web/upstream/src/components/MessageInfo.vue +192 -0
  92. package/apps/web/upstream/src/components/MessageList.vue +1028 -0
  93. package/apps/web/upstream/src/components/MessageListAvatar.vue +20 -0
  94. package/apps/web/upstream/src/components/MessageListMessageCompact.vue +361 -0
  95. package/apps/web/upstream/src/components/MessageListMessageInline.vue +257 -0
  96. package/apps/web/upstream/src/components/MessageListMessageModern.vue +430 -0
  97. package/apps/web/upstream/src/components/NetworkSettings.vue +528 -0
  98. package/apps/web/upstream/src/components/Nicklist.vue +309 -0
  99. package/apps/web/upstream/src/components/NicklistUser.vue +181 -0
  100. package/apps/web/upstream/src/components/NotConnected.vue +271 -0
  101. package/apps/web/upstream/src/components/SelfUser.vue +283 -0
  102. package/apps/web/upstream/src/components/ServerSelector.vue +162 -0
  103. package/apps/web/upstream/src/components/ServerView.vue +126 -0
  104. package/apps/web/upstream/src/components/SettingsAdvanced.vue +232 -0
  105. package/apps/web/upstream/src/components/SettingsAliases.vue +121 -0
  106. package/apps/web/upstream/src/components/Sidebar.vue +429 -0
  107. package/apps/web/upstream/src/components/SidebarAboutBuffer.vue +288 -0
  108. package/apps/web/upstream/src/components/SidebarState.vue +145 -0
  109. package/apps/web/upstream/src/components/StartupError.vue +35 -0
  110. package/apps/web/upstream/src/components/StateBrowser.vue +420 -0
  111. package/apps/web/upstream/src/components/StateBrowserBuffer.vue +124 -0
  112. package/apps/web/upstream/src/components/StateBrowserNetwork.vue +823 -0
  113. package/apps/web/upstream/src/components/StateBrowserUsermenu.vue +162 -0
  114. package/apps/web/upstream/src/components/TypingStatusIndicator.vue +34 -0
  115. package/apps/web/upstream/src/components/TypingUsersList.vue +56 -0
  116. package/apps/web/upstream/src/components/UrlEmbed.vue +149 -0
  117. package/apps/web/upstream/src/components/UserBox.vue +728 -0
  118. package/apps/web/upstream/src/components/inputtools/Emoji.vue +67 -0
  119. package/apps/web/upstream/src/components/inputtools/TextStyle.vue +142 -0
  120. package/apps/web/upstream/src/components/startups/CommonLayout.vue +208 -0
  121. package/apps/web/upstream/src/components/startups/CustomServer.vue +495 -0
  122. package/apps/web/upstream/src/components/startups/KiwiBnc.vue +361 -0
  123. package/apps/web/upstream/src/components/startups/Personal.vue +317 -0
  124. package/apps/web/upstream/src/components/startups/Welcome.vue +544 -0
  125. package/apps/web/upstream/src/components/startups/ZncLogin.vue +229 -0
  126. package/apps/web/upstream/src/components/utils/InputConfirm.vue +68 -0
  127. package/apps/web/upstream/src/components/utils/InputPrompt.vue +118 -0
  128. package/apps/web/upstream/src/components/utils/InputText.vue +172 -0
  129. package/apps/web/upstream/src/components/utils/IrcInput.vue +579 -0
  130. package/apps/web/upstream/src/components/utils/PluginWrapper.vue +26 -0
  131. package/apps/web/upstream/src/components/utils/TabbedView.vue +149 -0
  132. package/apps/web/upstream/src/components/utils/TransitionExpand.vue +97 -0
  133. package/apps/web/upstream/src/helpers/Colours.js +128 -0
  134. package/apps/web/upstream/src/helpers/IrcdDiffs.js +26 -0
  135. package/apps/web/upstream/src/helpers/Md5.js +193 -0
  136. package/apps/web/upstream/src/helpers/Misc.js +401 -0
  137. package/apps/web/upstream/src/helpers/TextFormatting.js +237 -0
  138. package/apps/web/upstream/src/libs/AliasRewriter.js +157 -0
  139. package/apps/web/upstream/src/libs/AudioManager.js +60 -0
  140. package/apps/web/upstream/src/libs/BouncerMiddleware.js +247 -0
  141. package/apps/web/upstream/src/libs/BouncerProvider.js +551 -0
  142. package/apps/web/upstream/src/libs/ChathistoryMiddleware.js +153 -0
  143. package/apps/web/upstream/src/libs/ConfigLoader.js +94 -0
  144. package/apps/web/upstream/src/libs/EmojiProvider.js +46 -0
  145. package/apps/web/upstream/src/libs/GlobalApi.js +346 -0
  146. package/apps/web/upstream/src/libs/IPC.js +51 -0
  147. package/apps/web/upstream/src/libs/InputHandler.js +921 -0
  148. package/apps/web/upstream/src/libs/IrcClient.js +1506 -0
  149. package/apps/web/upstream/src/libs/Logger.js +71 -0
  150. package/apps/web/upstream/src/libs/Message.js +169 -0
  151. package/apps/web/upstream/src/libs/MessageFormatter.js +364 -0
  152. package/apps/web/upstream/src/libs/MessageParser.js +249 -0
  153. package/apps/web/upstream/src/libs/Notifications.js +78 -0
  154. package/apps/web/upstream/src/libs/ServerConnection.js +270 -0
  155. package/apps/web/upstream/src/libs/ServerSession.js +102 -0
  156. package/apps/web/upstream/src/libs/SoundBleep.js +20 -0
  157. package/apps/web/upstream/src/libs/StatePersistence.js +90 -0
  158. package/apps/web/upstream/src/libs/ThemeManager.js +128 -0
  159. package/apps/web/upstream/src/libs/TypingMiddleware.js +105 -0
  160. package/apps/web/upstream/src/libs/WindowTitle.js +63 -0
  161. package/apps/web/upstream/src/libs/batchedAdd.js +74 -0
  162. package/apps/web/upstream/src/libs/bufferTools.js +177 -0
  163. package/apps/web/upstream/src/libs/polyfill/Element.closest.js +18 -0
  164. package/apps/web/upstream/src/libs/renderers/Html.js +113 -0
  165. package/apps/web/upstream/src/libs/settingTools.js +31 -0
  166. package/apps/web/upstream/src/libs/state/BufferState.js +703 -0
  167. package/apps/web/upstream/src/libs/state/NetworkState.js +158 -0
  168. package/apps/web/upstream/src/libs/state/UserState.js +89 -0
  169. package/apps/web/upstream/src/libs/state/common.js +26 -0
  170. package/apps/web/upstream/src/libs/state.js +961 -0
  171. package/apps/web/upstream/src/libs/storage/Local.js +51 -0
  172. package/apps/web/upstream/src/main.js +566 -0
  173. package/apps/web/upstream/src/res/autocompleteCommands.js +31 -0
  174. package/apps/web/upstream/src/res/configTemplates.js +373 -0
  175. package/apps/web/upstream/src/res/globalStyle.css +277 -0
  176. package/apps/web/upstream/src/res/kiwiLoadingLogo.png +0 -0
  177. package/apps/web/upstream/src/res/locales/app.af-ZA.po +1145 -0
  178. package/apps/web/upstream/src/res/locales/app.ar-SA.po +1145 -0
  179. package/apps/web/upstream/src/res/locales/app.bg-BG.po +1145 -0
  180. package/apps/web/upstream/src/res/locales/app.bs-BA.po +1145 -0
  181. package/apps/web/upstream/src/res/locales/app.ca-ES.po +1145 -0
  182. package/apps/web/upstream/src/res/locales/app.cs-CZ.po +1145 -0
  183. package/apps/web/upstream/src/res/locales/app.da-DK.po +1145 -0
  184. package/apps/web/upstream/src/res/locales/app.de-DE.po +1145 -0
  185. package/apps/web/upstream/src/res/locales/app.dev.po +1246 -0
  186. package/apps/web/upstream/src/res/locales/app.el-GR.po +1145 -0
  187. package/apps/web/upstream/src/res/locales/app.en-US.po +1145 -0
  188. package/apps/web/upstream/src/res/locales/app.es-419.po +1145 -0
  189. package/apps/web/upstream/src/res/locales/app.es-AR.po +1145 -0
  190. package/apps/web/upstream/src/res/locales/app.es-EM.po +536 -0
  191. package/apps/web/upstream/src/res/locales/app.es-ES.po +1145 -0
  192. package/apps/web/upstream/src/res/locales/app.es-US.po +1145 -0
  193. package/apps/web/upstream/src/res/locales/app.eu-ES.po +1145 -0
  194. package/apps/web/upstream/src/res/locales/app.fi-FI.po +1145 -0
  195. package/apps/web/upstream/src/res/locales/app.fr-FR.po +1145 -0
  196. package/apps/web/upstream/src/res/locales/app.gl-ES.po +1145 -0
  197. package/apps/web/upstream/src/res/locales/app.he-IL.po +1145 -0
  198. package/apps/web/upstream/src/res/locales/app.hi-IN.po +1145 -0
  199. package/apps/web/upstream/src/res/locales/app.hu-HU.po +1145 -0
  200. package/apps/web/upstream/src/res/locales/app.id-ID.po +1145 -0
  201. package/apps/web/upstream/src/res/locales/app.it-IT.po +1145 -0
  202. package/apps/web/upstream/src/res/locales/app.ja-JP.po +1145 -0
  203. package/apps/web/upstream/src/res/locales/app.ko-KR.po +1145 -0
  204. package/apps/web/upstream/src/res/locales/app.nl-NL.po +1145 -0
  205. package/apps/web/upstream/src/res/locales/app.no-NO.po +1145 -0
  206. package/apps/web/upstream/src/res/locales/app.pl-PL.po +1145 -0
  207. package/apps/web/upstream/src/res/locales/app.pt-BR.po +1145 -0
  208. package/apps/web/upstream/src/res/locales/app.pt-PT.po +1145 -0
  209. package/apps/web/upstream/src/res/locales/app.ro-RO.po +1145 -0
  210. package/apps/web/upstream/src/res/locales/app.ru-RU.po +1145 -0
  211. package/apps/web/upstream/src/res/locales/app.sl-SI.po +1145 -0
  212. package/apps/web/upstream/src/res/locales/app.sq-AL.po +1145 -0
  213. package/apps/web/upstream/src/res/locales/app.sr-SP.po +1145 -0
  214. package/apps/web/upstream/src/res/locales/app.sv-SE.po +1145 -0
  215. package/apps/web/upstream/src/res/locales/app.tr-TR.po +1145 -0
  216. package/apps/web/upstream/src/res/locales/app.uk-UA.po +1145 -0
  217. package/apps/web/upstream/src/res/locales/app.vi-VN.po +1145 -0
  218. package/apps/web/upstream/src/res/locales/app.zh-CN.po +1145 -0
  219. package/apps/web/upstream/src/res/locales/app.zh-TW.po +1145 -0
  220. package/apps/web/upstream/src/res/localesList.json +27 -0
  221. package/apps/web/upstream/src/res/logo.png +0 -0
  222. package/apps/web/upstream/src/thirdparty/about.html +43 -0
  223. package/apps/web/upstream/src/thirdparty/index.js +5 -0
  224. package/apps/web/upstream/src/thirdparty/kiwiirccom.vue +185 -0
  225. package/apps/web/upstream/static/config.json +28 -0
  226. package/apps/web/upstream/static/emoticons/smile.png +0 -0
  227. package/apps/web/upstream/static/favicon.png +0 -0
  228. package/apps/web/upstream/static/highlight.mp3 +0 -0
  229. package/apps/web/upstream/static/highlight.ogg +0 -0
  230. package/apps/web/upstream/static/locales/.gitignore +2 -0
  231. package/apps/web/upstream/static/plugins/customise.html.example +10 -0
  232. package/apps/web/upstream/static/themes/coffee/theme.css +145 -0
  233. package/apps/web/upstream/static/themes/common/base.css +1064 -0
  234. package/apps/web/upstream/static/themes/dark/theme.css +196 -0
  235. package/apps/web/upstream/static/themes/default/theme.css +92 -0
  236. package/apps/web/upstream/static/themes/elite/theme.css +248 -0
  237. package/apps/web/upstream/static/themes/grayfox/theme.css +143 -0
  238. package/apps/web/upstream/static/themes/nightswatch/theme.css +367 -0
  239. package/apps/web/upstream/static/themes/osprey/theme.css +115 -0
  240. package/apps/web/upstream/static/themes/radioactive/theme.css +1211 -0
  241. package/apps/web/upstream/static/themes/sky/theme.css +107 -0
  242. package/apps/web/upstream/tests/unit/BatchAdd.spec.js +174 -0
  243. package/apps/web/upstream/tests/unit/MessageParser.spec.js +125 -0
  244. package/apps/web/upstream/tests/unit/Misc.spec.js +24 -0
  245. package/apps/web/upstream/tests/unit/NetworkState.spec.js +58 -0
  246. package/apps/web/upstream/tests/unit/StartupError.spec.js +20 -0
  247. package/apps/web/upstream/vue.config.js +150 -0
  248. package/apps/web/upstream/yarn.lock +9767 -0
  249. package/apps/web/vitest.config.ts +13 -0
  250. package/biome.json +2 -0
  251. package/docs/ADR-001-pure-reducers-and-effect-system.md +74 -0
  252. package/docs/ADR-002-location-of-authority.md +82 -0
  253. package/docs/ADR-003-durable-object-sharding.md +110 -0
  254. package/docs/ADR-004-dynamodb-schema.md +96 -0
  255. package/docs/ADR-005-wss-only-transport-v1.md +83 -0
  256. package/docs/ADR-006-sasl-mechanism-scope.md +96 -0
  257. package/docs/ADR-007-deterministic-ports.md +82 -0
  258. package/docs/ADR-008-monorepo-tooling.md +60 -0
  259. package/docs/ADR-009-dual-transport-wss-and-irc-tls.md +138 -0
  260. package/docs/ADR-Index.md +15 -0
  261. package/docs/AWS-Adapter-Architecture.md +496 -0
  262. package/docs/AWS-Deployment.md +1275 -0
  263. package/docs/AWS-TCP-Deployment.md +410 -0
  264. package/docs/Cloudflare-Deployment-Guide.md +719 -0
  265. package/docs/Cloudflare-TCP-Deployment.md +510 -0
  266. package/docs/Home.md +16 -0
  267. package/docs/Observability.md +87 -0
  268. package/docs/PlanExtensions.md +812 -0
  269. package/docs/PlanIRCv3Websocket.md +503 -0
  270. package/docs/PlanWebClient.md +451 -0
  271. package/docs/Release-Process.md +443 -0
  272. package/docs/WebClientGuide.md +535 -0
  273. package/package.json +2 -2
  274. package/packages/aws-adapter/package.json +1 -1
  275. package/packages/aws-adapter/src/handlers/default.ts +3 -0
  276. package/packages/aws-adapter/src/handlers/nlb-stream.ts +9 -0
  277. package/packages/aws-adapter/src/serialize.ts +29 -1
  278. package/packages/aws-adapter/tests/account-store-dynamo.test.ts +49 -8
  279. package/packages/aws-adapter/tests/account-store.test.ts +4 -7
  280. package/packages/aws-adapter/tests/aws-harness.ts +5 -2
  281. package/packages/aws-adapter/tests/aws-integration.test.ts +8 -4
  282. package/packages/aws-adapter/tests/aws-runtime.test.ts +79 -0
  283. package/packages/aws-adapter/tests/config-loader.test.ts +11 -2
  284. package/packages/aws-adapter/tests/connect.test.ts +9 -9
  285. package/packages/aws-adapter/tests/disconnect-fanout.test.ts +3 -4
  286. package/packages/aws-adapter/tests/global-setup.ts +55 -30
  287. package/packages/aws-adapter/tests/gone-exception.test.ts +4 -9
  288. package/packages/aws-adapter/tests/handlers.test.ts +90 -4
  289. package/packages/aws-adapter/tests/message-store.test.ts +6 -5
  290. package/packages/aws-adapter/tests/nlb-stream.test.ts +60 -8
  291. package/packages/cf-adapter/package.json +2 -1
  292. package/packages/cf-adapter/src/connection-do.ts +3 -0
  293. package/packages/cf-adapter/src/serialize.ts +25 -4
  294. package/packages/cf-adapter/tests/cf-harness.ts +12 -1
  295. package/packages/cf-adapter/tests/cf-runtime.test.ts +269 -0
  296. package/packages/cf-adapter/tests/channel-do.test.ts +117 -0
  297. package/packages/cf-adapter/tests/config-loader.test.ts +49 -0
  298. package/packages/cf-adapter/tests/connection-do-pure.test.ts +91 -0
  299. package/packages/cf-adapter/tests/d1-account-store.test.ts +48 -0
  300. package/packages/cf-adapter/tests/registry-do.test.ts +104 -0
  301. package/packages/cf-adapter/tests/serialize.test.ts +308 -0
  302. package/packages/cf-adapter/vitest.config.ts +1 -1
  303. package/packages/in-memory-runtime/package.json +1 -1
  304. package/packages/irc-core/package.json +1 -1
  305. package/packages/irc-core/reports/mutation/mutation.html +342 -0
  306. package/packages/irc-core/src/caps/capabilities.ts +37 -3
  307. package/packages/irc-core/src/caps/index.ts +1 -0
  308. package/packages/irc-core/src/caps/sts.ts +84 -0
  309. package/packages/irc-core/src/commands/account-notify.ts +53 -0
  310. package/packages/irc-core/src/commands/away.ts +9 -3
  311. package/packages/irc-core/src/commands/cap.ts +23 -5
  312. package/packages/irc-core/src/commands/chathistory.ts +40 -11
  313. package/packages/irc-core/src/commands/index.ts +34 -0
  314. package/packages/irc-core/src/commands/isupport.ts +53 -0
  315. package/packages/irc-core/src/commands/mode.ts +8 -1
  316. package/packages/irc-core/src/commands/monitor.ts +327 -0
  317. package/packages/irc-core/src/commands/multiline.ts +256 -0
  318. package/packages/irc-core/src/commands/pre-away.ts +112 -0
  319. package/packages/irc-core/src/commands/privmsg.ts +19 -12
  320. package/packages/irc-core/src/commands/read-marker.ts +108 -0
  321. package/packages/irc-core/src/commands/registration.ts +8 -0
  322. package/packages/irc-core/src/commands/sasl.ts +24 -1
  323. package/packages/irc-core/src/commands/tagmsg.ts +71 -1
  324. package/packages/irc-core/src/commands/whois.ts +5 -0
  325. package/packages/irc-core/src/config.ts +65 -10
  326. package/packages/irc-core/src/effects.ts +14 -0
  327. package/packages/irc-core/src/ports.ts +389 -0
  328. package/packages/irc-core/src/protocol/index.ts +14 -0
  329. package/packages/irc-core/src/protocol/labeled-response.ts +133 -0
  330. package/packages/irc-core/src/protocol/numerics.ts +15 -0
  331. package/packages/irc-core/src/protocol/outbound.ts +16 -1
  332. package/packages/irc-core/src/protocol/standard-replies.ts +277 -0
  333. package/packages/irc-core/src/state/connection.ts +32 -1
  334. package/packages/irc-core/src/types.ts +112 -0
  335. package/packages/irc-core/stryker.commands.conf.json +1 -2
  336. package/packages/irc-core/tests/away-store.test.ts +73 -0
  337. package/packages/irc-core/tests/batch.test.ts +15 -0
  338. package/packages/irc-core/tests/caps/capabilities.test.ts +119 -2
  339. package/packages/irc-core/tests/caps/sts.test.ts +123 -0
  340. package/packages/irc-core/tests/commands/account-notify.test.ts +171 -0
  341. package/packages/irc-core/tests/commands/away.test.ts +85 -2
  342. package/packages/irc-core/tests/commands/cap.test.ts +165 -0
  343. package/packages/irc-core/tests/commands/chathistory.test.ts +148 -1
  344. package/packages/irc-core/tests/commands/echo-message.test.ts +9 -3
  345. package/packages/irc-core/tests/commands/isupport.test.ts +80 -0
  346. package/packages/irc-core/tests/commands/mode.test.ts +72 -0
  347. package/packages/irc-core/tests/commands/monitor.test.ts +411 -0
  348. package/packages/irc-core/tests/commands/multiline.test.ts +428 -0
  349. package/packages/irc-core/tests/commands/pre-away.test.ts +241 -0
  350. package/packages/irc-core/tests/commands/privmsg.test.ts +154 -3
  351. package/packages/irc-core/tests/commands/read-marker.test.ts +211 -0
  352. package/packages/irc-core/tests/commands/registration.test.ts +64 -0
  353. package/packages/irc-core/tests/commands/sasl.test.ts +116 -2
  354. package/packages/irc-core/tests/commands/tagmsg.test.ts +357 -0
  355. package/packages/irc-core/tests/commands/whois.test.ts +34 -0
  356. package/packages/irc-core/tests/config.test.ts +103 -13
  357. package/packages/irc-core/tests/labeled-response.test.ts +181 -0
  358. package/packages/irc-core/tests/message-tags.test.ts +114 -0
  359. package/packages/irc-core/tests/monitor-store.test.ts +200 -0
  360. package/packages/irc-core/tests/numerics.test.ts +13 -0
  361. package/packages/irc-core/tests/parser.test.ts +109 -0
  362. package/packages/irc-core/tests/read-marker-store.test.ts +108 -0
  363. package/packages/irc-core/tests/standard-replies.test.ts +412 -0
  364. package/packages/irc-core/tests/types.test.ts +27 -0
  365. package/packages/irc-server/package.json +1 -1
  366. package/packages/irc-server/src/actor.ts +450 -3
  367. package/packages/irc-server/src/dispatch.ts +108 -16
  368. package/packages/irc-server/tests/actor.test.ts +1432 -39
  369. package/packages/irc-server/tests/dispatch.test.ts +263 -2
  370. package/packages/irc-test-support/package.json +1 -1
  371. package/packages/irc-test-support/src/index.ts +6 -0
  372. package/packages/irc-test-support/src/scenarios.ts +24 -2
  373. package/packages/irc-test-support/src/test-config.ts +54 -0
  374. package/packages/irc-test-support/tests/test-config.test.ts +51 -0
  375. package/tools/ci-hardening/package.json +1 -1
  376. package/tools/ci-hardening/tests/ddb-local.test.ts +82 -0
  377. package/tools/load-test/package.json +33 -0
  378. package/tools/load-test/src/client.ts +351 -0
  379. package/tools/load-test/src/config.ts +313 -0
  380. package/tools/load-test/src/harness.ts +116 -0
  381. package/tools/load-test/src/main.ts +120 -0
  382. package/tools/load-test/src/metrics.ts +168 -0
  383. package/tools/load-test/src/report.ts +106 -0
  384. package/tools/load-test/tests/client.test.ts +212 -0
  385. package/tools/load-test/tests/config.test.ts +152 -0
  386. package/tools/load-test/tests/framing.test.ts +37 -0
  387. package/tools/load-test/tests/harness.test.ts +165 -0
  388. package/tools/load-test/tests/metrics.test.ts +174 -0
  389. package/tools/load-test/tests/report.test.ts +161 -0
  390. package/tools/load-test/tests/smoke.test.ts +67 -0
  391. package/tools/load-test/tsconfig.build.json +12 -0
  392. package/tools/load-test/tsconfig.test.json +10 -0
  393. package/tools/load-test/vitest.config.ts +29 -0
  394. package/tools/tcp-ws-forwarder/package.json +1 -1
@@ -0,0 +1,71 @@
1
+ 'kiwi public';
2
+
3
+ const defaultLogger = makeLogger();
4
+ export default defaultLogger;
5
+
6
+ function makeLogger(label, rootLogger) {
7
+ function logger(...args) {
8
+ logger.info(...args);
9
+ }
10
+
11
+ logger.LEVEL_DEBUG = 2;
12
+ logger.LEVEL_INFO = 1;
13
+ logger.LEVEL_ERROR = 0;
14
+ logger.level = logger.LEVEL_ERROR;
15
+
16
+ function logLevel(compareLevel) {
17
+ let l = rootLogger || logger;
18
+ return l.level >= compareLevel;
19
+ }
20
+
21
+ logger.debug = function logDebug(...args) {
22
+ if (logLevel(logger.LEVEL_DEBUG)) {
23
+ if (label) {
24
+ args[0] = `[${label}] DEBUG ${args[0]}`;
25
+ }
26
+ window.console.log(...args);
27
+ }
28
+ };
29
+
30
+ logger.info = function logInfo(...args) {
31
+ if (logLevel(logger.LEVEL_INFO)) {
32
+ if (label) {
33
+ args[0] = `[${label}] INFO ${args[0]}`;
34
+ }
35
+ window.console.log(...args);
36
+ }
37
+ };
38
+
39
+ logger.error = function logError(...args) {
40
+ if (logLevel(logger.LEVEL_ERROR)) {
41
+ if (label) {
42
+ args[0] = `[${label}] ERROR ${args[0]}`;
43
+ }
44
+
45
+ window.console.error(...args);
46
+ }
47
+ };
48
+
49
+ logger.assert = function assert(condition, ...args) {
50
+ if (condition) {
51
+ return;
52
+ }
53
+
54
+ this.error('Assertion failed.', ...args);
55
+ };
56
+
57
+ logger.setLevel = function setLevel(newLevel) {
58
+ logger.level = newLevel;
59
+ };
60
+
61
+ logger.namespace = function namespace(newLabel) {
62
+ let l = newLabel;
63
+ if (label) {
64
+ l = `[${label}][${l}]`;
65
+ }
66
+
67
+ return makeLogger(l, logger);
68
+ };
69
+
70
+ return logger;
71
+ }
@@ -0,0 +1,169 @@
1
+ 'kiwi public';
2
+
3
+ import Vue from 'vue';
4
+ import parseMessage from '@/libs/MessageParser';
5
+ import toHtml from '@/libs/renderers/Html';
6
+ import GlobalApi from '@/libs/GlobalApi';
7
+ import getState from './state';
8
+
9
+ let nextId = 0;
10
+
11
+ function def(target, key, value) {
12
+ Object.defineProperty(target, key, {
13
+ writable: true,
14
+ value,
15
+ });
16
+ }
17
+
18
+ export default class Message {
19
+ constructor(message, user) {
20
+ // instance_num is a running number for all messages created within Kiwi. Used to order
21
+ // messages if the message time is the same.
22
+ def(this, 'instance_num', nextId++);
23
+ def(this, 'id', extractMessageId(message) || nextId++);
24
+
25
+ // internal_time is used to allow for a getter/setter
26
+ // so day_num can be updated if the time is changed
27
+ def(this, 'internal_time', null);
28
+ def(this, 'day_num', null);
29
+
30
+ // Two different times;
31
+ // time = time in the users local time (getter/setter)
32
+ // server_time = time the server gave us
33
+ this.time = message.time || Date.now();
34
+ def(this, 'server_time', message.server_time || this.time);
35
+ def(this, 'nick', message.nick);
36
+ def(this, 'message', message.message);
37
+ def(this, 'tags', message.tags);
38
+ def(this, 'type', message.type || 'message');
39
+ def(this, 'type_extra', message.type_extra);
40
+ def(this, 'ignore', false);
41
+ def(this, 'mentioned_urls', []);
42
+ // If embed.payload is truthy, it will be embedded within the message
43
+ this.embed = { type: 'url', payload: null };
44
+ this.html = '';
45
+ this.blocks = [];
46
+ def(this, 'hasRendered', false);
47
+ // template should be null or a Vue component to render this message
48
+ def(this, 'template', message.template || null);
49
+ def(this, 'templateProps', message.templateProps || {});
50
+ // bodyTemplate should be null or a Vue component to render in the body of the message
51
+ def(this, 'bodyTemplate', message.bodyTemplate || null);
52
+ def(this, 'bodyTemplateProps', message.bodyTemplateProps || {});
53
+ def(this, 'isHighlight', false);
54
+
55
+ // We don't want the user object to be enumerable
56
+ Object.defineProperty(this, 'user', { value: user });
57
+
58
+ Vue.observable(this);
59
+ }
60
+
61
+ get time() {
62
+ return this.internal_time;
63
+ }
64
+
65
+ set time(newTime) {
66
+ this.internal_time = newTime;
67
+ // txOffset is the milliseconds needed to get localtime to UTC
68
+ // eg UTC+1 = -3,600,000
69
+ const tzOffset = (new Date(newTime)).getTimezoneOffset() * 60000;
70
+ // 68400000 equals one day in milliseconds
71
+ this.day_num = Math.floor((newTime - tzOffset) / 86400000);
72
+ }
73
+
74
+ render() {
75
+ // Allow plugins to render their own messages if needed
76
+ GlobalApi.singleton().emit('message.render', { message: this });
77
+ return this;
78
+ }
79
+
80
+ toHtml(messageList) {
81
+ if (this.hasRendered) {
82
+ return this.html;
83
+ }
84
+
85
+ this.hasRendered = true;
86
+
87
+ let state = getState();
88
+ let showEmoticons = state.setting('buffers.show_emoticons') && !messageList.buffer.isSpecial();
89
+
90
+ this.toBlocks(messageList.buffer, messageList.useExtraFormatting);
91
+
92
+ state.$emit('message.prestyle', { message: this, blocks: this.blocks });
93
+
94
+ let content = toHtml(this.blocks, showEmoticons);
95
+ this.html = content;
96
+
97
+ state.$emit('message.poststyle', { message: this, blocks: this.blocks });
98
+ return this.html;
99
+ }
100
+
101
+ toBlocks(buffer, useExtraFormatting) {
102
+ let state = getState();
103
+ let userList = buffer.users;
104
+
105
+ let blocks = parseMessage(
106
+ this.message,
107
+ {
108
+ extras: !buffer.isSpecial() && useExtraFormatting && this.type === 'privmsg',
109
+ },
110
+ userList
111
+ );
112
+
113
+ this.mentioned_urls = blocks.filter((block) => block.type === 'url').map((block) => block.meta.url);
114
+ this.maybeAutoEmbed();
115
+
116
+ state.$emit('message.blocks', { message: this, blocks: blocks });
117
+ this.blocks = blocks;
118
+ return blocks;
119
+ }
120
+
121
+ maybeAutoEmbed() {
122
+ if (!this.mentioned_urls || this.mentioned_urls.length === 0) {
123
+ return;
124
+ }
125
+
126
+ // Only auto preview links on user messages. Traffic, topics, notices, etc would get
127
+ // annoying as they usually contain links of some sort
128
+ if (this.type !== 'privmsg') {
129
+ return;
130
+ }
131
+
132
+ let url = this.mentioned_urls[0];
133
+
134
+ let whitelistRegex = getState().setting('buffers.inline_link_auto_preview_whitelist');
135
+ whitelistRegex = (whitelistRegex || '').trim();
136
+ try {
137
+ if (!whitelistRegex || !(new RegExp(whitelistRegex, 'i')).test(url)) {
138
+ return;
139
+ }
140
+ } catch (err) {
141
+ // A bad regex pattern will throw an error
142
+ return;
143
+ }
144
+
145
+ this.embed.payload = url;
146
+ this.embed.type = 'url';
147
+ }
148
+
149
+ serialise() {
150
+ return {
151
+ id: this.id,
152
+ time: this.time,
153
+ server_time: this.server_time,
154
+ nick: this.nick,
155
+ message: this.message,
156
+ tags: this.tags,
157
+ type: this.type,
158
+ type_extra: this.type_extra,
159
+ };
160
+ }
161
+ }
162
+
163
+ function extractMessageId(message) {
164
+ if (!message.tags) {
165
+ return undefined;
166
+ }
167
+
168
+ return message.tags.msgid || message.tags['draft/msgid'] || undefined;
169
+ }
@@ -0,0 +1,364 @@
1
+ 'kiwi public';
2
+
3
+ const tokens = Object.create(null);
4
+
5
+ /**
6
+ * Token functions may return:
7
+ * null - move forward in the input by the length of the token
8
+ * -1 - do not treat this character as a token and continue as normal content
9
+ * 0+ - move to this point in the input
10
+ */
11
+
12
+ /* eslint-disable dot-notation */
13
+ tokens['_'] = {
14
+ token: '_',
15
+ extra: true,
16
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
17
+ if (openToks[this.token]) {
18
+ delete block.styles.underline;
19
+ openToks[this.token] = null;
20
+ prevBlock.content += this.token;
21
+ return null;
22
+ }
23
+
24
+ // If this style is alrady open by something else, ignore it
25
+ if (block.styles.underline === true) {
26
+ return -1;
27
+ }
28
+
29
+ // Underscores may be part of a word or URL so consider it an opening
30
+ if (pos > 0 && inp[pos - 1] !== ' ') {
31
+ return -1;
32
+ }
33
+
34
+ // token if it's on it's own
35
+ // Only underline if we have a closing _ further on
36
+ if (inp.substr(pos + 1).indexOf(this.token) === -1) {
37
+ return -1;
38
+ }
39
+
40
+ openToks[this.token] = true;
41
+ block.styles.underline = true;
42
+ block.content += this.token;
43
+
44
+ return null;
45
+ },
46
+ };
47
+ tokens['*'] = {
48
+ token: '*',
49
+ extra: true,
50
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
51
+ if (openToks[this.token]) {
52
+ delete block.styles.italic;
53
+ openToks[this.token] = null;
54
+ prevBlock.content += this.token;
55
+ return null;
56
+ }
57
+
58
+ // If this style is alrady open by something else, ignore it
59
+ if (block.styles.italic === true) {
60
+ return -1;
61
+ }
62
+
63
+ // Ignore is after a : character. :* is usually a kiss emoji
64
+ if (inp[pos - 1] === ':') {
65
+ return -1;
66
+ }
67
+
68
+ // * may be part of a word (ie. pasting code) or URL so only start bolding if * is after a
69
+ // space
70
+ if (pos > 0 && inp[pos - 1] !== ' ') {
71
+ return -1;
72
+ }
73
+
74
+ // Only style if:
75
+ // * we have a closing * further on
76
+ // * the * further on has a space after it or is the last character
77
+ let remainingText = inp.substr(pos + 1);
78
+ let nextPos = remainingText.indexOf(this.token);
79
+ if (
80
+ nextPos === -1 ||
81
+ (nextPos < remainingText.length - 1 && remainingText[nextPos + 1] !== ' ')
82
+ ) {
83
+ return -1;
84
+ }
85
+
86
+ openToks[this.token] = true;
87
+ block.styles.italic = true;
88
+ block.content += this.token;
89
+
90
+ return null;
91
+ },
92
+ };
93
+ tokens['**'] = {
94
+ token: '**',
95
+ extra: true,
96
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
97
+ if (openToks[this.token]) {
98
+ delete block.styles.bold;
99
+ openToks[this.token] = null;
100
+ prevBlock.content += this.token;
101
+ return null;
102
+ }
103
+
104
+ // If this style is alrady open by something else, ignore it
105
+ if (block.styles.bold === true) {
106
+ return -1;
107
+ }
108
+
109
+ // Only style if we have a closing ** further on
110
+ if (inp.substr(pos + 1).indexOf(this.token) === -1) {
111
+ return -1;
112
+ }
113
+
114
+ openToks[this.token] = true;
115
+ block.styles.bold = true;
116
+ block.content += this.token;
117
+
118
+ return null;
119
+ },
120
+ };
121
+ tokens['`'] = {
122
+ token: '`',
123
+ extra: true,
124
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
125
+ if (openToks[this.token]) {
126
+ delete block.styles.quote;
127
+ openToks[this.token] = null;
128
+ prevBlock.content += this.token;
129
+ return null;
130
+ }
131
+
132
+ // Backticks may be part of a word or NICK so only consider it a codeblock if
133
+ // it's at the start of a scentence or comes after a space
134
+ if (pos > 0 && inp[pos - 1] !== ' ') {
135
+ return -1;
136
+ }
137
+
138
+ // Find the closing backtick
139
+ let str = inp.substr(pos + 1);
140
+ let endPos = str.indexOf(this.token);
141
+
142
+ // If we don't have a closing backtick further on, don't take this as an opening backtick
143
+ if (endPos === -1) {
144
+ return -1;
145
+ }
146
+
147
+ // Only consider the found closing backtick as closing if it comes before a space or is at
148
+ // the end of the text. If it's in the middle of text then it's highly lickely part of that
149
+ // text and not actually closing. eg. `hello and wel`come
150
+ if (str[endPos + 1] && str[endPos + 1] !== ' ') {
151
+ return -1;
152
+ }
153
+
154
+ // No styling should appear in this codeblock. Add all the content we can
155
+ // before jumping the position forward in the input
156
+ openToks[this.token] = true;
157
+ block.styles.quote = true;
158
+ block.content += this.token + str.substr(0, endPos);
159
+ block.containsContent = true;
160
+ // The + 1 because:
161
+ // We added 2 ` characters, but we want the last ` character to call this
162
+ // fn again so it can be closed.
163
+ return pos + endPos + 1;
164
+ },
165
+ };
166
+
167
+ // Bold
168
+ tokens['\x02'] = {
169
+ token: '\x02',
170
+ extra: false,
171
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
172
+ if (openToks[this.token]) {
173
+ delete block.styles.bold;
174
+ openToks[this.token] = null;
175
+ } else {
176
+ openToks[this.token] = true;
177
+ block.styles.bold = true;
178
+ }
179
+
180
+ return null;
181
+ },
182
+ };
183
+
184
+ // Italic
185
+ tokens['\x1D'] = {
186
+ token: '\x1D',
187
+ extra: false,
188
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
189
+ if (openToks[this.token]) {
190
+ delete block.styles.italic;
191
+ openToks[this.token] = null;
192
+ } else {
193
+ openToks[this.token] = true;
194
+ block.styles.italic = true;
195
+ }
196
+
197
+ return null;
198
+ },
199
+ };
200
+
201
+ // Underline
202
+ tokens['\x1F'] = {
203
+ token: '\x1F',
204
+ extra: false,
205
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
206
+ if (openToks[this.token]) {
207
+ delete block.styles.underline;
208
+ openToks[this.token] = null;
209
+ } else {
210
+ openToks[this.token] = true;
211
+ block.styles.underline = true;
212
+ }
213
+
214
+ return null;
215
+ },
216
+ };
217
+
218
+ // Clear all styles
219
+ tokens['\x0F'] = {
220
+ token: '\x0F',
221
+ extra: false,
222
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
223
+ Object.keys(block.styles).forEach((k) => delete block.styles[k]);
224
+ Object.keys(openToks).forEach((k) => delete openToks[k]);
225
+
226
+ return null;
227
+ },
228
+ };
229
+
230
+ // Colours
231
+ tokens['\x03'] = {
232
+ token: '\x03',
233
+ extra: false,
234
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
235
+ let colours = {
236
+ 0: 'white',
237
+ 1: 'black',
238
+ 2: 'blue',
239
+ 3: 'green',
240
+ 4: 'light-red',
241
+ 5: 'brown',
242
+ 6: 'purple',
243
+ 7: 'orange',
244
+ 8: 'yellow',
245
+ 9: 'light-green',
246
+ 10: 'cyan',
247
+ 11: 'light-cyan',
248
+ 12: 'light-blue',
249
+ 13: 'pink',
250
+ 14: 'grey',
251
+ 15: 'light-grey',
252
+ };
253
+
254
+ let colourMatchRegexp = /^\x03(([0-9][0-9]?)(,([0-9][0-9]?))?)/;
255
+ let match = colourMatchRegexp.exec(inp.substr(pos, 6));
256
+ if (match) {
257
+ // fg colour = 2, bg colour = 4
258
+ let fgColour = colours[parseInt(match[2], 10)];
259
+ let bgColour = colours[parseInt(match[4], 10)];
260
+ if (typeof fgColour !== 'undefined') {
261
+ block.styles.color = fgColour;
262
+ }
263
+ if (typeof bgColour !== 'undefined') {
264
+ block.styles.background = bgColour;
265
+ }
266
+
267
+ return pos + match[0].length;
268
+ }
269
+
270
+ // 03 without a colour = delete any existing colour
271
+ delete block.styles.color;
272
+ delete block.styles.background;
273
+
274
+ return null;
275
+ },
276
+ };
277
+
278
+ // Reverse (unimplemented)
279
+ tokens['\x16'] = {
280
+ token: '\x16',
281
+ extra: false,
282
+ fn: function parseToken(inp, pos, block, prevBlock, openToks) {
283
+ return null;
284
+ },
285
+ };
286
+
287
+ export default function parse(inp, _opts) {
288
+ let opts = _opts || {};
289
+ let block = createNewBlock();
290
+ let blocks = [block];
291
+ let openTokens = Object.create(null);
292
+
293
+ let pos = 0;
294
+ let len = inp.length;
295
+
296
+ while (pos < len) {
297
+ let tok = findTokenAtPosition();
298
+ if (!tok || (!opts.extras && tok.extra)) {
299
+ block.content += inp[pos];
300
+ block.containsContent = true;
301
+ pos++;
302
+ continue;
303
+ }
304
+
305
+ // Current character is a token of some sort
306
+
307
+ let newBlock = null;
308
+
309
+ // Consecutive tokens can stack up styles into the same blocks. A consecutive
310
+ // token means that the block before it will not have any content yet
311
+ if (block.containsContent) {
312
+ newBlock = createNewBlock();
313
+ } else {
314
+ newBlock = block;
315
+ }
316
+
317
+ Object.assign(newBlock.styles, block.styles);
318
+ let newPos = tok.fn(inp, pos, newBlock, block, openTokens);
319
+
320
+ if (newPos === -1) {
321
+ // The token invalidated itself so treat it as content
322
+ block.content += tok.token;
323
+ block.containsContent = true;
324
+ pos += tok.token.length;
325
+ continue;
326
+ }
327
+
328
+ block = newBlock;
329
+
330
+ // This block may have already been pushed if this is a consecutive token
331
+ if (blocks[blocks.length - 1] !== newBlock) {
332
+ blocks.push(newBlock);
333
+ }
334
+
335
+ if (typeof newPos === 'number') {
336
+ pos = newPos;
337
+ } else {
338
+ pos += tok.token.length;
339
+ }
340
+ }
341
+
342
+ return blocks;
343
+
344
+ function findTokenAtPosition() {
345
+ let tok = tokens[inp.substr(pos, 2)] || tokens[inp[pos]];
346
+ return tok;
347
+ }
348
+ }
349
+
350
+ export function createNewBlock(
351
+ content = '',
352
+ styles = {},
353
+ type = 'text',
354
+ meta = {}
355
+ ) {
356
+ const newBlock = {
357
+ styles: styles,
358
+ content: content,
359
+ containsContent: !!content,
360
+ type: type,
361
+ meta: meta,
362
+ };
363
+ return newBlock;
364
+ }