rnxsim 0.0.0 → 0.1.313

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 (228) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -0
  3. package/detox/colors.ts +54 -0
  4. package/detox/config-loader.ts +135 -0
  5. package/detox/element-types.ts +39 -0
  6. package/detox/expectations.ts +537 -0
  7. package/detox/gestures.ts +480 -0
  8. package/detox/index.ts +2118 -0
  9. package/detox/jest-preset.cjs +51 -0
  10. package/detox/jest-setup-after-env.cjs +18 -0
  11. package/detox/matchers.ts +30 -0
  12. package/detox/motion-change.cjs +109 -0
  13. package/detox/motion-change.d.cts +35 -0
  14. package/detox/navigation.ts +43 -0
  15. package/detox/screenshots/animated-color-test-rest-norngh.png +0 -0
  16. package/detox/screenshots/color-test-after-drag-norngh.png +0 -0
  17. package/detox/screenshots/color-test-rest-norngh.png +0 -0
  18. package/detox/screenshots/theme-blue-toggle.png +0 -0
  19. package/detox/screenshots/theme-blue.png +0 -0
  20. package/detox/screenshots/theme-red-toggle.png +0 -0
  21. package/detox/screenshots/theme-red.png +0 -0
  22. package/dist-cli/bin.js +15 -0
  23. package/dist-cli/chunks/agent-XZ2KTPCU.js +48 -0
  24. package/dist-cli/chunks/agent-wrapper-JJYYW2WH.js +17 -0
  25. package/dist-cli/chunks/app-fonts-IXRNQG6B.js +4 -0
  26. package/dist-cli/chunks/assert-54T5SK5F.js +49 -0
  27. package/dist-cli/chunks/auth-FI5UDI45.js +12 -0
  28. package/dist-cli/chunks/beta-JV6UKADW.js +4 -0
  29. package/dist-cli/chunks/camera-VL73YIKP.js +22 -0
  30. package/dist-cli/chunks/chunk-2D2UPBBR.js +4 -0
  31. package/dist-cli/chunks/chunk-2YR5BGA5.js +5 -0
  32. package/dist-cli/chunks/chunk-3NV2NCNX.js +4 -0
  33. package/dist-cli/chunks/chunk-46EUUFJ5.js +4 -0
  34. package/dist-cli/chunks/chunk-4NPPOV2N.js +5 -0
  35. package/dist-cli/chunks/chunk-5DHC6KHQ.js +7 -0
  36. package/dist-cli/chunks/chunk-5TEF3ET3.js +74 -0
  37. package/dist-cli/chunks/chunk-5TPRP5QT.js +4 -0
  38. package/dist-cli/chunks/chunk-5YJCOWCH.js +4 -0
  39. package/dist-cli/chunks/chunk-7GN3LVWB.js +4 -0
  40. package/dist-cli/chunks/chunk-BBULZ7CG.js +568 -0
  41. package/dist-cli/chunks/chunk-BTWORNNG.js +71 -0
  42. package/dist-cli/chunks/chunk-D4FFVGI5.js +5 -0
  43. package/dist-cli/chunks/chunk-DCEMHR2Y.js +4 -0
  44. package/dist-cli/chunks/chunk-DZS6WPUI.js +4 -0
  45. package/dist-cli/chunks/chunk-F5ZRSS3C.js +3 -0
  46. package/dist-cli/chunks/chunk-FSUYIVJ6.js +9 -0
  47. package/dist-cli/chunks/chunk-G2WW6L2C.js +23 -0
  48. package/dist-cli/chunks/chunk-GASE6UBA.js +4 -0
  49. package/dist-cli/chunks/chunk-GGRX24GF.js +142 -0
  50. package/dist-cli/chunks/chunk-HI5TFJWN.js +5 -0
  51. package/dist-cli/chunks/chunk-IJ5CAZZC.js +5 -0
  52. package/dist-cli/chunks/chunk-IJO63TDP.js +4 -0
  53. package/dist-cli/chunks/chunk-KTHV3RUS.js +26 -0
  54. package/dist-cli/chunks/chunk-LF2ZVT7O.js +6 -0
  55. package/dist-cli/chunks/chunk-MJRLLB4R.js +38 -0
  56. package/dist-cli/chunks/chunk-NFK7T35W.js +4 -0
  57. package/dist-cli/chunks/chunk-NMF2ZMZQ.js +15 -0
  58. package/dist-cli/chunks/chunk-OHAZNXLK.js +4 -0
  59. package/dist-cli/chunks/chunk-OVFJFXUD.js +101 -0
  60. package/dist-cli/chunks/chunk-OZSSI4WN.js +28 -0
  61. package/dist-cli/chunks/chunk-QKDWYITG.js +25 -0
  62. package/dist-cli/chunks/chunk-RSZWCKNT.js +30 -0
  63. package/dist-cli/chunks/chunk-RTN5C5RL.js +4 -0
  64. package/dist-cli/chunks/chunk-TIVZIMMW.js +4 -0
  65. package/dist-cli/chunks/chunk-TZFFR3SD.js +7 -0
  66. package/dist-cli/chunks/chunk-UC6U3MML.js +5 -0
  67. package/dist-cli/chunks/chunk-VFCMSYZK.js +6 -0
  68. package/dist-cli/chunks/chunk-VNQEB4L7.js +5 -0
  69. package/dist-cli/chunks/chunk-VZXWHRUZ.js +983 -0
  70. package/dist-cli/chunks/chunk-W6K4EFPH.js +107 -0
  71. package/dist-cli/chunks/chunk-WEXDAC74.js +4 -0
  72. package/dist-cli/chunks/chunk-WF3T4SVI.js +14 -0
  73. package/dist-cli/chunks/chunk-WINYQ44O.js +4 -0
  74. package/dist-cli/chunks/chunk-WMIIKMGK.js +10 -0
  75. package/dist-cli/chunks/chunk-WUSWBCWA.js +507 -0
  76. package/dist-cli/chunks/chunk-WWZIXIRD.js +4 -0
  77. package/dist-cli/chunks/chunk-XEVZYVIW.js +766 -0
  78. package/dist-cli/chunks/chunk-YDGQTMQL.js +4 -0
  79. package/dist-cli/chunks/chunk-YIFT42WN.js +4 -0
  80. package/dist-cli/chunks/chunk-ZMJD5GEC.js +125 -0
  81. package/dist-cli/chunks/cleanup-P27PA6JI.js +25 -0
  82. package/dist-cli/chunks/cli-version-WWLPBDQ7.js +4 -0
  83. package/dist-cli/chunks/compat-ZD65FED3.js +20 -0
  84. package/dist-cli/chunks/config-XMJRNM2A.js +13 -0
  85. package/dist-cli/chunks/control-KMIQT3QP.js +4 -0
  86. package/dist-cli/chunks/daemon-G2ME7NLB.js +4 -0
  87. package/dist-cli/chunks/debug-PT4HOP7N.js +200 -0
  88. package/dist-cli/chunks/desktop-S3FG72AK.js +31 -0
  89. package/dist-cli/chunks/detox-B3D4IFCN.js +52 -0
  90. package/dist-cli/chunks/device-XBNDSB2R.js +18 -0
  91. package/dist-cli/chunks/diagnose-HMQXJE5N.js +43 -0
  92. package/dist-cli/chunks/disk-cleanup-BLCZ5BSZ.js +4 -0
  93. package/dist-cli/chunks/drivers-LDECZGP2.js +4 -0
  94. package/dist-cli/chunks/film-BJGTBYZB.js +74 -0
  95. package/dist-cli/chunks/flow-UEQNVTU7.js +4 -0
  96. package/dist-cli/chunks/help-T5FYSVGB.js +4 -0
  97. package/dist-cli/chunks/hidden-runtime-alias-ANOYADHM.js +4 -0
  98. package/dist-cli/chunks/home-paths-GT3LFNOR.js +4 -0
  99. package/dist-cli/chunks/inspect-ZA6XF5LD.js +4 -0
  100. package/dist-cli/chunks/install-desktop-TIMUDHPL.js +4 -0
  101. package/dist-cli/chunks/login-FJ737MWG.js +28 -0
  102. package/dist-cli/chunks/logout-ZCNMMHMY.js +4 -0
  103. package/dist-cli/chunks/maestro-SZTNKLDF.js +104 -0
  104. package/dist-cli/chunks/maestro-generate-DCFAIZ4H.js +36 -0
  105. package/dist-cli/chunks/mode-GRMQCRXR.js +26 -0
  106. package/dist-cli/chunks/optional-demo-registry-W36EWFFB.js +4 -0
  107. package/dist-cli/chunks/perf-QYBAAUZG.js +48 -0
  108. package/dist-cli/chunks/permissions-3QCQ6VF4.js +13 -0
  109. package/dist-cli/chunks/record-QPPC2S4E.js +72 -0
  110. package/dist-cli/chunks/report-issue-7NMFP4HK.js +29 -0
  111. package/dist-cli/chunks/runtime-XOAXMSTU.js +4 -0
  112. package/dist-cli/chunks/screenshot-command-67AECJFB.js +159 -0
  113. package/dist-cli/chunks/screenshot-layers-ASWBYPJL.js +20 -0
  114. package/dist-cli/chunks/screenshots-capture-PXA3HFQK.js +42 -0
  115. package/dist-cli/chunks/serve-BI2NBAXG.js +44 -0
  116. package/dist-cli/chunks/setup-7DWPMRSB.js +32 -0
  117. package/dist-cli/chunks/skills-S3Y22TUA.js +50 -0
  118. package/dist-cli/chunks/storage-XUIMJWAJ.js +37 -0
  119. package/dist-cli/chunks/store-JTHEJLAZ.js +4 -0
  120. package/dist-cli/chunks/telemetry-ZYJGD2DB.js +4 -0
  121. package/dist-cli/chunks/timeline-TMPLQPSP.js +24 -0
  122. package/dist-cli/chunks/upgrade-7HDSIM7K.js +7 -0
  123. package/dist-cli/chunks/upload-GMSZPWM6.js +4 -0
  124. package/dist-cli/chunks/version-HOCHZ37L.js +6 -0
  125. package/dist-cli/chunks/web-DG3WBYD3.js +4 -0
  126. package/dist-cli/chunks/what-happened-XFVUTZR7.js +25 -0
  127. package/dist-lib/agent-daemon-client.cjs +468 -0
  128. package/dist-lib/agent-events.cjs +48 -0
  129. package/dist-lib/agent-identity.cjs +53 -0
  130. package/dist-lib/agent-sessions.cjs +725 -0
  131. package/dist-lib/attached-projects.cjs +526 -0
  132. package/dist-lib/auth/shared-session.cjs +195 -0
  133. package/dist-lib/backend-origin.cjs +70 -0
  134. package/dist-lib/beta.cjs +41 -0
  135. package/dist-lib/beta.mjs +13 -0
  136. package/dist-lib/bridge-constants.cjs +161 -0
  137. package/dist-lib/cli-constants.cjs +32 -0
  138. package/dist-lib/config.cjs +96 -0
  139. package/dist-lib/detox/index.cjs +2863 -0
  140. package/dist-lib/detox/jest-preset.cjs +51 -0
  141. package/dist-lib/dev-bundle-resolution.cjs +223 -0
  142. package/dist-lib/home-paths.cjs +421 -0
  143. package/dist-lib/host/bridge-host.cjs +5600 -0
  144. package/dist-lib/host/fetch-proxy-handler.cjs +373 -0
  145. package/dist-lib/host/fetch-proxy-overrides.cjs +63 -0
  146. package/dist-lib/host/fetch-proxy-overrides.mjs +37 -0
  147. package/dist-lib/host/websocket-proxy.cjs +214 -0
  148. package/dist-lib/index.cjs +513 -0
  149. package/dist-lib/jump-to-source-babel.cjs +93 -0
  150. package/dist-lib/menu.cjs +620 -0
  151. package/dist-lib/menu.mjs +581 -0
  152. package/dist-lib/metro.cjs +297 -0
  153. package/dist-lib/profiles.cjs +246 -0
  154. package/dist-lib/public-brand.cjs +39 -0
  155. package/dist-lib/render-mode.cjs +54 -0
  156. package/dist-lib/scripts/dev-server-scanner.cjs +1034 -0
  157. package/dist-lib/sdk.cjs +2333 -0
  158. package/dist-lib/sdk.mjs +2240 -0
  159. package/dist-lib/skills.cjs +23922 -0
  160. package/dist-lib/vite.cjs +358 -0
  161. package/package.json +189 -18
  162. package/scripts/dev-server-scanner.ts +941 -0
  163. package/scripts/optional-demo-registry.ts +113 -0
  164. package/scripts/postinstall.cjs +3 -0
  165. package/scripts/preuninstall.cjs +118 -0
  166. package/skills/contrast/SKILL.md +171 -0
  167. package/skills/rnx-debug/SKILL.md +425 -0
  168. package/skills/rnx-perf/SKILL.md +295 -0
  169. package/skills/rnx-setup/SKILL.md +160 -0
  170. package/skills/rnx-test/SKILL.md +292 -0
  171. package/skills/rnx-visual/SKILL.md +122 -0
  172. package/src/agent-daemon-client.ts +410 -0
  173. package/src/agent-events.ts +71 -0
  174. package/src/agent-identity.ts +23 -0
  175. package/src/agent-prompt.ts +71 -0
  176. package/src/agent-sessions.ts +573 -0
  177. package/src/attached-projects.ts +539 -0
  178. package/src/auth/shared-session.ts +204 -0
  179. package/src/backend-origin.ts +49 -0
  180. package/src/beta.ts +19 -0
  181. package/src/bridge-constants.ts +171 -0
  182. package/src/browser-cache.ts +16 -0
  183. package/src/cli-constants.ts +1 -0
  184. package/src/cli-version.ts +32 -0
  185. package/src/codex-client.ts +215 -0
  186. package/src/config.ts +134 -0
  187. package/src/dev-bundle-resolution.ts +236 -0
  188. package/src/disk-cleanup.ts +466 -0
  189. package/src/home-paths.ts +552 -0
  190. package/src/host/agent-host.ts +666 -0
  191. package/src/host/bridge-host.ts +2626 -0
  192. package/src/host/fetch-proxy-handler.ts +397 -0
  193. package/src/host/fetch-proxy-overrides.ts +51 -0
  194. package/src/host/open-url.ts +89 -0
  195. package/src/host/websocket-proxy.ts +210 -0
  196. package/src/index.ts +12 -705
  197. package/src/jump-to-source-babel.ts +135 -0
  198. package/src/menu.ts +734 -0
  199. package/src/metro-plugin.ts +139 -0
  200. package/src/native-dev-bundle-url.ts +96 -0
  201. package/src/native-seam-manifest.ts +341 -0
  202. package/src/plist.ts +27 -0
  203. package/src/poll-until.ts +92 -0
  204. package/src/profiles.ts +179 -0
  205. package/src/public-brand.ts +9 -0
  206. package/src/render-mode.ts +27 -0
  207. package/src/runtime-assets.ts +228 -0
  208. package/src/runtime-delivery.ts +54 -0
  209. package/src/screenshots/compose.ts +422 -0
  210. package/src/screenshots/frame-compose.ts +454 -0
  211. package/src/screenshots/orchestrate.ts +256 -0
  212. package/src/screenshots/org-deck.ts +91 -0
  213. package/src/screenshots/registry.ts +58 -0
  214. package/src/screenshots/schema.ts +364 -0
  215. package/src/sdk.ts +7 -0
  216. package/src/settings-bundle.ts +418 -0
  217. package/src/skills/builtin/a11y-review.ts +132 -0
  218. package/src/skills/builtin/compat-check.ts +71 -0
  219. package/src/skills/builtin/maestro-test.ts +121 -0
  220. package/src/skills/builtin/perf-profile.ts +90 -0
  221. package/src/skills/builtin/screenshot-all.ts +52 -0
  222. package/src/skills/builtin/visual-diff.ts +100 -0
  223. package/src/skills/registry.ts +107 -0
  224. package/src/skills/types.ts +41 -0
  225. package/src/team-machine-prompt.ts +73 -0
  226. package/src/vite-plugin-one.ts +190 -0
  227. package/src/vite-plugin.ts +1750 -0
  228. package/src/worklets-babel.ts +134 -0
@@ -0,0 +1,210 @@
1
+ import { WebSocket, WebSocketServer } from 'ws'
2
+ import type { IncomingMessage } from 'http'
3
+ import type { Duplex } from 'stream'
4
+
5
+ export const WEBSOCKET_PROXY_PATH = '/__websocket-proxy'
6
+
7
+ const STRIP_UPSTREAM_HEADERS = new Set([
8
+ 'host',
9
+ 'connection',
10
+ 'upgrade',
11
+ 'transfer-encoding',
12
+ 'content-length',
13
+ 'sec-websocket-accept',
14
+ 'sec-websocket-extensions',
15
+ 'sec-websocket-key',
16
+ 'sec-websocket-protocol',
17
+ 'sec-websocket-version',
18
+ ])
19
+
20
+ function rejectUpgrade(socket: Duplex, status: number, message: string) {
21
+ try {
22
+ socket.write(
23
+ `HTTP/1.1 ${status} ${message}\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: ${message.length}\r\n\r\n${message}`,
24
+ )
25
+ } catch {}
26
+ socket.destroy()
27
+ }
28
+
29
+ function isSameOriginUpgrade(req: IncomingMessage): boolean {
30
+ const origin = req.headers.origin
31
+ const host = req.headers.host
32
+ if (!origin || !host) return false
33
+ try {
34
+ return new URL(origin).host === host
35
+ } catch {
36
+ return false
37
+ }
38
+ }
39
+
40
+ function decodeProxyHeaders(encoded: string | null): Record<string, string> {
41
+ if (!encoded) return {}
42
+ const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/')
43
+ const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4)
44
+ const parsed = JSON.parse(Buffer.from(padded, 'base64').toString('utf8'))
45
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {}
46
+ const headers: Record<string, string> = {}
47
+ for (const [key, value] of Object.entries(parsed)) {
48
+ if (value == null) continue
49
+ if (STRIP_UPSTREAM_HEADERS.has(key.toLowerCase())) continue
50
+ headers[key] = Array.isArray(value) ? value.join(', ') : String(value)
51
+ }
52
+ return headers
53
+ }
54
+
55
+ function getDefaultWebSocketOrigin(targetUrl: URL): string {
56
+ const origin = new URL(targetUrl.href)
57
+ origin.protocol = targetUrl.protocol === 'wss:' ? 'https:' : 'http:'
58
+ return origin.origin
59
+ }
60
+
61
+ function getRequestedProtocols(req: IncomingMessage): string[] {
62
+ const header = req.headers['sec-websocket-protocol']
63
+ const value = Array.isArray(header) ? header.join(',') : header || ''
64
+ return value
65
+ .split(',')
66
+ .map((part) => part.trim())
67
+ .filter(Boolean)
68
+ }
69
+
70
+ function safeClose(ws: WebSocket, code: number, reason: string) {
71
+ if (ws.readyState === WebSocket.CLOSED || ws.readyState === WebSocket.CLOSING) {
72
+ return
73
+ }
74
+ try {
75
+ ws.close(code, reason)
76
+ } catch {
77
+ ws.terminate()
78
+ }
79
+ }
80
+
81
+ function connectProxyPair(clientWs: WebSocket, upstream: WebSocket) {
82
+ let closing = false
83
+
84
+ const closeBoth = (
85
+ source: WebSocket,
86
+ target: WebSocket,
87
+ code: number,
88
+ reason: Buffer,
89
+ ) => {
90
+ if (closing) return
91
+ closing = true
92
+ safeClose(target, code, reason.toString())
93
+ if (source.readyState === WebSocket.OPEN) {
94
+ safeClose(source, code, reason.toString())
95
+ }
96
+ }
97
+
98
+ clientWs.on('message', (data, isBinary) => {
99
+ if (upstream.readyState === WebSocket.OPEN) {
100
+ upstream.send(data, { binary: isBinary })
101
+ }
102
+ })
103
+ upstream.on('message', (data, isBinary) => {
104
+ if (clientWs.readyState === WebSocket.OPEN) {
105
+ clientWs.send(data, { binary: isBinary })
106
+ }
107
+ })
108
+
109
+ clientWs.on('close', (code, reason) => closeBoth(clientWs, upstream, code, reason))
110
+ upstream.on('close', (code, reason) => closeBoth(upstream, clientWs, code, reason))
111
+ clientWs.on('error', () => safeClose(upstream, 1011, 'proxy client error'))
112
+ upstream.on('error', () => safeClose(clientWs, 1011, 'upstream websocket error'))
113
+ }
114
+
115
+ function createUpstreamWebSocket(
116
+ targetUrl: URL,
117
+ protocols: string[],
118
+ headers: Record<string, string>,
119
+ forwardOrigin: boolean,
120
+ ): WebSocket {
121
+ const upstreamHeaders = { ...headers }
122
+ const originKeys = Object.keys(upstreamHeaders).filter(
123
+ (key) => key.toLowerCase() === 'origin',
124
+ )
125
+ if (forwardOrigin && originKeys.length === 0) {
126
+ upstreamHeaders.origin = getDefaultWebSocketOrigin(targetUrl)
127
+ } else if (!forwardOrigin) {
128
+ for (const key of originKeys) delete upstreamHeaders[key]
129
+ }
130
+ if (Object.keys(upstreamHeaders).length === 0)
131
+ return new WebSocket(targetUrl.href, protocols)
132
+ return new WebSocket(targetUrl.href, protocols, {
133
+ headers: upstreamHeaders,
134
+ })
135
+ }
136
+
137
+ export function isWebSocketProxyRequestUrl(rawUrl: string | undefined): boolean {
138
+ if (!rawUrl) return false
139
+ try {
140
+ return new URL(rawUrl, 'http://localhost').pathname === WEBSOCKET_PROXY_PATH
141
+ } catch {
142
+ return false
143
+ }
144
+ }
145
+
146
+ export function handleWebSocketProxyUpgrade(
147
+ req: IncomingMessage,
148
+ socket: Duplex,
149
+ head: Buffer,
150
+ forwardOrigin = true,
151
+ ): boolean {
152
+ if (!isWebSocketProxyRequestUrl(req.url)) return false
153
+ if (!isSameOriginUpgrade(req)) {
154
+ rejectUpgrade(socket, 403, 'forbidden websocket proxy origin')
155
+ return true
156
+ }
157
+
158
+ let targetUrl: URL
159
+ let headers: Record<string, string>
160
+ try {
161
+ const requestUrl = new URL(req.url || '/', 'http://localhost')
162
+ const target = requestUrl.searchParams.get('url')
163
+ if (!target) {
164
+ rejectUpgrade(socket, 400, 'missing websocket proxy url')
165
+ return true
166
+ }
167
+ targetUrl = new URL(target)
168
+ if (targetUrl.protocol !== 'ws:' && targetUrl.protocol !== 'wss:') {
169
+ rejectUpgrade(socket, 400, 'invalid websocket proxy protocol')
170
+ return true
171
+ }
172
+ headers = decodeProxyHeaders(requestUrl.searchParams.get('headers'))
173
+ } catch {
174
+ rejectUpgrade(socket, 400, 'invalid websocket proxy request')
175
+ return true
176
+ }
177
+
178
+ const protocols = getRequestedProtocols(req)
179
+ const upstream = createUpstreamWebSocket(targetUrl, protocols, headers, forwardOrigin)
180
+ let completed = false
181
+ socket.once('close', () => {
182
+ if (!completed) upstream.terminate()
183
+ })
184
+ upstream.once('open', () => {
185
+ if (completed) return
186
+ completed = true
187
+ const selectedProtocol = upstream.protocol
188
+ const proxyServer = new WebSocketServer({
189
+ noServer: true,
190
+ clientTracking: false,
191
+ handleProtocols(requestedProtocols) {
192
+ return selectedProtocol || requestedProtocols.values().next().value || false
193
+ },
194
+ })
195
+ proxyServer.handleUpgrade(req, socket, head, (clientWs) => {
196
+ connectProxyPair(clientWs, upstream)
197
+ })
198
+ })
199
+ upstream.once('error', () => {
200
+ if (completed) return
201
+ completed = true
202
+ rejectUpgrade(socket, 502, 'upstream websocket error')
203
+ })
204
+ upstream.once('close', () => {
205
+ if (completed) return
206
+ completed = true
207
+ rejectUpgrade(socket, 502, 'upstream websocket closed')
208
+ })
209
+ return true
210
+ }