effect-web-midi 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +276 -0
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/src/EMIDIAccess.js +129 -0
  5. package/dist/src/EMIDIAccess.js.map +1 -0
  6. package/dist/src/EMIDIInput.js +226 -0
  7. package/dist/src/EMIDIInput.js.map +1 -0
  8. package/dist/src/EMIDIOutput.js +227 -0
  9. package/dist/src/EMIDIOutput.js.map +1 -0
  10. package/dist/src/EMIDIPort.js +218 -0
  11. package/dist/src/EMIDIPort.js.map +1 -0
  12. package/dist/src/MIDIErrors.js +4 -0
  13. package/dist/src/MIDIErrors.js.map +1 -0
  14. package/dist/src/MIDIEventStreams.js +2 -0
  15. package/dist/src/MIDIEventStreams.js.map +1 -0
  16. package/dist/src/Parsing.js +2 -0
  17. package/dist/src/Parsing.js.map +1 -0
  18. package/dist/src/StreamMaker.js +1 -0
  19. package/dist/src/StreamMaker.js.map +1 -0
  20. package/dist/src/Util.js +2 -0
  21. package/dist/src/Util.js.map +1 -0
  22. package/dist/src/index.js +10 -0
  23. package/dist/src/index.js.map +1 -0
  24. package/dist/src/internal/EMIDIAccess.js +634 -0
  25. package/dist/src/internal/EMIDIAccess.js.map +1 -0
  26. package/dist/src/internal/EMIDIInput.js +66 -0
  27. package/dist/src/internal/EMIDIInput.js.map +1 -0
  28. package/dist/src/internal/EMIDIOutput.js +120 -0
  29. package/dist/src/internal/EMIDIOutput.js.map +1 -0
  30. package/dist/src/internal/EMIDIPort.js +125 -0
  31. package/dist/src/internal/EMIDIPort.js.map +1 -0
  32. package/dist/src/internal/MIDIErrors.js +190 -0
  33. package/dist/src/internal/MIDIErrors.js.map +1 -0
  34. package/dist/src/internal/MIDIEventStreams.js +41 -0
  35. package/dist/src/internal/MIDIEventStreams.js.map +1 -0
  36. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.js +27 -0
  37. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.js.map +1 -0
  38. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.js +19 -0
  39. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.js.map +1 -0
  40. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.js +16 -0
  41. package/dist/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.js.map +1 -0
  42. package/dist/src/internal/MIDIPortMethodCalls/actOnPort.js +17 -0
  43. package/dist/src/internal/MIDIPortMethodCalls/actOnPort.js.map +1 -0
  44. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.js +27 -0
  45. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.js.map +1 -0
  46. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.js +18 -0
  47. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.js.map +1 -0
  48. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.js +16 -0
  49. package/dist/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.js.map +1 -0
  50. package/dist/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.js +21 -0
  51. package/dist/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.js.map +1 -0
  52. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.js +34 -0
  53. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.js.map +1 -0
  54. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.js +18 -0
  55. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.js.map +1 -0
  56. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.js +16 -0
  57. package/dist/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.js.map +1 -0
  58. package/dist/src/internal/Parsing.js +119 -0
  59. package/dist/src/internal/Parsing.js.map +1 -0
  60. package/dist/src/internal/StreamMaker.js +105 -0
  61. package/dist/src/internal/StreamMaker.js.map +1 -0
  62. package/dist/src/internal/Util.js +59 -0
  63. package/dist/src/internal/Util.js.map +1 -0
  64. package/dist/src/internal/getPortByPortId/getPortByPortIdAndAccess.js +53 -0
  65. package/dist/src/internal/getPortByPortId/getPortByPortIdAndAccess.js.map +1 -0
  66. package/dist/src/internal/getPortByPortId/getPortByPortIdInContext.js +18 -0
  67. package/dist/src/internal/getPortByPortId/getPortByPortIdInContext.js.map +1 -0
  68. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.js +52 -0
  69. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.js.map +1 -0
  70. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.js +21 -0
  71. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.js.map +1 -0
  72. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.js +21 -0
  73. package/dist/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.js.map +1 -0
  74. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.js +66 -0
  75. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.js.map +1 -0
  76. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.js +61 -0
  77. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.js.map +1 -0
  78. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.js +68 -0
  79. package/dist/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.js.map +1 -0
  80. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.js +42 -0
  81. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.js.map +1 -0
  82. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.js +43 -0
  83. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.js.map +1 -0
  84. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.js +33 -0
  85. package/dist/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.js.map +1 -0
  86. package/dist/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.js +6 -0
  87. package/dist/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.js.map +1 -0
  88. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.js +46 -0
  89. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.js.map +1 -0
  90. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.js +25 -0
  91. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.js.map +1 -0
  92. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.js +31 -0
  93. package/dist/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.js.map +1 -0
  94. package/dist-types/index.d.ts +2 -0
  95. package/dist-types/index.d.ts.map +1 -0
  96. package/dist-types/src/EMIDIAccess.d.ts +18 -0
  97. package/dist-types/src/EMIDIAccess.d.ts.map +1 -0
  98. package/dist-types/src/EMIDIInput.d.ts +26 -0
  99. package/dist-types/src/EMIDIInput.d.ts.map +1 -0
  100. package/dist-types/src/EMIDIOutput.d.ts +26 -0
  101. package/dist-types/src/EMIDIOutput.d.ts.map +1 -0
  102. package/dist-types/src/EMIDIPort.d.ts +26 -0
  103. package/dist-types/src/EMIDIPort.d.ts.map +1 -0
  104. package/dist-types/src/MIDIErrors.d.ts +2 -0
  105. package/dist-types/src/MIDIErrors.d.ts.map +1 -0
  106. package/dist-types/src/MIDIEventStreams.d.ts +2 -0
  107. package/dist-types/src/MIDIEventStreams.d.ts.map +1 -0
  108. package/dist-types/src/Parsing.d.ts +2 -0
  109. package/dist-types/src/Parsing.d.ts.map +1 -0
  110. package/dist-types/src/StreamMaker.d.ts +2 -0
  111. package/dist-types/src/StreamMaker.d.ts.map +1 -0
  112. package/dist-types/src/Util.d.ts +2 -0
  113. package/dist-types/src/Util.d.ts.map +1 -0
  114. package/dist-types/src/index.d.ts +10 -0
  115. package/dist-types/src/index.d.ts.map +1 -0
  116. package/dist-types/src/internal/EMIDIAccess.d.ts +551 -0
  117. package/dist-types/src/internal/EMIDIAccess.d.ts.map +1 -0
  118. package/dist-types/src/internal/EMIDIInput.d.ts +50 -0
  119. package/dist-types/src/internal/EMIDIInput.d.ts.map +1 -0
  120. package/dist-types/src/internal/EMIDIOutput.d.ts +95 -0
  121. package/dist-types/src/internal/EMIDIOutput.d.ts.map +1 -0
  122. package/dist-types/src/internal/EMIDIPort.d.ts +90 -0
  123. package/dist-types/src/internal/EMIDIPort.d.ts.map +1 -0
  124. package/dist-types/src/internal/MIDIErrors.d.ts +270 -0
  125. package/dist-types/src/internal/MIDIErrors.d.ts.map +1 -0
  126. package/dist-types/src/internal/MIDIEventStreams.d.ts +74 -0
  127. package/dist-types/src/internal/MIDIEventStreams.d.ts.map +1 -0
  128. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.d.ts +16 -0
  129. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.d.ts.map +1 -0
  130. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.d.ts +15 -0
  131. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.d.ts.map +1 -0
  132. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.d.ts +13 -0
  133. package/dist-types/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.d.ts.map +1 -0
  134. package/dist-types/src/internal/MIDIPortMethodCalls/actOnPort.d.ts +11 -0
  135. package/dist-types/src/internal/MIDIPortMethodCalls/actOnPort.d.ts.map +1 -0
  136. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.d.ts +23 -0
  137. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.d.ts.map +1 -0
  138. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.d.ts +15 -0
  139. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.d.ts.map +1 -0
  140. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.d.ts +13 -0
  141. package/dist-types/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.d.ts.map +1 -0
  142. package/dist-types/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.d.ts +15 -0
  143. package/dist-types/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.d.ts.map +1 -0
  144. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.d.ts +21 -0
  145. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.d.ts.map +1 -0
  146. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.d.ts +15 -0
  147. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.d.ts.map +1 -0
  148. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.d.ts +13 -0
  149. package/dist-types/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.d.ts.map +1 -0
  150. package/dist-types/src/internal/Parsing.d.ts +110 -0
  151. package/dist-types/src/internal/Parsing.d.ts.map +1 -0
  152. package/dist-types/src/internal/StreamMaker.d.ts +204 -0
  153. package/dist-types/src/internal/StreamMaker.d.ts.map +1 -0
  154. package/dist-types/src/internal/Util.d.ts +33 -0
  155. package/dist-types/src/internal/Util.d.ts.map +1 -0
  156. package/dist-types/src/internal/getPortByPortId/getPortByPortIdAndAccess.d.ts +27 -0
  157. package/dist-types/src/internal/getPortByPortId/getPortByPortIdAndAccess.d.ts.map +1 -0
  158. package/dist-types/src/internal/getPortByPortId/getPortByPortIdInContext.d.ts +20 -0
  159. package/dist-types/src/internal/getPortByPortId/getPortByPortIdInContext.d.ts.map +1 -0
  160. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.d.ts +76 -0
  161. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.d.ts.map +1 -0
  162. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.d.ts +39 -0
  163. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.d.ts.map +1 -0
  164. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.d.ts +29 -0
  165. package/dist-types/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.d.ts.map +1 -0
  166. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.d.ts +62 -0
  167. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.d.ts.map +1 -0
  168. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.d.ts +16 -0
  169. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.d.ts.map +1 -0
  170. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.d.ts +65 -0
  171. package/dist-types/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.d.ts.map +1 -0
  172. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.d.ts +36 -0
  173. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.d.ts.map +1 -0
  174. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.d.ts +23 -0
  175. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.d.ts.map +1 -0
  176. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.d.ts +35 -0
  177. package/dist-types/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.d.ts.map +1 -0
  178. package/dist-types/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.d.ts +7 -0
  179. package/dist-types/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.d.ts.map +1 -0
  180. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.d.ts +71 -0
  181. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.d.ts.map +1 -0
  182. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.d.ts +7 -0
  183. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.d.ts.map +1 -0
  184. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.d.ts +28 -0
  185. package/dist-types/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.d.ts.map +1 -0
  186. package/index.ts +1 -0
  187. package/package.json +87 -0
  188. package/src/EMIDIAccess.ts +285 -0
  189. package/src/EMIDIInput.ts +273 -0
  190. package/src/EMIDIOutput.ts +272 -0
  191. package/src/EMIDIPort.ts +270 -0
  192. package/src/MIDIErrors.ts +13 -0
  193. package/src/MIDIEventStreams.ts +36 -0
  194. package/src/Parsing.ts +32 -0
  195. package/src/StreamMaker.ts +12 -0
  196. package/src/Util.ts +19 -0
  197. package/src/index.ts +9 -0
  198. package/src/internal/EMIDIAccess.ts +1280 -0
  199. package/src/internal/EMIDIInput.ts +114 -0
  200. package/src/internal/EMIDIOutput.ts +231 -0
  201. package/src/internal/EMIDIPort.ts +239 -0
  202. package/src/internal/MIDIErrors.ts +260 -0
  203. package/src/internal/MIDIEventStreams.ts +255 -0
  204. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPort.ts +48 -0
  205. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdAndAccess.ts +31 -0
  206. package/src/internal/MIDIPortMethodCalls/acquireReleasePortConnection/acquireReleasePortConnectionByPortIdInContext.ts +28 -0
  207. package/src/internal/MIDIPortMethodCalls/actOnPort.ts +66 -0
  208. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPort.ts +38 -0
  209. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdAndAccess.ts +38 -0
  210. package/src/internal/MIDIPortMethodCalls/closePortConnection/closePortConnectionByPortIdInContext.ts +28 -0
  211. package/src/internal/MIDIPortMethodCalls/makeMIDIPortMethodCallerFactory.ts +68 -0
  212. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPort.ts +48 -0
  213. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdAndAccess.ts +38 -0
  214. package/src/internal/MIDIPortMethodCalls/openPortConnection/openPortConnectionByPortIdInContext.ts +28 -0
  215. package/src/internal/Parsing.ts +304 -0
  216. package/src/internal/StreamMaker.ts +416 -0
  217. package/src/internal/Util.ts +152 -0
  218. package/src/internal/getPortByPortId/getPortByPortIdAndAccess.ts +117 -0
  219. package/src/internal/getPortByPortId/getPortByPortIdInContext.ts +26 -0
  220. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPort.ts +148 -0
  221. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdAndAccess.ts +135 -0
  222. package/src/internal/makePortStateChangesStream/makePortStateChangesStreamByPortIdInContext.ts +70 -0
  223. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPort.ts +128 -0
  224. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdAndAccess.ts +74 -0
  225. package/src/internal/mutablePropertyTools/doesMutablePortPropertyHaveSpecificValue/doesMutablePortPropertyHaveSpecificValueByPortIdInContext.ts +132 -0
  226. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPort.ts +64 -0
  227. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdAndAccess.ts +114 -0
  228. package/src/internal/mutablePropertyTools/getMutablePortProperty/getMutablePortPropertyByPortIdInContext.ts +47 -0
  229. package/src/internal/mutablePropertyTools/getValueInRawPortFieldUnsafe.ts +12 -0
  230. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPort.ts +182 -0
  231. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdAndAccess.ts +29 -0
  232. package/src/internal/mutablePropertyTools/matchMutablePortProperty/matchMutablePortPropertyByPortIdInContext.ts +87 -0
@@ -0,0 +1,416 @@
1
+ /** biome-ignore-all lint/style/useShorthandFunctionType: It's a nice way to
2
+ * preserve JSDoc comments attached to the function signature */
3
+
4
+ import * as Cause from 'effect/Cause'
5
+ import * as Effect from 'effect/Effect'
6
+ import * as EFunction from 'effect/Function'
7
+ import * as Stream from 'effect/Stream'
8
+
9
+ import * as EMIDIAccess from './EMIDIAccess.ts'
10
+ import * as EMIDIInput from './EMIDIInput.ts'
11
+ import * as EMIDIOutput from './EMIDIOutput.ts'
12
+ import * as Util from './Util.ts'
13
+
14
+ // TODO: make an experiment to see if listeners are automatically removed on disconnect
15
+
16
+ /**
17
+ * Set of possible ways to react when the MIDI-related event will have relevant
18
+ * field be null. Although there should be no sane scenario where it would be
19
+ * the case, it's still allowed by the spec, and for a better UX this lib lets
20
+ * the developer make a decision on how to handle such cases.
21
+ *
22
+ * - `fail` will add an error into a signature of a stream, allowing the user to
23
+ * handle it
24
+ * - `die` will throw a defect, which won't be reflected as a possible failure
25
+ * in types
26
+ * - `ignore` will just silently remove such events from the stream
27
+ * - `passthrough` - will pass such events with an unmodified content of the
28
+ * relevant field
29
+ *
30
+ * @internal
31
+ */
32
+ const validOnNullStrategies = new Set([
33
+ 'fail',
34
+ 'die',
35
+ 'ignore',
36
+ 'passthrough',
37
+ ] as const)
38
+
39
+ /**
40
+ * Helper utility to turn MIDI event listeners into effect's Streams.
41
+ *
42
+ * The signature is split into 2 calls, so that you are able at first call pass
43
+ * into generic an interface with `addEventListener` types of the raw web MIDI
44
+ * objects as keys and according event structures as values.
45
+ *
46
+ * **Second call arguments**
47
+ *
48
+ * - `isSelf` - Function determining if the maker was called as an overload with
49
+ * all parameters passed at once, or with them spread by 2 calls. `self` will
50
+ * be later assigned to a `cameFrom` property of the object in the success
51
+ * channel of the stream
52
+ *
53
+ * - `buildConfig` - Function that makes config out of an effectful version
54
+ * (e.g. {@linkcode EMIDIAccess.EMIDIAccessInstance|EMIDIAccess.Instance},
55
+ * {@linkcode EMIDIInput.EMIDIInput}, {@linkcode EMIDIOutput.EMIDIOutput}) of
56
+ * a MIDI object.
57
+ *
58
+ * - `remapValueToContainer` - Callback that maps the value of the event's
59
+ * selected field to an extension of the object inside stream's success
60
+ * channel. All fields of the returned object must always be present and
61
+ * should be consistently nullable, when the incoming event's field is null.
62
+ *
63
+ * @template TEventTypeToEventValueMap An interface with event types of raw Web
64
+ * MIDI objects as keys and according event structures as values. e.g.
65
+ * {@linkcode MIDIAccessEventMap}, {@linkcode MIDIPortEventMap},
66
+ * {@linkcode MIDIInputEventMap}
67
+ *
68
+ * @internal
69
+ */
70
+ export const createStreamMakerFrom =
71
+ <TEventTypeToEventValueMap extends object>() =>
72
+ /**
73
+ * @param isSelf Function determining if the maker was called as an overload
74
+ * with all parameters passed at once, or with them spread by 2 calls.
75
+ * `self` will be later assigned to a `cameFrom` property of the object in the
76
+ * success channel of the stream
77
+ *
78
+ * @param buildConfig Function that makes config out of an effectful version
79
+ * (e.g. {@linkcode EMIDIAccess.EMIDIAccessInstance|EMIDIAccess.Instance}, {@linkcode EMIDIInput.EMIDIInput},
80
+ * {@linkcode EMIDIOutput.EMIDIOutput}) of a MIDI object.
81
+ *
82
+ * @param remapValueToContainer Callback that maps the `fieldValue` of the
83
+ * event's selected field (`nullableFieldName`) to an extension of the object
84
+ * inside stream's success channel. The value is not null, except when
85
+ * `onNullStrategy` is `'passthrough'`. All fields of the returned object must
86
+ * always be present and should be consistently nullable, if the incoming
87
+ * event's field is null.
88
+ */
89
+ <
90
+ TEventTarget extends Stream.EventListener<
91
+ TEventTypeToEventValueMap[TSelectedEventType]
92
+ >,
93
+ const TSelectedEventType extends Extract<
94
+ keyof TEventTypeToEventValueMap,
95
+ string
96
+ >,
97
+ const TNullableFieldName extends Extract<
98
+ keyof TEventTypeToEventValueMap[TSelectedEventType],
99
+ string
100
+ >,
101
+ TCameFrom,
102
+ const TTag extends string,
103
+ TContainerWithNullableFields extends object,
104
+ >(
105
+ isSelf: (self: unknown) => self is TCameFrom,
106
+ buildConfig: (
107
+ self: TCameFrom,
108
+ ) => StreamConfig<
109
+ TTag,
110
+ TEventTarget,
111
+ TSelectedEventType,
112
+ TNullableFieldName
113
+ >,
114
+ remapValueToContainer: (
115
+ fieldValue: TEventTypeToEventValueMap[TSelectedEventType][TNullableFieldName],
116
+ ) => TContainerWithNullableFields,
117
+ ): DualStreamMaker<TCameFrom, TTag, TContainerWithNullableFields> =>
118
+ EFunction.dual<
119
+ MakeStreamTargetLast<TCameFrom, TTag, TContainerWithNullableFields>,
120
+ MakeStreamTargetFirst<TCameFrom, TTag, TContainerWithNullableFields>
121
+ >(
122
+ Util.polymorphicCheckInDual(isSelf),
123
+ (cameFromPolymorphic, options) =>
124
+ Effect.gen(function* () {
125
+ const onNullStrategy = ((
126
+ options as { onExtremelyRareNullableField?: OnNullStrategy }
127
+ )?.onExtremelyRareNullableField ?? 'die') as Exclude<
128
+ OnNullStrategy,
129
+ undefined
130
+ >
131
+
132
+ if (!validOnNullStrategies.has(onNullStrategy))
133
+ throw new Error(
134
+ `Invalid strategy to handle nullish values: ${onNullStrategy}`,
135
+ )
136
+
137
+ const cameFrom = yield* Util.fromPolymorphic(
138
+ cameFromPolymorphic,
139
+ isSelf,
140
+ )
141
+
142
+ const {
143
+ tag,
144
+ eventListener: { target, type },
145
+ spanAttributes,
146
+ nullableFieldName: field,
147
+ } = buildConfig(cameFrom)
148
+
149
+ const missingFieldMessage = `Property ${field} of ${tag} is null`
150
+ const NullCausedErrorEffect = new Cause.NoSuchElementException(
151
+ missingFieldMessage,
152
+ )
153
+
154
+ return Stream.fromEventListener(target, type, options).pipe(
155
+ Stream.filter(
156
+ event => !!event[field] || onNullStrategy !== 'ignore',
157
+ ),
158
+ Stream.mapEffect(event =>
159
+ event[field] || onNullStrategy === 'passthrough'
160
+ ? Effect.succeed({
161
+ _tag: tag,
162
+ ...remapValueToContainer(event[field]),
163
+ cameFrom,
164
+ capturedAt: new Date(),
165
+ })
166
+ : onNullStrategy === 'fail'
167
+ ? NullCausedErrorEffect
168
+ : Effect.dieMessage(missingFieldMessage),
169
+ ),
170
+ Stream.withSpan('MIDI Web API event stream', {
171
+ kind: 'producer',
172
+ attributes: { eventType: type, ...spanAttributes },
173
+ }),
174
+ )
175
+ }).pipe(Stream.unwrap) as any,
176
+ )
177
+
178
+ interface StreamConfig<
179
+ TTag,
180
+ TEventTarget,
181
+ TSelectedEventType,
182
+ TNullableFieldName,
183
+ > {
184
+ /**
185
+ * Tag that will be assigned to the object inside stream's success channel
186
+ */
187
+ readonly tag: TTag
188
+
189
+ /**
190
+ * Config specifying where to attach the event listener
191
+ */
192
+ readonly eventListener: {
193
+ /**
194
+ * Native MIDI object (e.g. {@linkcode MIDIAccess},
195
+ * {@linkcode MIDIInput}, {@linkcode MIDIOutput}) that can have new
196
+ * listeners attached
197
+ */
198
+ readonly target: TEventTarget
199
+
200
+ /**
201
+ * The type of event supported by the native MIDI object,
202
+ * `addEventListener`'s first argument (e.g.
203
+ * {@linkcode MIDIAccess.addEventListener|MIDIAccess's},
204
+ * {@linkcode MIDIInput.addEventListener|MIDIInput's},
205
+ * {@linkcode MIDIOutput.addEventListener|MIDIOutput's}) which can have
206
+ * new listeners attached. Restricted by the keys of
207
+ * {@linkcode TEventTypeToEventValueMap} passed in the first call
208
+ */
209
+ readonly type: TSelectedEventType
210
+ }
211
+
212
+ /**
213
+ * Additional attributes that will be attached to Open Telemetry span of
214
+ * the stream
215
+ */
216
+ readonly spanAttributes: {
217
+ readonly spanTargetName: string
218
+ readonly [k: string]: unknown
219
+ }
220
+
221
+ /**
222
+ * The name of the field that will be extracted from the event (e.g.
223
+ * {@linkcode MIDIConnectionEvent.port|MIDIConnectionEvent's port},
224
+ * {@linkcode MIDIMessageEvent.data|MIDIMessageEvent's data})
225
+ */
226
+ readonly nullableFieldName: TNullableFieldName
227
+ }
228
+
229
+ export interface StreamMakerOptionsWellknown {
230
+ /**
231
+ * A boolean value indicating that events of this type will be dispatched to
232
+ * the registered `listener` before being dispatched to any `EventTarget`
233
+ * beneath it in the DOM tree.
234
+ * @default false
235
+ */
236
+ readonly capture?: boolean
237
+
238
+ /**
239
+ * A boolean value indicating that the `listener` should be invoked at most
240
+ * once after being added. If `true`, the `listener` would be automatically
241
+ * removed when invoked.
242
+ * @default false
243
+ */
244
+ readonly passive?: boolean
245
+
246
+ /**
247
+ * A boolean value that, if true, indicates that the function specified by
248
+ * listener will never call `preventDefault()`. If a passive listener calls
249
+ * `preventDefault()`, nothing will happen and a console warning may be
250
+ * generated.
251
+ * @default false
252
+ */
253
+ readonly once?: boolean
254
+
255
+ /**
256
+ * How many elements sent by event target to buffer while waiting for the
257
+ * moment they are consumed. Can be limited to a certain number
258
+ * @default "unbounded"
259
+ */
260
+ readonly bufferSize?: number | 'unbounded' | undefined
261
+ }
262
+
263
+ export interface StreamMakerOptionsObject<
264
+ TOnNullStrategy extends OnNullStrategy,
265
+ > extends StreamMakerOptionsWellknown {
266
+ /**
267
+ * A strategy to react when the MIDI-related event will have relevant field be
268
+ * null. Although there should be no sane scenario where it would be the case,
269
+ * it's still allowed by the spec, and for a better DevX this lib lets the dev
270
+ * make a decision on how to handle such cases.
271
+ *
272
+ * - `fail` will add an error into a signature of a stream, allowing the user
273
+ * to handle it
274
+ * - `die` will throw a defect, which won't be reflected as a possible failure
275
+ * in types. Selected by default. `undefined` is treated the same.
276
+ * - `ignore` will just silently remove such events from the stream
277
+ * - `passthrough` - will pass such events with an unmodified content of the
278
+ * relevant field
279
+ *
280
+ * @default 'die'
281
+ */
282
+ readonly onExtremelyRareNullableField?: TOnNullStrategy
283
+ }
284
+
285
+ /**
286
+ * Passing a value of a `boolean` type is equivalent to setting
287
+ * `options.capture` property
288
+ */
289
+ export type StreamMakerOptions<TOnNullStrategy extends OnNullStrategy> =
290
+ | boolean
291
+ | StreamMakerOptionsObject<TOnNullStrategy>
292
+ | undefined
293
+
294
+ export type OnNullStrategy =
295
+ | (typeof validOnNullStrategies extends Set<infer U> ? U : never)
296
+ | undefined
297
+
298
+ export type StreamValue<
299
+ TTag extends string,
300
+ TCameFrom,
301
+ TContainerWithNullableFields extends object,
302
+ TOnNullStrategy extends OnNullStrategy,
303
+ > = {
304
+ readonly _tag: TTag
305
+ /**
306
+ * An effectful MIDI entity that wraps the raw MIDI object, which triggered an
307
+ * event
308
+ */
309
+ readonly cameFrom: TCameFrom
310
+ readonly capturedAt: Date
311
+ } & (
312
+ | {
313
+ readonly [NullableField in keyof TContainerWithNullableFields]: Exclude<
314
+ TContainerWithNullableFields[NullableField],
315
+ null
316
+ >
317
+ }
318
+ | ([TOnNullStrategy] extends ['passthrough']
319
+ ? {
320
+ readonly [NullableField in keyof TContainerWithNullableFields]: null
321
+ }
322
+ : never)
323
+ )
324
+
325
+ export type StreamError<TOnNullStrategy extends OnNullStrategy, E> =
326
+ | E
327
+ | ([TOnNullStrategy] extends ['fail'] ? Cause.NoSuchElementException : never)
328
+
329
+ export interface BuiltStream<
330
+ TTag extends string,
331
+ TCameFrom,
332
+ TContainerWithNullableFields extends object,
333
+ TOnNullStrategy extends OnNullStrategy,
334
+ E = never,
335
+ R = never,
336
+ > extends Stream.Stream<
337
+ StreamValue<TTag, TCameFrom, TContainerWithNullableFields, TOnNullStrategy>,
338
+ StreamError<TOnNullStrategy, E>,
339
+ R
340
+ > {}
341
+
342
+ export interface DualStreamMaker<
343
+ TCameFrom,
344
+ TTag extends string,
345
+ TContainerWithNullableFields extends object,
346
+ > extends MakeStreamTargetFirst<TCameFrom, TTag, TContainerWithNullableFields>,
347
+ MakeStreamTargetLast<TCameFrom, TTag, TContainerWithNullableFields> {}
348
+
349
+ export interface MakeStreamTargetFirst<
350
+ TCameFrom,
351
+ TTag extends string,
352
+ TContainerWithNullableFields extends object,
353
+ > {
354
+ /**
355
+ * @param polymorphicEventTargetWrapper Raw MIDI object, which triggers
356
+ * events, wrapped in this lib's abstraction and potentially inside Effect.
357
+ * Will be assigned to the `cameFrom` property of the stream's success channel
358
+ * object
359
+ *
360
+ * @param options Passing a value of a `boolean` type is equivalent to setting
361
+ * `options.capture` property
362
+ */
363
+ <
364
+ E = never,
365
+ R = never,
366
+ const TOnNullStrategy extends OnNullStrategy = undefined,
367
+ >(
368
+ polymorphicEventTargetWrapper: Util.PolymorphicEffect<TCameFrom, E, R>,
369
+ options?: StreamMakerOptions<TOnNullStrategy>,
370
+ ): BuiltStream<
371
+ TTag,
372
+ TCameFrom,
373
+ TContainerWithNullableFields,
374
+ TOnNullStrategy,
375
+ E,
376
+ R
377
+ >
378
+ }
379
+
380
+ export interface MakeStreamTargetLast<
381
+ TCameFrom,
382
+ TTag extends string,
383
+ TContainerWithNullableFields extends object,
384
+ > {
385
+ /**
386
+ * @param options Passing a value of a `boolean` type is equivalent to setting
387
+ * `options.capture` property
388
+ *
389
+ * **Second call argument**
390
+ *
391
+ * - `polymorphicEventTargetWrapper` Raw MIDI object, which triggers events,
392
+ * wrapped in this lib's abstraction and potentially inside Effect. Will be
393
+ * assigned to the `cameFrom` property of the stream's success channel
394
+ * object
395
+ */
396
+ <const TOnNullStrategy extends OnNullStrategy = undefined>(
397
+ options?: StreamMakerOptions<TOnNullStrategy>,
398
+ ): {
399
+ /**
400
+ * @param polymorphicEventTargetWrapper Raw MIDI object, which triggers
401
+ * events, wrapped in this lib's abstraction and potentially inside Effect.
402
+ * Will be assigned to the `cameFrom` property of the stream's success
403
+ * channel object
404
+ */
405
+ <E = never, R = never>(
406
+ polymorphicEventTargetWrapper: Util.PolymorphicEffect<TCameFrom, E, R>,
407
+ ): BuiltStream<
408
+ TTag,
409
+ TCameFrom,
410
+ TContainerWithNullableFields,
411
+ TOnNullStrategy,
412
+ E,
413
+ R
414
+ >
415
+ }
416
+ }
@@ -0,0 +1,152 @@
1
+ import * as EArray from 'effect/Array'
2
+ import type * as Brand from 'effect/Brand'
3
+ import * as Effect from 'effect/Effect'
4
+ import * as EFunction from 'effect/Function'
5
+ import * as Record from 'effect/Record'
6
+ import * as Stream from 'effect/Stream'
7
+ import * as Struct from 'effect/Struct'
8
+
9
+ import type * as MIDIErrors from './MIDIErrors.ts'
10
+
11
+ export const midiPortStaticFields = [
12
+ 'id',
13
+ 'name',
14
+ 'manufacturer',
15
+ 'version',
16
+ 'type',
17
+ ] as const
18
+
19
+ export type MIDIPortStaticFields = (typeof midiPortStaticFields)[number]
20
+
21
+ export const getStaticMIDIPortInfo = (
22
+ port: Pick<MIDIPort, MIDIPortStaticFields>,
23
+ ) => Struct.pick(port, ...midiPortStaticFields)
24
+
25
+ /**
26
+ * Puts Self into success channel for easier chaining of operations on the same
27
+ * entity
28
+ */
29
+ export interface SentMessageEffectFrom<Self, E = never, R = never>
30
+ extends Effect.Effect<
31
+ Self,
32
+ | E
33
+ | MIDIErrors.CannotSendSysexMessageError
34
+ | MIDIErrors.MalformedMIDIMessageError
35
+ | MIDIErrors.CannotSendToDisconnectedPortError,
36
+ R
37
+ > {}
38
+
39
+ export type PolymorphicEffect<A, E, R> = A | Effect.Effect<A, E, R>
40
+
41
+ export type FallbackOnUnknownOrAny<TCandidate, Fallback> =
42
+ unknown extends TCandidate
43
+ ? TCandidate extends unknown
44
+ ? Fallback
45
+ : TCandidate
46
+ : TCandidate
47
+
48
+ export const polymorphicCheckInDual =
49
+ (is: (arg: unknown) => boolean) => (args: IArguments) =>
50
+ Effect.isEffect(args[0]) || is(args[0])
51
+
52
+ export function fromPolymorphic<A, E = never, R = never>(
53
+ polymorphicValue: PolymorphicEffect<A, E, R>,
54
+ is: (arg: unknown) => arg is NoInfer<A>,
55
+ ) {
56
+ const check = (value: A) =>
57
+ is(value)
58
+ ? Effect.succeed(value)
59
+ : Effect.dieMessage('Assertion failed on polymorphic value')
60
+
61
+ return Effect.isEffect(polymorphicValue)
62
+ ? Effect.flatMap(polymorphicValue, check)
63
+ : check(polymorphicValue)
64
+ }
65
+
66
+ /**
67
+ * @internal
68
+ */
69
+ const isEqual =
70
+ <TWideValue extends string, TPropertyName extends string>() =>
71
+ <const TExpectedValue extends TWideValue>(expected: TExpectedValue) =>
72
+ <E, R>(self: Effect.Effect<TWideValue, E, R>) =>
73
+ Effect.map(
74
+ self,
75
+ current =>
76
+ (current === expected) as IsEqualFlag<TPropertyName, TExpectedValue>,
77
+ )
78
+
79
+ export type IsEqualFlag<
80
+ TPropertyName extends string,
81
+ TExpectedValue extends string,
82
+ > = Brand.Branded<boolean, TPropertyName> &
83
+ Brand.Brand<`expectedValue: ${TExpectedValue}`>
84
+
85
+ export const isCertainDeviceState = isEqual<
86
+ MIDIPortDeviceState,
87
+ 'isCertainDeviceState'
88
+ >()
89
+
90
+ export const isCertainConnectionState = isEqual<
91
+ MIDIPortConnectionState,
92
+ 'isCertainConnectionState'
93
+ >()
94
+
95
+ export const isDeviceConnected = isCertainDeviceState('connected')
96
+ export const isDeviceDisconnected = isCertainDeviceState('disconnected')
97
+
98
+ export const isConnectionOpen = isCertainConnectionState('open')
99
+ export const isConnectionPending = isCertainConnectionState('pending')
100
+ export const isConnectionClosed = isCertainConnectionState('closed')
101
+
102
+ export const mapToGlidingStringLogOfLimitedEntriesCount =
103
+ <A>(
104
+ windowSize: number,
105
+ show: 'latestFirst' | 'oldestFirst',
106
+ objectify: (current: NoInfer<A>) => object,
107
+ ) =>
108
+ <E, R>(self: Stream.Stream<A, E, R>) => {
109
+ if (windowSize < 1) throw new Error('Window size should be greater than 0')
110
+
111
+ return Stream.mapAccum(
112
+ self,
113
+ { text: '', entrySizeLog: [] as number[] },
114
+ ({ entrySizeLog: oldLog, text: oldText }, current) => {
115
+ const currMapped =
116
+ EFunction.pipe(
117
+ objectify(current),
118
+ Record.toEntries,
119
+ EArray.map(EArray.join(': ')),
120
+ EArray.join(', '),
121
+ ) + '\n'
122
+
123
+ const potentiallyShiftedLog =
124
+ oldLog.length >= windowSize
125
+ ? oldLog.slice(...(show === 'latestFirst' ? [0, -1] : [1]))
126
+ : oldLog
127
+
128
+ const potentiallyShiftedText =
129
+ oldLog.length >= windowSize
130
+ ? oldText.slice(
131
+ ...(show === 'latestFirst'
132
+ ? // biome-ignore lint/style/noNonNullAssertion: oldLog guaranteed to have at least one element by oldLog.length >= windowSize
133
+ [0, -oldLog.at(-1)!]
134
+ : // biome-ignore lint/style/noNonNullAssertion: oldLog guaranteed to have at least one element by oldLog.length >= windowSize
135
+ [oldLog.at(0)!]),
136
+ )
137
+ : oldText
138
+
139
+ const text =
140
+ show === 'latestFirst'
141
+ ? currMapped + potentiallyShiftedText
142
+ : potentiallyShiftedText + currMapped
143
+
144
+ const entrySizeLog =
145
+ show === 'latestFirst'
146
+ ? [currMapped.length, ...potentiallyShiftedLog]
147
+ : [...potentiallyShiftedLog, currMapped.length]
148
+
149
+ return [{ text, entrySizeLog }, text]
150
+ },
151
+ )
152
+ }
@@ -0,0 +1,117 @@
1
+ /** biome-ignore-all lint/style/useShorthandFunctionType: It's a nice way to
2
+ * preserve JSDoc comments attached to the function signature */
3
+
4
+ import * as Effect from 'effect/Effect'
5
+ import * as EFunction from 'effect/Function'
6
+
7
+ import * as EMIDIAccess from '../EMIDIAccess.ts'
8
+ import * as EMIDIInput from '../EMIDIInput.ts'
9
+ import * as EMIDIOutput from '../EMIDIOutput.ts'
10
+ import type * as EMIDIPort from '../EMIDIPort.ts'
11
+ import * as MIDIErrors from '../MIDIErrors.ts'
12
+
13
+ /**
14
+ *
15
+ * @internal
16
+ */
17
+ const getPortByIdAndRemap = <
18
+ EInput,
19
+ EOutput,
20
+ RInput,
21
+ ROutput,
22
+ AInputType extends 'input' = never,
23
+ AOutputType extends 'output' = never,
24
+ >(handlers: {
25
+ onInputFound: (
26
+ rawInput: MIDIInput,
27
+ ) => Effect.Effect<EMIDIPort.EMIDIPort<AInputType>, EInput, RInput>
28
+ onOutputFound: (
29
+ rawOutput: MIDIOutput,
30
+ ) => Effect.Effect<EMIDIPort.EMIDIPort<AOutputType>, EOutput, ROutput>
31
+ }): GetPortById<
32
+ AInputType | AOutputType,
33
+ AInputType | AOutputType,
34
+ never,
35
+ never,
36
+ MIDIErrors.PortNotFoundError | EInput | EOutput,
37
+ RInput | ROutput
38
+ > =>
39
+ EFunction.dual(2, (polymorphicAccess, portId) =>
40
+ Effect.flatMap(EMIDIAccess.simplify(polymorphicAccess), access => {
41
+ const rawAccess = EMIDIAccess.assumeImpl(access)._access
42
+
43
+ let rawPort: MIDIOutput | MIDIInput | undefined =
44
+ rawAccess.inputs.get(portId)
45
+
46
+ if (rawPort) return handlers.onInputFound(rawPort)
47
+
48
+ rawPort = rawAccess.outputs.get(portId)
49
+
50
+ if (rawPort) return handlers.onOutputFound(rawPort)
51
+
52
+ return new MIDIErrors.PortNotFoundError({
53
+ portId,
54
+ }) as EMIDIAccess.AcquiredThing<
55
+ EMIDIPort.EMIDIPort<AInputType | AOutputType>,
56
+ never,
57
+ never,
58
+ never,
59
+ never,
60
+ MIDIErrors.PortNotFoundError | EInput | EOutput,
61
+ RInput | ROutput
62
+ >
63
+ }),
64
+ )
65
+
66
+ /**
67
+ *
68
+ * If you want to ensure the type of returned port match the type of ID, use
69
+ * type-specific getters {@linkcode getInputByPortIdAndAccess} and
70
+ * {@linkcode getOutputByPortIdAndAccess}, because in runtime, these branded
71
+ * port IDs passed as function arguments, are just strings and cannot ensure
72
+ * soundness
73
+ */
74
+ export const getPortByPortIdAndAccess = getPortByIdAndRemap({
75
+ onInputFound: EFunction.flow(EMIDIInput.make, Effect.succeed),
76
+ onOutputFound: EFunction.flow(EMIDIOutput.make, Effect.succeed),
77
+ })
78
+
79
+ /**
80
+ *
81
+ *
82
+ */
83
+ export const getInputByPortIdAndAccess = getPortByIdAndRemap({
84
+ onInputFound: EFunction.flow(EMIDIInput.make, Effect.succeed),
85
+ onOutputFound: rawOutput =>
86
+ Effect.dieMessage(
87
+ `Assertion failed: getInputById expected id=${rawOutput.id} to point at input, but it points at output instead`,
88
+ ),
89
+ })
90
+
91
+ /**
92
+ *
93
+ *
94
+ */
95
+ export const getOutputByPortIdAndAccess = getPortByIdAndRemap({
96
+ onInputFound: rawInput =>
97
+ Effect.dieMessage(
98
+ `Assertion failed: getOutputById expected id=${rawInput.id} to point at output, but it points at input instead`,
99
+ ),
100
+ onOutputFound: EFunction.flow(EMIDIOutput.make, Effect.succeed),
101
+ })
102
+
103
+ export interface GetPortById<
104
+ TReturnedPortType extends TTypeOfPortId,
105
+ TTypeOfPortId extends MIDIPortType,
106
+ TAccessGettingFallbackError,
107
+ TAccessGettingFallbackRequirement,
108
+ TAdditionalError,
109
+ TAdditionalRequirement,
110
+ > extends EMIDIAccess.GetThingByPortId<
111
+ EMIDIPort.EMIDIPort<TReturnedPortType>,
112
+ TTypeOfPortId,
113
+ TAccessGettingFallbackError,
114
+ TAccessGettingFallbackRequirement,
115
+ TAdditionalError | MIDIErrors.PortNotFoundError,
116
+ TAdditionalRequirement
117
+ > {}
@@ -0,0 +1,26 @@
1
+ import * as EMIDIAccess from '../EMIDIAccess.ts'
2
+ import type * as EMIDIInput from '../EMIDIInput.ts'
3
+ import type * as EMIDIOutput from '../EMIDIOutput.ts'
4
+ import type * as EMIDIPort from '../EMIDIPort.ts'
5
+ import * as Get from './getPortByPortIdAndAccess.ts'
6
+
7
+ /**
8
+ *
9
+ *
10
+ */
11
+ export const getPortByPortIdInContext = (id: EMIDIPort.BothId) =>
12
+ Get.getPortByPortIdAndAccess(EMIDIAccess.EMIDIAccess, id)
13
+
14
+ /**
15
+ *
16
+ *
17
+ */
18
+ export const getInputByPortIdInContext = (id: EMIDIInput.Id) =>
19
+ Get.getInputByPortIdAndAccess(EMIDIAccess.EMIDIAccess, id)
20
+
21
+ /**
22
+ *
23
+ *
24
+ */
25
+ export const getOutputByPortIdInContext = (id: EMIDIOutput.Id) =>
26
+ Get.getOutputByPortIdAndAccess(EMIDIAccess.EMIDIAccess, id)