@webspatial/core-sdk 1.6.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +10 -0
  3. package/dist/JSBCommand.d.ts +398 -0
  4. package/dist/JSBCommand.js +668 -0
  5. package/dist/JSBCommand.js.map +1 -0
  6. package/dist/Spatial.d.ts +63 -0
  7. package/dist/Spatial.js +60 -0
  8. package/dist/Spatial.js.map +1 -0
  9. package/dist/SpatialObject.d.ts +19 -0
  10. package/dist/SpatialObject.js +44 -0
  11. package/dist/SpatialObject.js.map +1 -0
  12. package/dist/SpatialScene.d.ts +51 -0
  13. package/dist/SpatialScene.js +74 -0
  14. package/dist/SpatialScene.js.map +1 -0
  15. package/dist/SpatialSession.d.ts +143 -0
  16. package/dist/SpatialSession.js +173 -0
  17. package/dist/SpatialSession.js.map +1 -0
  18. package/dist/SpatialWebEvent.d.ts +8 -0
  19. package/dist/SpatialWebEvent.js +18 -0
  20. package/dist/SpatialWebEvent.js.map +1 -0
  21. package/dist/SpatialWebEventCreator.d.ts +11 -0
  22. package/dist/SpatialWebEventCreator.js +11 -0
  23. package/dist/SpatialWebEventCreator.js.map +1 -0
  24. package/dist/Spatialized2DElement.d.ts +42 -0
  25. package/dist/Spatialized2DElement.js +47 -0
  26. package/dist/Spatialized2DElement.js.map +1 -0
  27. package/dist/SpatializedDynamic3DElement.d.ts +7 -0
  28. package/dist/SpatializedDynamic3DElement.js +43 -0
  29. package/dist/SpatializedDynamic3DElement.js.map +1 -0
  30. package/dist/SpatializedElement.d.ts +7 -0
  31. package/dist/SpatializedElement.js +206 -0
  32. package/dist/SpatializedElement.js.map +1 -0
  33. package/dist/SpatializedElementCreator.d.ts +15 -0
  34. package/dist/SpatializedElementCreator.js +47 -0
  35. package/dist/SpatializedElementCreator.js.map +1 -0
  36. package/dist/SpatializedStatic3DElement.d.ts +195 -0
  37. package/dist/SpatializedStatic3DElement.js +327 -0
  38. package/dist/SpatializedStatic3DElement.js.map +1 -0
  39. package/dist/WebMsgCommand.d.ts +7 -0
  40. package/dist/WebMsgCommand.js +23 -0
  41. package/dist/WebMsgCommand.js.map +1 -0
  42. package/dist/index.d.ts +35 -1101
  43. package/dist/index.js +21 -3393
  44. package/dist/index.js.map +1 -1
  45. package/dist/install-polyfills.d.ts +2 -0
  46. package/dist/install-polyfills.js +13 -0
  47. package/dist/install-polyfills.js.map +1 -0
  48. package/dist/isSSREnv.d.ts +3 -0
  49. package/dist/isSSREnv.js +6 -0
  50. package/dist/isSSREnv.js.map +1 -0
  51. package/dist/motion/AnimationObject.d.ts +7 -0
  52. package/dist/motion/AnimationObject.js +140 -0
  53. package/dist/motion/AnimationObject.js.map +1 -0
  54. package/dist/motion/compute/index.d.ts +10 -0
  55. package/dist/motion/compute/index.js +19 -0
  56. package/dist/motion/compute/index.js.map +1 -0
  57. package/dist/motion/compute/motionPropertyValues.d.ts +19 -0
  58. package/dist/motion/compute/motionPropertyValues.js +50 -0
  59. package/dist/motion/compute/motionPropertyValues.js.map +1 -0
  60. package/dist/motion/compute/normalize.d.ts +31 -0
  61. package/dist/motion/compute/normalize.js +201 -0
  62. package/dist/motion/compute/normalize.js.map +1 -0
  63. package/dist/motion/compute/validate.d.ts +22 -0
  64. package/dist/motion/compute/validate.js +103 -0
  65. package/dist/motion/compute/validate.js.map +1 -0
  66. package/dist/motion/index.d.ts +8 -0
  67. package/dist/motion/index.js +6 -0
  68. package/dist/motion/index.js.map +1 -0
  69. package/dist/motion/native/serializeMotionTimeline.d.ts +12 -0
  70. package/dist/motion/native/serializeMotionTimeline.js +21 -0
  71. package/dist/motion/native/serializeMotionTimeline.js.map +1 -0
  72. package/dist/physicalMetrics-W5uZ5xKb.d.ts +48 -0
  73. package/dist/physicalMetrics.d.ts +1 -0
  74. package/dist/physicalMetrics.js +58 -0
  75. package/dist/physicalMetrics.js.map +1 -0
  76. package/dist/platform-adapter/CommandResultUtils.d.ts +12 -0
  77. package/dist/platform-adapter/CommandResultUtils.js +21 -0
  78. package/dist/platform-adapter/CommandResultUtils.js.map +1 -0
  79. package/dist/platform-adapter/createPlatformSync.d.ts +16 -0
  80. package/dist/platform-adapter/createPlatformSync.js +30 -0
  81. package/dist/platform-adapter/createPlatformSync.js.map +1 -0
  82. package/dist/platform-adapter/index.d.ts +12 -0
  83. package/dist/platform-adapter/index.js +10 -0
  84. package/dist/platform-adapter/index.js.map +1 -0
  85. package/dist/platform-adapter/interface.d.ts +7 -0
  86. package/dist/platform-adapter/interface.js +1 -0
  87. package/dist/platform-adapter/interface.js.map +1 -0
  88. package/dist/platform-adapter/pico-os/PicoOSPlatform.d.ts +25 -0
  89. package/dist/platform-adapter/pico-os/PicoOSPlatform.js +168 -0
  90. package/dist/platform-adapter/pico-os/PicoOSPlatform.js.map +1 -0
  91. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.d.ts +66 -0
  92. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js +372 -0
  93. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js.map +1 -0
  94. package/dist/platform-adapter/spatialRequestMetadata.d.ts +6 -0
  95. package/dist/platform-adapter/spatialRequestMetadata.js +39 -0
  96. package/dist/platform-adapter/spatialRequestMetadata.js.map +1 -0
  97. package/dist/platform-adapter/spatialSceneQuery.d.ts +12 -0
  98. package/dist/platform-adapter/spatialSceneQuery.js +12 -0
  99. package/dist/platform-adapter/spatialSceneQuery.js.map +1 -0
  100. package/dist/platform-adapter/vision-os/VisionOSPlatform.d.ts +19 -0
  101. package/dist/platform-adapter/vision-os/VisionOSPlatform.js +77 -0
  102. package/dist/platform-adapter/vision-os/VisionOSPlatform.js.map +1 -0
  103. package/dist/platform-runtime.d.ts +12 -0
  104. package/dist/platform-runtime.js +14 -0
  105. package/dist/platform-runtime.js.map +1 -0
  106. package/dist/reality/Attachment.d.ts +19 -0
  107. package/dist/reality/Attachment.js +39 -0
  108. package/dist/reality/Attachment.js.map +1 -0
  109. package/dist/reality/component/ModelComponent.d.ts +14 -0
  110. package/dist/reality/component/ModelComponent.js +11 -0
  111. package/dist/reality/component/ModelComponent.js.map +1 -0
  112. package/dist/reality/component/SpatialComponent.d.ts +8 -0
  113. package/dist/reality/component/SpatialComponent.js +19 -0
  114. package/dist/reality/component/SpatialComponent.js.map +1 -0
  115. package/dist/reality/component/index.d.ts +8 -0
  116. package/dist/reality/component/index.js +3 -0
  117. package/dist/reality/component/index.js.map +1 -0
  118. package/dist/reality/entity/SpatialEntity.d.ts +7 -0
  119. package/dist/reality/entity/SpatialEntity.js +291 -0
  120. package/dist/reality/entity/SpatialEntity.js.map +1 -0
  121. package/dist/reality/entity/SpatialModelEntity.d.ts +17 -0
  122. package/dist/reality/entity/SpatialModelEntity.js +17 -0
  123. package/dist/reality/entity/SpatialModelEntity.js.map +1 -0
  124. package/dist/reality/entity/index.d.ts +8 -0
  125. package/dist/reality/entity/index.js +3 -0
  126. package/dist/reality/entity/index.js.map +1 -0
  127. package/dist/reality/geometry/SpatialBoxGeometry.d.ts +16 -0
  128. package/dist/reality/geometry/SpatialBoxGeometry.js +13 -0
  129. package/dist/reality/geometry/SpatialBoxGeometry.js.map +1 -0
  130. package/dist/reality/geometry/SpatialConeGeometry.d.ts +16 -0
  131. package/dist/reality/geometry/SpatialConeGeometry.js +13 -0
  132. package/dist/reality/geometry/SpatialConeGeometry.js.map +1 -0
  133. package/dist/reality/geometry/SpatialCylinderGeometry.d.ts +16 -0
  134. package/dist/reality/geometry/SpatialCylinderGeometry.js +13 -0
  135. package/dist/reality/geometry/SpatialCylinderGeometry.js.map +1 -0
  136. package/dist/reality/geometry/SpatialGeometry.d.ts +7 -0
  137. package/dist/reality/geometry/SpatialGeometry.js +13 -0
  138. package/dist/reality/geometry/SpatialGeometry.js.map +1 -0
  139. package/dist/reality/geometry/SpatialPlaneGeometry.d.ts +16 -0
  140. package/dist/reality/geometry/SpatialPlaneGeometry.js +13 -0
  141. package/dist/reality/geometry/SpatialPlaneGeometry.js.map +1 -0
  142. package/dist/reality/geometry/SpatialSphereGeometry.d.ts +16 -0
  143. package/dist/reality/geometry/SpatialSphereGeometry.js +13 -0
  144. package/dist/reality/geometry/SpatialSphereGeometry.js.map +1 -0
  145. package/dist/reality/geometry/index.d.ts +12 -0
  146. package/dist/reality/geometry/index.js +7 -0
  147. package/dist/reality/geometry/index.js.map +1 -0
  148. package/dist/reality/index.d.ts +18 -0
  149. package/dist/reality/index.js +7 -0
  150. package/dist/reality/index.js.map +1 -0
  151. package/dist/reality/material/SpatialMaterial.d.ts +7 -0
  152. package/dist/reality/material/SpatialMaterial.js +13 -0
  153. package/dist/reality/material/SpatialMaterial.js.map +1 -0
  154. package/dist/reality/material/SpatialUnlitMaterial.d.ts +16 -0
  155. package/dist/reality/material/SpatialUnlitMaterial.js +16 -0
  156. package/dist/reality/material/SpatialUnlitMaterial.js.map +1 -0
  157. package/dist/reality/material/index.d.ts +8 -0
  158. package/dist/reality/material/index.js +3 -0
  159. package/dist/reality/material/index.js.map +1 -0
  160. package/dist/reality/realityCreator.d.ts +22 -0
  161. package/dist/reality/realityCreator.js +89 -0
  162. package/dist/reality/realityCreator.js.map +1 -0
  163. package/dist/reality/resource/SpatialModelAsset.d.ts +15 -0
  164. package/dist/reality/resource/SpatialModelAsset.js +12 -0
  165. package/dist/reality/resource/SpatialModelAsset.js.map +1 -0
  166. package/dist/reality/resource/SpatialTextureResource.d.ts +16 -0
  167. package/dist/reality/resource/SpatialTextureResource.js +16 -0
  168. package/dist/reality/resource/SpatialTextureResource.js.map +1 -0
  169. package/dist/reality/resource/index.d.ts +9 -0
  170. package/dist/reality/resource/index.js +3 -0
  171. package/dist/reality/resource/index.js.map +1 -0
  172. package/dist/runtime/WebSpatialRuntimeError.d.ts +10 -0
  173. package/dist/runtime/WebSpatialRuntimeError.js +14 -0
  174. package/dist/runtime/WebSpatialRuntimeError.js.map +1 -0
  175. package/dist/runtime/capability-data.d.ts +12 -0
  176. package/dist/runtime/capability-data.js +134 -0
  177. package/dist/runtime/capability-data.js.map +1 -0
  178. package/dist/runtime/index.d.ts +8 -0
  179. package/dist/runtime/index.js +27 -0
  180. package/dist/runtime/index.js.map +1 -0
  181. package/dist/runtime/jsbAdapterPlatform.d.ts +9 -0
  182. package/dist/runtime/jsbAdapterPlatform.js +38 -0
  183. package/dist/runtime/jsbAdapterPlatform.js.map +1 -0
  184. package/dist/runtime/keys.d.ts +34 -0
  185. package/dist/runtime/keys.js +122 -0
  186. package/dist/runtime/keys.js.map +1 -0
  187. package/dist/runtime/semver.d.ts +8 -0
  188. package/dist/runtime/semver.js +32 -0
  189. package/dist/runtime/semver.js.map +1 -0
  190. package/dist/runtime/supports.d.ts +22 -0
  191. package/dist/runtime/supports.js +78 -0
  192. package/dist/runtime/supports.js.map +1 -0
  193. package/dist/runtime/types.d.ts +12 -0
  194. package/dist/runtime/types.js +1 -0
  195. package/dist/runtime/types.js.map +1 -0
  196. package/dist/runtime/userAgent.d.ts +20 -0
  197. package/dist/runtime/userAgent.js +41 -0
  198. package/dist/runtime/userAgent.js.map +1 -0
  199. package/dist/scene-polyfill.d.ts +18 -0
  200. package/dist/scene-polyfill.js +480 -0
  201. package/dist/scene-polyfill.js.map +1 -0
  202. package/dist/spatial-host.d.ts +13 -0
  203. package/dist/spatial-host.js +18 -0
  204. package/dist/spatial-host.js.map +1 -0
  205. package/dist/spatial-window-polyfill.d.ts +3 -0
  206. package/dist/spatial-window-polyfill.js +155 -0
  207. package/dist/spatial-window-polyfill.js.map +1 -0
  208. package/dist/spatializedElementMotion-_0XWPQCE.d.ts +1009 -0
  209. package/dist/types/animation.d.ts +7 -0
  210. package/dist/types/animation.js +1 -0
  211. package/dist/types/animation.js.map +1 -0
  212. package/dist/types/global.d.ts +38 -0
  213. package/dist/types/global.js +1 -0
  214. package/dist/types/global.js.map +1 -0
  215. package/dist/types/internal.d.ts +7 -0
  216. package/dist/types/internal.js +12 -0
  217. package/dist/types/internal.js.map +1 -0
  218. package/dist/types/motion/index.d.ts +7 -0
  219. package/dist/types/motion/index.js +3 -0
  220. package/dist/types/motion/index.js.map +1 -0
  221. package/dist/types/motion/spatializedElementMotion.d.ts +7 -0
  222. package/dist/types/motion/spatializedElementMotion.js +1 -0
  223. package/dist/types/motion/spatializedElementMotion.js.map +1 -0
  224. package/dist/types/motion/spatializedMotion.d.ts +7 -0
  225. package/dist/types/motion/spatializedMotion.js +16 -0
  226. package/dist/types/motion/spatializedMotion.js.map +1 -0
  227. package/dist/types/motion/spatializedPlayback.d.ts +11 -0
  228. package/dist/types/motion/spatializedPlayback.js +1 -0
  229. package/dist/types/motion/spatializedPlayback.js.map +1 -0
  230. package/dist/types/motion/spatializedVisual.d.ts +35 -0
  231. package/dist/types/motion/spatializedVisual.js +1 -0
  232. package/dist/types/motion/spatializedVisual.js.map +1 -0
  233. package/dist/types/types.d.ts +7 -0
  234. package/dist/types/types.js +117 -0
  235. package/dist/types/types.js.map +1 -0
  236. package/dist/utils.d.ts +44 -0
  237. package/dist/utils.js +86 -0
  238. package/dist/utils.js.map +1 -0
  239. package/package.json +20 -4
  240. package/src/JSBCommand.ts +148 -91
  241. package/src/Spatial.ts +0 -21
  242. package/src/SpatialObject.ts +10 -0
  243. package/src/SpatialScene.ts +1 -5
  244. package/src/SpatialSession.ts +17 -3
  245. package/src/Spatialized2DElement.ts +5 -0
  246. package/src/SpatializedDynamic3DElement.ts +5 -1
  247. package/src/SpatializedElement.ts +29 -0
  248. package/src/SpatializedElementCreator.ts +6 -4
  249. package/src/SpatializedStatic3DElement.test.ts +99 -0
  250. package/src/SpatializedStatic3DElement.ts +141 -4
  251. package/src/WebMsgCommand.ts +50 -0
  252. package/src/coverage-boost.test.ts +258 -316
  253. package/src/index.ts +28 -12
  254. package/src/install-polyfills.ts +38 -0
  255. package/src/jsbcommand.coverage.test.ts +42 -48
  256. package/src/motion/AnimationObject.test.ts +421 -0
  257. package/src/motion/AnimationObject.ts +208 -0
  258. package/src/motion/compute/index.ts +10 -0
  259. package/src/motion/compute/motionPropertyValues.test.ts +55 -0
  260. package/src/motion/compute/motionPropertyValues.ts +70 -0
  261. package/src/motion/compute/normalize.test.ts +99 -0
  262. package/src/motion/compute/normalize.ts +289 -0
  263. package/src/motion/compute/validate.test.ts +229 -0
  264. package/src/motion/compute/validate.ts +156 -0
  265. package/src/motion/index.ts +2 -0
  266. package/src/motion/native/serializeMotionTimeline.test.ts +61 -0
  267. package/src/motion/native/serializeMotionTimeline.ts +27 -0
  268. package/src/platform-adapter/CommandResultUtils.ts +2 -2
  269. package/src/platform-adapter/createPlatformSync.ts +36 -0
  270. package/src/platform-adapter/index.ts +5 -51
  271. package/src/platform-adapter/interface.ts +35 -23
  272. package/src/platform-adapter/pico-os/PicoOSPlatform.ts +156 -59
  273. package/src/platform-adapter/puppeteer/PuppeteerPlatform.ts +37 -11
  274. package/src/platform-adapter/spatialRequestMetadata.test.ts +175 -0
  275. package/src/platform-adapter/spatialRequestMetadata.ts +48 -0
  276. package/src/platform-adapter/spatialSceneQuery.ts +17 -0
  277. package/src/platform-adapter/vision-os/VisionOSPlatform.ts +60 -24
  278. package/src/platform-runtime.ts +13 -0
  279. package/src/reality/Attachment.ts +2 -2
  280. package/src/reality/entity/SpatialEntity.ts +127 -2
  281. package/src/reality/realityCreator.ts +15 -1
  282. package/src/reality/resource/SpatialTextureResource.ts +16 -0
  283. package/src/reality/resource/index.ts +1 -0
  284. package/src/runtime/WebSpatialRuntimeError.ts +16 -0
  285. package/src/runtime/capability-data.ts +213 -0
  286. package/src/runtime/contract-review.test.ts +44 -0
  287. package/src/runtime/index.ts +17 -0
  288. package/src/runtime/jsbAdapterPlatform.test.ts +36 -0
  289. package/src/runtime/jsbAdapterPlatform.ts +51 -0
  290. package/src/runtime/keys.ts +140 -0
  291. package/src/runtime/semver.ts +33 -0
  292. package/src/runtime/supports.test.ts +346 -0
  293. package/src/runtime/supports.ts +112 -0
  294. package/src/runtime/types.ts +11 -0
  295. package/src/runtime/useAnimation.capability.test.ts +275 -0
  296. package/src/runtime/userAgent.ts +64 -0
  297. package/src/scene-polyfill.manifest.test.ts +312 -9
  298. package/src/scene-polyfill.request-metadata.test.ts +39 -0
  299. package/src/scene-polyfill.test.ts +33 -94
  300. package/src/scene-polyfill.ts +125 -92
  301. package/src/spatial-host.ts +25 -0
  302. package/src/spatial-window-polyfill.ts +18 -2
  303. package/src/transform-roundtrip.test.ts +90 -0
  304. package/src/types/animation.ts +224 -0
  305. package/src/types/{global.d.ts → global.ts} +10 -12
  306. package/src/types/motion/index.ts +10 -0
  307. package/src/types/motion/spatializedElementMotion.ts +49 -0
  308. package/src/types/motion/spatializedMotion.ts +147 -0
  309. package/src/types/motion/spatializedPlayback.ts +17 -0
  310. package/src/types/motion/spatializedVisual.ts +24 -0
  311. package/src/types/types.ts +12 -0
  312. package/src/utils.ts +54 -0
  313. package/tsup.config.ts +61 -36
  314. package/vitest.config.ts +5 -1
  315. package/dist/iife/index.d.ts +0 -1101
  316. package/dist/iife/index.global.js +0 -75
  317. package/dist/iife/index.global.js.map +0 -1
  318. package/src/platform-adapter/android/AndroidPlatform.ts +0 -133
  319. package/src/platform-adapter/ssr/SSRPlatform.ts +0 -43
  320. /package/src/{ssr-polyfill.ts → isSSREnv.ts} +0 -0
@@ -0,0 +1,61 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { motionConfigToNativeTimeline } from './serializeMotionTimeline'
3
+
4
+ describe('motionConfigToNativeTimeline', () => {
5
+ test('builds timeline payload for multi-track', () => {
6
+ const tl = motionConfigToNativeTimeline({
7
+ duration: 5,
8
+ tracks: [
9
+ {
10
+ property: 'transform.translate.x',
11
+ keyframes: [
12
+ { at: 0, value: 0 },
13
+ { at: 5, value: 100 },
14
+ ],
15
+ },
16
+ {
17
+ property: 'opacity',
18
+ timingFunction: 'easeOut',
19
+ keyframes: [
20
+ { at: 3, value: 0 },
21
+ { at: 5, value: 1 },
22
+ ],
23
+ },
24
+ ],
25
+ })
26
+ expect(tl.duration).toBe(5)
27
+ expect(tl.tracks).toHaveLength(2)
28
+ expect(tl.tracks[1].timingFunction).toBe('easeOut')
29
+ })
30
+
31
+ test('serializes keyframe and config timingFunction propagation', () => {
32
+ const tl = motionConfigToNativeTimeline({
33
+ duration: 4,
34
+ timingFunction: 'easeInOut',
35
+ tracks: [
36
+ {
37
+ property: 'transform.translate.x',
38
+ keyframes: [
39
+ { at: 0, value: 0, timingFunction: 'easeOut' },
40
+ { at: 2, value: 100 },
41
+ { at: 4, value: 200 },
42
+ ],
43
+ },
44
+ {
45
+ property: 'opacity',
46
+ keyframes: [
47
+ { at: 0, value: 0 },
48
+ { at: 4, value: 1 },
49
+ ],
50
+ },
51
+ ],
52
+ })
53
+
54
+ expect(tl.tracks[0].keyframes[0]).toMatchObject({
55
+ at: 0,
56
+ value: 0,
57
+ timingFunction: 'easeOut',
58
+ })
59
+ expect(tl.tracks[1].timingFunction).toBe('easeInOut')
60
+ })
61
+ })
@@ -0,0 +1,27 @@
1
+ import type {
2
+ NormalizedSpatializedMotionConfig,
3
+ SpatializedMotionTimeline,
4
+ } from '../../types/motion/spatializedMotion'
5
+
6
+ /** Full timeline payload for native. */
7
+ export function motionConfigToNativeTimeline(
8
+ config: NormalizedSpatializedMotionConfig,
9
+ ): SpatializedMotionTimeline {
10
+ return {
11
+ duration: config.duration,
12
+ delay: config.delay,
13
+ playbackRate: config.playbackRate,
14
+ loop: config.loop,
15
+ tracks: config.tracks.map(track => ({
16
+ property: track.property,
17
+ keyframes: track.keyframes.map(k => ({
18
+ at: k.at,
19
+ value: k.value,
20
+ ...(k.timingFunction !== undefined
21
+ ? { timingFunction: k.timingFunction }
22
+ : {}),
23
+ })),
24
+ timingFunction: track.timingFunction ?? config.timingFunction ?? 'linear',
25
+ })),
26
+ }
27
+ }
@@ -1,6 +1,6 @@
1
1
  import { CommandResult } from './interface'
2
2
 
3
- export function CommandResultSuccess(data: any): CommandResult {
3
+ export function CommandResultSuccess<TData>(data: TData): CommandResult<TData> {
4
4
  return {
5
5
  success: true,
6
6
  data,
@@ -12,7 +12,7 @@ export function CommandResultSuccess(data: any): CommandResult {
12
12
  export function CommandResultFailure(
13
13
  errorCode: string,
14
14
  errorMessage = '',
15
- ): CommandResult {
15
+ ): CommandResult<undefined> {
16
16
  return {
17
17
  success: false,
18
18
  data: undefined,
@@ -0,0 +1,36 @@
1
+ import { resolveJsbAdapterPlatform } from '../runtime/jsbAdapterPlatform'
2
+ import { isSSREnv } from '../isSSREnv'
3
+ import { PlatformAbility } from './interface'
4
+ import { PicoOSPlatform } from './pico-os/PicoOSPlatform'
5
+ import { PuppeteerPlatform } from './puppeteer/PuppeteerPlatform'
6
+ import { VisionOSPlatform } from './vision-os/VisionOSPlatform'
7
+
8
+ const SSR_PLATFORM_ERROR =
9
+ 'WebSpatial platform APIs (JSB / openSpatialScene) cannot run during SSR or without window. Use @webspatial/react-sdk default entry with facades, or CSR-gate spatial UI on the client.'
10
+
11
+ function assertNever(_: never): never {
12
+ throw new Error('Unhandled jsb adapter platform kind')
13
+ }
14
+
15
+ /**
16
+ * Construct the JSB platform synchronously (static imports).
17
+ * Used by getPlatformSync (e.g. scene-polyfill openSpatialSceneSync) and kept
18
+ * consistent with async createPlatform so paths share one implementation.
19
+ */
20
+ export function createPlatformSync(): PlatformAbility {
21
+ if (isSSREnv()) {
22
+ throw new Error(SSR_PLATFORM_ERROR)
23
+ }
24
+ const userAgent = window.navigator.userAgent
25
+ const kind = resolveJsbAdapterPlatform(userAgent)
26
+ switch (kind) {
27
+ case 'puppeteer':
28
+ return new PuppeteerPlatform()
29
+ case 'picoos':
30
+ return new PicoOSPlatform()
31
+ case 'visionos':
32
+ return new VisionOSPlatform()
33
+ default:
34
+ return assertNever(kind)
35
+ }
36
+ }
@@ -1,53 +1,7 @@
1
- import { isSSREnv } from '../ssr-polyfill'
2
- import { PlatformAbility } from './interface'
3
- import { SSRPlatform } from './ssr/SSRPlatform'
1
+ export { createPlatformSync } from './createPlatformSync'
2
+ import { createPlatformSync } from './createPlatformSync'
3
+ import type { PlatformAbility } from './interface'
4
4
 
5
- function getWebSpatialVersion(ua: string): number[] | null {
6
- const match = ua.match(/WebSpatial\/(\d+)\.(\d+)\.(\d+)/)
7
- if (!match) {
8
- return null
9
- }
10
- return [Number(match[1]), Number(match[2]), Number(match[3])]
11
- }
12
-
13
- function isVersionGreater(a: number[] | null, b: number[]): boolean {
14
- if (!a) {
15
- return false
16
- }
17
- for (let index = 0; index < 3; index += 1) {
18
- const diff = a[index] - b[index]
19
- if (diff > 0) {
20
- return true
21
- }
22
- if (diff < 0) {
23
- return false
24
- }
25
- }
26
- return false
27
- }
28
-
29
- export function createPlatform(): PlatformAbility {
30
- if (isSSREnv()) {
31
- return new SSRPlatform()
32
- }
33
- const userAgent = window.navigator.userAgent
34
- const webSpatialVersion = getWebSpatialVersion(userAgent)
35
- if (window.navigator.userAgent.includes('Puppeteer')) {
36
- const PuppeteerPlatform =
37
- require('./puppeteer/PuppeteerPlatform').PuppeteerPlatform
38
- return new PuppeteerPlatform()
39
- } else if (
40
- userAgent.includes('PicoWebApp') &&
41
- isVersionGreater(webSpatialVersion, [0, 0, 1])
42
- ) {
43
- const PicoOSPlatform = require('./pico-os/PicoOSPlatform').PicoOSPlatform
44
- return new PicoOSPlatform()
45
- } else if (userAgent.includes('Android') || userAgent.includes('Linux')) {
46
- const AndroidPlatform = require('./android/AndroidPlatform').AndroidPlatform
47
- return new AndroidPlatform()
48
- } else {
49
- const VisionOSPlatform =
50
- require('./vision-os/VisionOSPlatform').VisionOSPlatform
51
- return new VisionOSPlatform()
52
- }
5
+ export async function createPlatform(): Promise<PlatformAbility> {
6
+ return createPlatformSync()
53
7
  }
@@ -1,36 +1,48 @@
1
- export interface CommandResult {
2
- success: boolean
3
- data: any
4
- errorCode: string | undefined
5
- errorMessage: string | undefined
6
- }
1
+ import type { SpatialSceneCreationOptionsInternal } from '../types/internal'
2
+ import type { AttachmentEntityOptions } from '../types/types'
7
3
 
8
- export interface WebSpatialProtocolResult extends CommandResult {
4
+ export interface CommandResult<TData = any> {
9
5
  success: boolean
10
- data:
11
- | {
12
- windowProxy: WindowProxy
13
- id: string
14
- }
15
- | undefined
6
+ data: TData
16
7
  errorCode: string | undefined
17
8
  errorMessage: string | undefined
18
9
  }
19
10
 
11
+ export type WebSpatialProtocolResult = CommandResult<
12
+ | {
13
+ // Platform-dependent window proxy shape:
14
+ // - browser WindowProxy (visionOS/PICO)
15
+ // - puppeteer simulated window object
16
+ // Keep broad to avoid over-constraining platform adapters/callers.
17
+ windowProxy: any
18
+ id: string
19
+ }
20
+ | undefined
21
+ >
22
+
23
+ /**
24
+ * Host/runtime bridge: JSB plus explicit spatial host capabilities.
25
+ * Implementations may use webspatial://, iframes, native events, etc.
26
+ */
20
27
  export interface PlatformAbility {
21
28
  callJSB(cmd: string, msg: string): Promise<CommandResult>
22
- callWebSpatialProtocol(
23
- schema: string,
24
- query?: string,
25
- target?: string,
26
- features?: string,
27
- ): Promise<WebSpatialProtocolResult>
28
29
 
29
- callWebSpatialProtocolSync(
30
- schema: string,
31
- query?: string,
30
+ /**
31
+ * Open a spatial scene synchronously (e.g. window.open polyfill).
32
+ * Implementations may use webspatial://createSpatialScene under the hood.
33
+ */
34
+ openSpatialSceneSync(
35
+ url: string,
36
+ config: SpatialSceneCreationOptionsInternal | undefined,
32
37
  target?: string,
33
38
  features?: string,
34
- resultCallback?: (result: CommandResult) => void,
35
39
  ): WebSpatialProtocolResult
40
+
41
+ /** Create a native-backed spatial 2D surface (spatial div). */
42
+ createNativeSpatialDiv(): Promise<WebSpatialProtocolResult>
43
+
44
+ /** Create a native attachment surface; options reserved for future protocol fields. */
45
+ createNativeAttachment(
46
+ options?: AttachmentEntityOptions,
47
+ ): Promise<WebSpatialProtocolResult>
36
48
  }
@@ -1,22 +1,36 @@
1
- import { PlatformAbility, CommandResult } from '../interface'
1
+ import {
2
+ PlatformAbility,
3
+ CommandResult,
4
+ WebSpatialProtocolResult,
5
+ } from '../interface'
2
6
  import {
3
7
  CommandResultFailure,
4
8
  CommandResultSuccess,
5
9
  } from '../CommandResultUtils'
10
+ import { buildSpatialSceneQuery } from '../spatialSceneQuery'
6
11
  import { SpatialWebEvent } from '../../SpatialWebEvent'
12
+ import type { SpatialSceneCreationOptionsInternal } from '../../types/internal'
13
+ import type { AttachmentEntityOptions } from '../../types/types'
14
+ import {
15
+ buildSpatialRequestQuery,
16
+ createSpatialRequestId,
17
+ DEFAULT_SPATIAL_REQUEST_TIMEOUT_MS,
18
+ } from '../spatialRequestMetadata'
7
19
 
8
20
  interface JSBResponse {
9
21
  success: boolean
10
22
  data: any
11
23
  }
12
24
  type JSBError = {
13
- code: string
25
+ code?: string
14
26
  message: string
15
27
  }
16
28
 
17
29
  let requestId = 0
18
30
 
19
31
  const MAX_ID = 100000
32
+ const DEFAULT_JSB_ERROR_CODE = 'E_PICO_JSB'
33
+ const DEFAULT_JSB_ERROR_MESSAGE = 'Pico JSB execution failed'
20
34
 
21
35
  function nextRequestId() {
22
36
  requestId = (requestId + 1) % MAX_ID
@@ -28,104 +42,187 @@ export class PicoOSPlatform implements PlatformAbility {
28
42
  async callJSB(cmd: string, msg: string): Promise<CommandResult> {
29
43
  // swan JS Bridge interface only support sync invoking
30
44
  // in order to implement promise API, register every request by requestId and remove when resolve/reject.
31
- return new Promise((resolve, reject) => {
45
+ return new Promise(resolve => {
32
46
  try {
33
47
  const rId = nextRequestId()
34
48
 
35
49
  SpatialWebEvent.addEventReceiver(rId, (result: JSBResponse) => {
36
50
  SpatialWebEvent.removeEventReceiver(rId)
37
- if (result.success) {
38
- resolve(CommandResultSuccess(result.data))
39
- } else {
40
- const { code, message } = result.data as JSBError
41
- resolve(CommandResultFailure(code, message))
42
- }
51
+ resolve(this.toCommandResult(result))
43
52
  })
44
53
 
45
54
  const ans = window.webspatialBridge.postMessage(rId, cmd, msg)
46
55
  if (ans !== '') {
47
56
  SpatialWebEvent.removeEventReceiver(rId)
48
57
  // sync call
49
- const result = JSON.parse(ans) as JSBResponse
50
- if (result.success) {
51
- resolve(CommandResultSuccess(result.data))
52
- } else {
53
- const { code, message } = result.data as JSBError
54
- resolve(CommandResultFailure(code, message))
55
- }
58
+ resolve(this.parseBridgeResponse(ans))
56
59
  }
57
60
  } catch (error: unknown) {
58
61
  console.error(`SwanPlatform cmd: ${cmd}, msg: ${msg} error: ${error}`)
59
- const { code, message } = error as JSBError
62
+ const { code, message } = this.parseJSBError(error)
60
63
  resolve(CommandResultFailure(code, message))
61
64
  }
62
65
  })
63
66
  }
64
67
 
65
- async callWebSpatialProtocol(
66
- command: string,
67
- query?: string,
68
+ openSpatialSceneSync(
69
+ url: string,
70
+ config: SpatialSceneCreationOptionsInternal | undefined,
68
71
  target?: string,
69
72
  features?: string,
70
- ): Promise<CommandResult> {
71
- // Waiting for request to create spatial div
72
- return new Promise((resolve, reject) => {
73
- const createdId = nextRequestId()
73
+ ): WebSpatialProtocolResult {
74
+ const query = buildSpatialSceneQuery(url, config)
75
+ const { spatialId: id = '', windowProxy } = this.openWindow(
76
+ 'createSpatialScene',
77
+ query,
78
+ target,
79
+ features,
80
+ )
81
+
82
+ return CommandResultSuccess({ windowProxy, id })
83
+ }
84
+
85
+ createNativeSpatialDiv(): Promise<WebSpatialProtocolResult> {
86
+ return this.waitForRidProtocolAsync('createSpatialized2DElement')
87
+ }
88
+
89
+ createNativeAttachment(
90
+ _options?: AttachmentEntityOptions,
91
+ ): Promise<WebSpatialProtocolResult> {
92
+ return this.waitForRidProtocolAsync('createAttachment')
93
+ }
94
+
95
+ /**
96
+ * Async path for createNativeSpatialDiv / createNativeAttachment: open webspatial URL
97
+ * with rid= correlation (Pico OS 6).
98
+ */
99
+ private waitForRidProtocolAsync(
100
+ command: string,
101
+ ): Promise<WebSpatialProtocolResult> {
102
+ return new Promise(resolve => {
103
+ const createdId = createSpatialRequestId()
104
+ let settled = false
105
+ let timeoutId: ReturnType<typeof setTimeout> | undefined
106
+ let cleanupDocumentReadyListener: (() => void) | undefined
107
+
108
+ // Native creation may respond synchronously, asynchronously, or never.
109
+ // Funnel every path through one settle() helper so receiver cleanup is
110
+ // exactly-once.
111
+ const settle = (result: WebSpatialProtocolResult) => {
112
+ if (settled) return
113
+ settled = true
114
+ if (timeoutId !== undefined) {
115
+ clearTimeout(timeoutId)
116
+ }
117
+ cleanupDocumentReadyListener?.()
118
+ cleanupDocumentReadyListener = undefined
119
+ SpatialWebEvent.removeEventReceiver(createdId)
120
+ resolve(result)
121
+ }
122
+
74
123
  try {
75
- let windowProxy: any = null
124
+ let windowProxy: WindowProxy | null = null
125
+ const settleWhenDocumentComplete = (spatialId: string) => {
126
+ const successResult = CommandResultSuccess({
127
+ windowProxy: windowProxy,
128
+ id: spatialId,
129
+ })
130
+ const childDocument = windowProxy?.document
131
+
132
+ if (!childDocument) {
133
+ settle(
134
+ CommandResultFailure(
135
+ 'E_SPATIAL_DOCUMENT_UNAVAILABLE',
136
+ `${command} document is unavailable`,
137
+ ),
138
+ )
139
+ return
140
+ }
141
+
142
+ if (childDocument.readyState === 'complete') {
143
+ settle(successResult)
144
+ return
145
+ }
146
+
147
+ const onReadyStateChange = () => {
148
+ if (childDocument.readyState !== 'complete') return
149
+ settle(successResult)
150
+ }
151
+
152
+ cleanupDocumentReadyListener = () => {
153
+ childDocument.removeEventListener(
154
+ 'readystatechange',
155
+ onReadyStateChange,
156
+ )
157
+ }
158
+ childDocument.addEventListener('readystatechange', onReadyStateChange)
159
+ }
160
+
161
+ timeoutId = setTimeout(() => {
162
+ settle(
163
+ CommandResultFailure(
164
+ 'E_SPATIAL_REQUEST_TIMEOUT',
165
+ `${command} request timed out`,
166
+ ),
167
+ )
168
+ }, DEFAULT_SPATIAL_REQUEST_TIMEOUT_MS)
169
+
76
170
  SpatialWebEvent.addEventReceiver(
77
171
  createdId,
78
172
  (result: { spatialId: string }) => {
79
- resolve(
80
- CommandResultSuccess({
81
- windowProxy: windowProxy,
82
- id: result.spatialId,
83
- }),
84
- )
85
- SpatialWebEvent.removeEventReceiver(createdId)
173
+ settleWhenDocumentComplete(result.spatialId)
86
174
  },
87
175
  )
88
176
  windowProxy = this.openWindow(
89
177
  command,
90
- 'rid=' + createdId,
91
- target,
92
- features,
178
+ buildSpatialRequestQuery(createdId),
93
179
  ).windowProxy
94
180
  } catch (error: unknown) {
95
- const { code, message } = error as JSBError
96
- SpatialWebEvent.removeEventReceiver(createdId)
97
- resolve(CommandResultFailure(code, message))
181
+ const { code, message } = this.parseJSBError(error)
182
+ settle(CommandResultFailure(code, message))
98
183
  }
99
184
  })
100
185
  }
101
186
 
102
- callWebSpatialProtocolSync(
187
+ private openWindow(
103
188
  command: string,
104
189
  query?: string,
105
190
  target?: string,
106
191
  features?: string,
107
- ): CommandResult {
108
- const { spatialId: id = '', windowProxy } = this.openWindow(
109
- command,
110
- query,
111
- target,
112
- features,
113
- )
192
+ ): { spatialId: string; windowProxy: WindowProxy | null } {
193
+ const url = query
194
+ ? `webspatial://${command}?${query}`
195
+ : `webspatial://${command}`
196
+ const windowProxy = window.open(url, target, features)
197
+ return { spatialId: '', windowProxy }
198
+ }
114
199
 
115
- return CommandResultSuccess({ windowProxy, id })
200
+ private parseBridgeResponse(ans: string): CommandResult {
201
+ try {
202
+ const result = JSON.parse(ans) as JSBResponse
203
+ return this.toCommandResult(result)
204
+ } catch {
205
+ return CommandResultFailure(
206
+ DEFAULT_JSB_ERROR_CODE,
207
+ 'Invalid Pico JSB response payload',
208
+ )
209
+ }
116
210
  }
117
211
 
118
- private openWindow(
119
- command: string,
120
- query?: string,
121
- target?: string,
122
- features?: string,
123
- ) {
124
- const windowProxy = window.open(
125
- `webspatial://${command}?${query || ''}`,
126
- target,
127
- features,
128
- )
129
- return { spatialId: '', windowProxy }
212
+ private toCommandResult(result: JSBResponse): CommandResult {
213
+ if (result.success) {
214
+ return CommandResultSuccess(result.data)
215
+ }
216
+ const { code, message } = this.parseJSBError(result.data)
217
+ return CommandResultFailure(code, message)
218
+ }
219
+
220
+ private parseJSBError(error: unknown): { code: string; message: string } {
221
+ return {
222
+ code: (error as JSBError)?.code ?? DEFAULT_JSB_ERROR_CODE,
223
+ message:
224
+ (error as JSBError)?.message ??
225
+ (typeof error === 'string' ? error : DEFAULT_JSB_ERROR_MESSAGE),
226
+ }
130
227
  }
131
228
  }
@@ -1,4 +1,11 @@
1
- import { PlatformAbility, CommandResult } from '../interface'
1
+ import {
2
+ PlatformAbility,
3
+ CommandResult,
4
+ WebSpatialProtocolResult,
5
+ } from '../interface'
6
+ import { buildSpatialSceneQuery } from '../spatialSceneQuery'
7
+ import type { SpatialSceneCreationOptionsInternal } from '../../types/internal'
8
+ import type { AttachmentEntityOptions } from '../../types/types'
2
9
  import {
3
10
  CommandResultFailure,
4
11
  CommandResultSuccess,
@@ -17,12 +24,6 @@ declare global {
17
24
  }
18
25
  }
19
26
 
20
- type JSBError = {
21
- message: string
22
- }
23
-
24
- console.log('PuppeteerPlatform')
25
-
26
27
  export class PuppeteerPlatform implements PlatformAbility {
27
28
  // store iframe instance
28
29
  private iframeRegistry: Map<string, HTMLIFrameElement> = new Map()
@@ -85,12 +86,37 @@ export class PuppeteerPlatform implements PlatformAbility {
85
86
  }
86
87
  }
87
88
 
88
- callWebSpatialProtocol(
89
+ openSpatialSceneSync(
90
+ url: string,
91
+ config: SpatialSceneCreationOptionsInternal | undefined,
92
+ target?: string,
93
+ features?: string,
94
+ ): WebSpatialProtocolResult {
95
+ const query = buildSpatialSceneQuery(url, config)
96
+ return this.runProtocolSync('createSpatialScene', query, target, features)
97
+ }
98
+
99
+ createNativeSpatialDiv(): Promise<WebSpatialProtocolResult> {
100
+ return this.runProtocolAsync(
101
+ 'createSpatialized2DElement',
102
+ '',
103
+ undefined,
104
+ undefined,
105
+ )
106
+ }
107
+
108
+ createNativeAttachment(
109
+ _options?: AttachmentEntityOptions,
110
+ ): Promise<WebSpatialProtocolResult> {
111
+ return this.runProtocolAsync('createAttachment', '', undefined, undefined)
112
+ }
113
+
114
+ private runProtocolAsync(
89
115
  command: string,
90
116
  query?: string,
91
117
  target?: string,
92
118
  features?: string,
93
- ): Promise<CommandResult> {
119
+ ): Promise<WebSpatialProtocolResult> {
94
120
  console.log(
95
121
  `PuppeteerPlatform: Calling webspatial protocol: webspatial://${command}${query ? `?${query}` : ''}`,
96
122
  )
@@ -124,12 +150,12 @@ export class PuppeteerPlatform implements PlatformAbility {
124
150
  })
125
151
  }
126
152
 
127
- callWebSpatialProtocolSync(
153
+ private runProtocolSync(
128
154
  command: string,
129
155
  query?: string,
130
156
  target?: string,
131
157
  features?: string,
132
- ): CommandResult {
158
+ ): WebSpatialProtocolResult {
133
159
  try {
134
160
  // create complete webspatial URL
135
161
  const webspatialUrl = `webspatial://${command}${query ? `?${query}` : ''}`