@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.
- package/CHANGELOG.md +84 -0
- package/README.md +10 -0
- package/dist/JSBCommand.d.ts +398 -0
- package/dist/JSBCommand.js +668 -0
- package/dist/JSBCommand.js.map +1 -0
- package/dist/Spatial.d.ts +63 -0
- package/dist/Spatial.js +60 -0
- package/dist/Spatial.js.map +1 -0
- package/dist/SpatialObject.d.ts +19 -0
- package/dist/SpatialObject.js +44 -0
- package/dist/SpatialObject.js.map +1 -0
- package/dist/SpatialScene.d.ts +51 -0
- package/dist/SpatialScene.js +74 -0
- package/dist/SpatialScene.js.map +1 -0
- package/dist/SpatialSession.d.ts +143 -0
- package/dist/SpatialSession.js +173 -0
- package/dist/SpatialSession.js.map +1 -0
- package/dist/SpatialWebEvent.d.ts +8 -0
- package/dist/SpatialWebEvent.js +18 -0
- package/dist/SpatialWebEvent.js.map +1 -0
- package/dist/SpatialWebEventCreator.d.ts +11 -0
- package/dist/SpatialWebEventCreator.js +11 -0
- package/dist/SpatialWebEventCreator.js.map +1 -0
- package/dist/Spatialized2DElement.d.ts +42 -0
- package/dist/Spatialized2DElement.js +47 -0
- package/dist/Spatialized2DElement.js.map +1 -0
- package/dist/SpatializedDynamic3DElement.d.ts +7 -0
- package/dist/SpatializedDynamic3DElement.js +43 -0
- package/dist/SpatializedDynamic3DElement.js.map +1 -0
- package/dist/SpatializedElement.d.ts +7 -0
- package/dist/SpatializedElement.js +206 -0
- package/dist/SpatializedElement.js.map +1 -0
- package/dist/SpatializedElementCreator.d.ts +15 -0
- package/dist/SpatializedElementCreator.js +47 -0
- package/dist/SpatializedElementCreator.js.map +1 -0
- package/dist/SpatializedStatic3DElement.d.ts +195 -0
- package/dist/SpatializedStatic3DElement.js +327 -0
- package/dist/SpatializedStatic3DElement.js.map +1 -0
- package/dist/WebMsgCommand.d.ts +7 -0
- package/dist/WebMsgCommand.js +23 -0
- package/dist/WebMsgCommand.js.map +1 -0
- package/dist/index.d.ts +35 -1101
- package/dist/index.js +21 -3393
- package/dist/index.js.map +1 -1
- package/dist/install-polyfills.d.ts +2 -0
- package/dist/install-polyfills.js +13 -0
- package/dist/install-polyfills.js.map +1 -0
- package/dist/isSSREnv.d.ts +3 -0
- package/dist/isSSREnv.js +6 -0
- package/dist/isSSREnv.js.map +1 -0
- package/dist/motion/AnimationObject.d.ts +7 -0
- package/dist/motion/AnimationObject.js +140 -0
- package/dist/motion/AnimationObject.js.map +1 -0
- package/dist/motion/compute/index.d.ts +10 -0
- package/dist/motion/compute/index.js +19 -0
- package/dist/motion/compute/index.js.map +1 -0
- package/dist/motion/compute/motionPropertyValues.d.ts +19 -0
- package/dist/motion/compute/motionPropertyValues.js +50 -0
- package/dist/motion/compute/motionPropertyValues.js.map +1 -0
- package/dist/motion/compute/normalize.d.ts +31 -0
- package/dist/motion/compute/normalize.js +201 -0
- package/dist/motion/compute/normalize.js.map +1 -0
- package/dist/motion/compute/validate.d.ts +22 -0
- package/dist/motion/compute/validate.js +103 -0
- package/dist/motion/compute/validate.js.map +1 -0
- package/dist/motion/index.d.ts +8 -0
- package/dist/motion/index.js +6 -0
- package/dist/motion/index.js.map +1 -0
- package/dist/motion/native/serializeMotionTimeline.d.ts +12 -0
- package/dist/motion/native/serializeMotionTimeline.js +21 -0
- package/dist/motion/native/serializeMotionTimeline.js.map +1 -0
- package/dist/physicalMetrics-W5uZ5xKb.d.ts +48 -0
- package/dist/physicalMetrics.d.ts +1 -0
- package/dist/physicalMetrics.js +58 -0
- package/dist/physicalMetrics.js.map +1 -0
- package/dist/platform-adapter/CommandResultUtils.d.ts +12 -0
- package/dist/platform-adapter/CommandResultUtils.js +21 -0
- package/dist/platform-adapter/CommandResultUtils.js.map +1 -0
- package/dist/platform-adapter/createPlatformSync.d.ts +16 -0
- package/dist/platform-adapter/createPlatformSync.js +30 -0
- package/dist/platform-adapter/createPlatformSync.js.map +1 -0
- package/dist/platform-adapter/index.d.ts +12 -0
- package/dist/platform-adapter/index.js +10 -0
- package/dist/platform-adapter/index.js.map +1 -0
- package/dist/platform-adapter/interface.d.ts +7 -0
- package/dist/platform-adapter/interface.js +1 -0
- package/dist/platform-adapter/interface.js.map +1 -0
- package/dist/platform-adapter/pico-os/PicoOSPlatform.d.ts +25 -0
- package/dist/platform-adapter/pico-os/PicoOSPlatform.js +168 -0
- package/dist/platform-adapter/pico-os/PicoOSPlatform.js.map +1 -0
- package/dist/platform-adapter/puppeteer/PuppeteerPlatform.d.ts +66 -0
- package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js +372 -0
- package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js.map +1 -0
- package/dist/platform-adapter/spatialRequestMetadata.d.ts +6 -0
- package/dist/platform-adapter/spatialRequestMetadata.js +39 -0
- package/dist/platform-adapter/spatialRequestMetadata.js.map +1 -0
- package/dist/platform-adapter/spatialSceneQuery.d.ts +12 -0
- package/dist/platform-adapter/spatialSceneQuery.js +12 -0
- package/dist/platform-adapter/spatialSceneQuery.js.map +1 -0
- package/dist/platform-adapter/vision-os/VisionOSPlatform.d.ts +19 -0
- package/dist/platform-adapter/vision-os/VisionOSPlatform.js +77 -0
- package/dist/platform-adapter/vision-os/VisionOSPlatform.js.map +1 -0
- package/dist/platform-runtime.d.ts +12 -0
- package/dist/platform-runtime.js +14 -0
- package/dist/platform-runtime.js.map +1 -0
- package/dist/reality/Attachment.d.ts +19 -0
- package/dist/reality/Attachment.js +39 -0
- package/dist/reality/Attachment.js.map +1 -0
- package/dist/reality/component/ModelComponent.d.ts +14 -0
- package/dist/reality/component/ModelComponent.js +11 -0
- package/dist/reality/component/ModelComponent.js.map +1 -0
- package/dist/reality/component/SpatialComponent.d.ts +8 -0
- package/dist/reality/component/SpatialComponent.js +19 -0
- package/dist/reality/component/SpatialComponent.js.map +1 -0
- package/dist/reality/component/index.d.ts +8 -0
- package/dist/reality/component/index.js +3 -0
- package/dist/reality/component/index.js.map +1 -0
- package/dist/reality/entity/SpatialEntity.d.ts +7 -0
- package/dist/reality/entity/SpatialEntity.js +291 -0
- package/dist/reality/entity/SpatialEntity.js.map +1 -0
- package/dist/reality/entity/SpatialModelEntity.d.ts +17 -0
- package/dist/reality/entity/SpatialModelEntity.js +17 -0
- package/dist/reality/entity/SpatialModelEntity.js.map +1 -0
- package/dist/reality/entity/index.d.ts +8 -0
- package/dist/reality/entity/index.js +3 -0
- package/dist/reality/entity/index.js.map +1 -0
- package/dist/reality/geometry/SpatialBoxGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialBoxGeometry.js +13 -0
- package/dist/reality/geometry/SpatialBoxGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialConeGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialConeGeometry.js +13 -0
- package/dist/reality/geometry/SpatialConeGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialCylinderGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialCylinderGeometry.js +13 -0
- package/dist/reality/geometry/SpatialCylinderGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialGeometry.d.ts +7 -0
- package/dist/reality/geometry/SpatialGeometry.js +13 -0
- package/dist/reality/geometry/SpatialGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialPlaneGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialPlaneGeometry.js +13 -0
- package/dist/reality/geometry/SpatialPlaneGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialSphereGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialSphereGeometry.js +13 -0
- package/dist/reality/geometry/SpatialSphereGeometry.js.map +1 -0
- package/dist/reality/geometry/index.d.ts +12 -0
- package/dist/reality/geometry/index.js +7 -0
- package/dist/reality/geometry/index.js.map +1 -0
- package/dist/reality/index.d.ts +18 -0
- package/dist/reality/index.js +7 -0
- package/dist/reality/index.js.map +1 -0
- package/dist/reality/material/SpatialMaterial.d.ts +7 -0
- package/dist/reality/material/SpatialMaterial.js +13 -0
- package/dist/reality/material/SpatialMaterial.js.map +1 -0
- package/dist/reality/material/SpatialUnlitMaterial.d.ts +16 -0
- package/dist/reality/material/SpatialUnlitMaterial.js +16 -0
- package/dist/reality/material/SpatialUnlitMaterial.js.map +1 -0
- package/dist/reality/material/index.d.ts +8 -0
- package/dist/reality/material/index.js +3 -0
- package/dist/reality/material/index.js.map +1 -0
- package/dist/reality/realityCreator.d.ts +22 -0
- package/dist/reality/realityCreator.js +89 -0
- package/dist/reality/realityCreator.js.map +1 -0
- package/dist/reality/resource/SpatialModelAsset.d.ts +15 -0
- package/dist/reality/resource/SpatialModelAsset.js +12 -0
- package/dist/reality/resource/SpatialModelAsset.js.map +1 -0
- package/dist/reality/resource/SpatialTextureResource.d.ts +16 -0
- package/dist/reality/resource/SpatialTextureResource.js +16 -0
- package/dist/reality/resource/SpatialTextureResource.js.map +1 -0
- package/dist/reality/resource/index.d.ts +9 -0
- package/dist/reality/resource/index.js +3 -0
- package/dist/reality/resource/index.js.map +1 -0
- package/dist/runtime/WebSpatialRuntimeError.d.ts +10 -0
- package/dist/runtime/WebSpatialRuntimeError.js +14 -0
- package/dist/runtime/WebSpatialRuntimeError.js.map +1 -0
- package/dist/runtime/capability-data.d.ts +12 -0
- package/dist/runtime/capability-data.js +134 -0
- package/dist/runtime/capability-data.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.js +27 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/jsbAdapterPlatform.d.ts +9 -0
- package/dist/runtime/jsbAdapterPlatform.js +38 -0
- package/dist/runtime/jsbAdapterPlatform.js.map +1 -0
- package/dist/runtime/keys.d.ts +34 -0
- package/dist/runtime/keys.js +122 -0
- package/dist/runtime/keys.js.map +1 -0
- package/dist/runtime/semver.d.ts +8 -0
- package/dist/runtime/semver.js +32 -0
- package/dist/runtime/semver.js.map +1 -0
- package/dist/runtime/supports.d.ts +22 -0
- package/dist/runtime/supports.js +78 -0
- package/dist/runtime/supports.js.map +1 -0
- package/dist/runtime/types.d.ts +12 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/userAgent.d.ts +20 -0
- package/dist/runtime/userAgent.js +41 -0
- package/dist/runtime/userAgent.js.map +1 -0
- package/dist/scene-polyfill.d.ts +18 -0
- package/dist/scene-polyfill.js +480 -0
- package/dist/scene-polyfill.js.map +1 -0
- package/dist/spatial-host.d.ts +13 -0
- package/dist/spatial-host.js +18 -0
- package/dist/spatial-host.js.map +1 -0
- package/dist/spatial-window-polyfill.d.ts +3 -0
- package/dist/spatial-window-polyfill.js +155 -0
- package/dist/spatial-window-polyfill.js.map +1 -0
- package/dist/spatializedElementMotion-_0XWPQCE.d.ts +1009 -0
- package/dist/types/animation.d.ts +7 -0
- package/dist/types/animation.js +1 -0
- package/dist/types/animation.js.map +1 -0
- package/dist/types/global.d.ts +38 -0
- package/dist/types/global.js +1 -0
- package/dist/types/global.js.map +1 -0
- package/dist/types/internal.d.ts +7 -0
- package/dist/types/internal.js +12 -0
- package/dist/types/internal.js.map +1 -0
- package/dist/types/motion/index.d.ts +7 -0
- package/dist/types/motion/index.js +3 -0
- package/dist/types/motion/index.js.map +1 -0
- package/dist/types/motion/spatializedElementMotion.d.ts +7 -0
- package/dist/types/motion/spatializedElementMotion.js +1 -0
- package/dist/types/motion/spatializedElementMotion.js.map +1 -0
- package/dist/types/motion/spatializedMotion.d.ts +7 -0
- package/dist/types/motion/spatializedMotion.js +16 -0
- package/dist/types/motion/spatializedMotion.js.map +1 -0
- package/dist/types/motion/spatializedPlayback.d.ts +11 -0
- package/dist/types/motion/spatializedPlayback.js +1 -0
- package/dist/types/motion/spatializedPlayback.js.map +1 -0
- package/dist/types/motion/spatializedVisual.d.ts +35 -0
- package/dist/types/motion/spatializedVisual.js +1 -0
- package/dist/types/motion/spatializedVisual.js.map +1 -0
- package/dist/types/types.d.ts +7 -0
- package/dist/types/types.js +117 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils.d.ts +44 -0
- package/dist/utils.js +86 -0
- package/dist/utils.js.map +1 -0
- package/package.json +20 -4
- package/src/JSBCommand.ts +148 -91
- package/src/Spatial.ts +0 -21
- package/src/SpatialObject.ts +10 -0
- package/src/SpatialScene.ts +1 -5
- package/src/SpatialSession.ts +17 -3
- package/src/Spatialized2DElement.ts +5 -0
- package/src/SpatializedDynamic3DElement.ts +5 -1
- package/src/SpatializedElement.ts +29 -0
- package/src/SpatializedElementCreator.ts +6 -4
- package/src/SpatializedStatic3DElement.test.ts +99 -0
- package/src/SpatializedStatic3DElement.ts +141 -4
- package/src/WebMsgCommand.ts +50 -0
- package/src/coverage-boost.test.ts +258 -316
- package/src/index.ts +28 -12
- package/src/install-polyfills.ts +38 -0
- package/src/jsbcommand.coverage.test.ts +42 -48
- package/src/motion/AnimationObject.test.ts +421 -0
- package/src/motion/AnimationObject.ts +208 -0
- package/src/motion/compute/index.ts +10 -0
- package/src/motion/compute/motionPropertyValues.test.ts +55 -0
- package/src/motion/compute/motionPropertyValues.ts +70 -0
- package/src/motion/compute/normalize.test.ts +99 -0
- package/src/motion/compute/normalize.ts +289 -0
- package/src/motion/compute/validate.test.ts +229 -0
- package/src/motion/compute/validate.ts +156 -0
- package/src/motion/index.ts +2 -0
- package/src/motion/native/serializeMotionTimeline.test.ts +61 -0
- package/src/motion/native/serializeMotionTimeline.ts +27 -0
- package/src/platform-adapter/CommandResultUtils.ts +2 -2
- package/src/platform-adapter/createPlatformSync.ts +36 -0
- package/src/platform-adapter/index.ts +5 -51
- package/src/platform-adapter/interface.ts +35 -23
- package/src/platform-adapter/pico-os/PicoOSPlatform.ts +156 -59
- package/src/platform-adapter/puppeteer/PuppeteerPlatform.ts +37 -11
- package/src/platform-adapter/spatialRequestMetadata.test.ts +175 -0
- package/src/platform-adapter/spatialRequestMetadata.ts +48 -0
- package/src/platform-adapter/spatialSceneQuery.ts +17 -0
- package/src/platform-adapter/vision-os/VisionOSPlatform.ts +60 -24
- package/src/platform-runtime.ts +13 -0
- package/src/reality/Attachment.ts +2 -2
- package/src/reality/entity/SpatialEntity.ts +127 -2
- package/src/reality/realityCreator.ts +15 -1
- package/src/reality/resource/SpatialTextureResource.ts +16 -0
- package/src/reality/resource/index.ts +1 -0
- package/src/runtime/WebSpatialRuntimeError.ts +16 -0
- package/src/runtime/capability-data.ts +213 -0
- package/src/runtime/contract-review.test.ts +44 -0
- package/src/runtime/index.ts +17 -0
- package/src/runtime/jsbAdapterPlatform.test.ts +36 -0
- package/src/runtime/jsbAdapterPlatform.ts +51 -0
- package/src/runtime/keys.ts +140 -0
- package/src/runtime/semver.ts +33 -0
- package/src/runtime/supports.test.ts +346 -0
- package/src/runtime/supports.ts +112 -0
- package/src/runtime/types.ts +11 -0
- package/src/runtime/useAnimation.capability.test.ts +275 -0
- package/src/runtime/userAgent.ts +64 -0
- package/src/scene-polyfill.manifest.test.ts +312 -9
- package/src/scene-polyfill.request-metadata.test.ts +39 -0
- package/src/scene-polyfill.test.ts +33 -94
- package/src/scene-polyfill.ts +125 -92
- package/src/spatial-host.ts +25 -0
- package/src/spatial-window-polyfill.ts +18 -2
- package/src/transform-roundtrip.test.ts +90 -0
- package/src/types/animation.ts +224 -0
- package/src/types/{global.d.ts → global.ts} +10 -12
- package/src/types/motion/index.ts +10 -0
- package/src/types/motion/spatializedElementMotion.ts +49 -0
- package/src/types/motion/spatializedMotion.ts +147 -0
- package/src/types/motion/spatializedPlayback.ts +17 -0
- package/src/types/motion/spatializedVisual.ts +24 -0
- package/src/types/types.ts +12 -0
- package/src/utils.ts +54 -0
- package/tsup.config.ts +61 -36
- package/vitest.config.ts +5 -1
- package/dist/iife/index.d.ts +0 -1101
- package/dist/iife/index.global.js +0 -75
- package/dist/iife/index.global.js.map +0 -1
- package/src/platform-adapter/android/AndroidPlatform.ts +0 -133
- package/src/platform-adapter/ssr/SSRPlatform.ts +0 -43
- /package/src/{ssr-polyfill.ts → isSSREnv.ts} +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Versioned capability rows transcribed from the product matrix (`capability-matrix.template.md`).
|
|
3
|
+
* visionOS **WSAppShell/1.5.0** & **1.6.0** & **1.7.0** & **1.8.0**; picoOS **PicoWebApp/0.1.1** & **0.1.2** & **0.2.2** & **0.3.1** & **0.4.90** — see matrix in OpenSpec / product docs.
|
|
4
|
+
*
|
|
5
|
+
* **picoOS** rows use dedicated builders (alpha2.0 / alpha2.1 subtokens); visionOS rows are separate.
|
|
6
|
+
*/
|
|
7
|
+
import { SUB_TOKENS_BY_NAME, TOP_LEVEL_KEYS } from './keys'
|
|
8
|
+
|
|
9
|
+
export type CapabilityVersionRow = {
|
|
10
|
+
/** Semver string from `WSAppShell` / `PicoWebApp` (see `review.md` §4). */
|
|
11
|
+
version: string
|
|
12
|
+
/** Top-level keys and `name:subToken` compound keys. */
|
|
13
|
+
flags: Record<string, boolean>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function baseTrueFlags(): Record<string, boolean> {
|
|
17
|
+
const flags: Record<string, boolean> = {}
|
|
18
|
+
for (const k of TOP_LEVEL_KEYS) {
|
|
19
|
+
flags[k] = true
|
|
20
|
+
}
|
|
21
|
+
for (const [name, toks] of Object.entries(SUB_TOKENS_BY_NAME)) {
|
|
22
|
+
for (const t of toks) {
|
|
23
|
+
flags[`${name}:${t}`] = true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return flags
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* visionOS **WSAppShell/1.5.0**.
|
|
31
|
+
* Model: only `ready`, `currentSrc`, `entityTransform` among tracked sub-tokens are Y; SpatialRotateEvent:constrainedToAxis Y.
|
|
32
|
+
*/
|
|
33
|
+
function matrixVision_1_5_0_Flags(): Record<string, boolean> {
|
|
34
|
+
const flags = baseTrueFlags()
|
|
35
|
+
const modelNo = [
|
|
36
|
+
'autoplay',
|
|
37
|
+
'loop',
|
|
38
|
+
'stagemode',
|
|
39
|
+
'poster',
|
|
40
|
+
'loading',
|
|
41
|
+
'source',
|
|
42
|
+
'paused',
|
|
43
|
+
'duration',
|
|
44
|
+
'playbackRate',
|
|
45
|
+
'play',
|
|
46
|
+
'pause',
|
|
47
|
+
'currentTime',
|
|
48
|
+
] as const
|
|
49
|
+
for (const t of modelNo) {
|
|
50
|
+
flags[`Model:${t}`] = false
|
|
51
|
+
}
|
|
52
|
+
flags['SpatialRotateEvent:constrainedToAxis'] = true
|
|
53
|
+
// Container useAnimation is not supported until WSAppShell/1.8.0.
|
|
54
|
+
flags['useAnimation'] = false
|
|
55
|
+
// Placement-shaped attachment protocol lands in picoOS PicoWebApp/0.4.90
|
|
56
|
+
// (OTA0); no visionOS shell decodes it yet.
|
|
57
|
+
flags['AttachmentEntity:placement'] = false
|
|
58
|
+
return flags
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* visionOS **WSAppShell/1.6.0** — WebSpatial April / playback expansion (see product matrix).
|
|
63
|
+
* Model: `stagemode`, `poster`, `loading`, `currentTime` remain N; rest of tracked Model sub-tokens Y.
|
|
64
|
+
*/
|
|
65
|
+
function matrixVision_1_6_0_Flags(): Record<string, boolean> {
|
|
66
|
+
const flags = baseTrueFlags()
|
|
67
|
+
for (const t of ['stagemode', 'poster', 'loading', 'currentTime'] as const) {
|
|
68
|
+
flags[`Model:${t}`] = false
|
|
69
|
+
}
|
|
70
|
+
flags['SpatialRotateEvent:constrainedToAxis'] = true
|
|
71
|
+
// Container useAnimation is not supported until WSAppShell/1.8.0.
|
|
72
|
+
flags['useAnimation'] = false
|
|
73
|
+
// Placement-shaped attachment protocol lands in picoOS PicoWebApp/0.4.90
|
|
74
|
+
// (OTA0); no visionOS shell decodes it yet.
|
|
75
|
+
flags['AttachmentEntity:placement'] = false
|
|
76
|
+
return flags
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* visionOS **WSAppShell/1.7.0** — entity transform animation support.
|
|
81
|
+
* Container `useAnimation` remains unavailable in this row.
|
|
82
|
+
*/
|
|
83
|
+
function matrixVision_1_7_0_Flags(): Record<string, boolean> {
|
|
84
|
+
const flags = matrixVision_1_6_0_Flags()
|
|
85
|
+
flags['Model:currentTime'] = true
|
|
86
|
+
flags['Model:loading'] = true
|
|
87
|
+
flags['Model:poster'] = true
|
|
88
|
+
return flags
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* visionOS **WSAppShell/1.8.0**.
|
|
93
|
+
*/
|
|
94
|
+
function matrixVision_1_8_0_Flags(): Record<string, boolean> {
|
|
95
|
+
const flags = matrixVision_1_7_0_Flags()
|
|
96
|
+
flags['useAnimation'] = true
|
|
97
|
+
return flags
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* picoOS **PicoWebApp/0.1.1** — alpha2.0 baseline (product matrix).
|
|
102
|
+
* WindowScene / VolumeScene / Material subtokens Y; Model sub-tokens per matrix; **`xrInnerDepth` / `xrOuterDepth` N**.
|
|
103
|
+
*/
|
|
104
|
+
function matrixPico_0_1_1_Flags(): Record<string, boolean> {
|
|
105
|
+
const flags = matrixVision_1_5_0_Flags()
|
|
106
|
+
flags.xrInnerDepth = false
|
|
107
|
+
flags.xrOuterDepth = false
|
|
108
|
+
return flags
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* picoOS **PicoWebApp/0.1.2** — beta2.0 playback expansion (product matrix).
|
|
113
|
+
* **`xrInnerDepth` / `xrOuterDepth` N** (same as 0.1.1).
|
|
114
|
+
*/
|
|
115
|
+
function matrixPico_0_1_2_Flags(): Record<string, boolean> {
|
|
116
|
+
const flags = matrixVision_1_6_0_Flags()
|
|
117
|
+
flags.xrInnerDepth = false
|
|
118
|
+
flags.xrOuterDepth = false
|
|
119
|
+
flags['Model:currentTime'] = true
|
|
120
|
+
flags['Model:poster'] = true
|
|
121
|
+
return flags
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* picoOS **PicoWebApp/0.2.2** — entity transform animation support.
|
|
126
|
+
* Container `useAnimation` remains unavailable in this row.
|
|
127
|
+
*/
|
|
128
|
+
function matrixPico_0_2_2_Flags(): Record<string, boolean> {
|
|
129
|
+
const flags = matrixPico_0_1_2_Flags()
|
|
130
|
+
return flags
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* picoOS **PicoWebApp/0.3.1** — beta2.1
|
|
135
|
+
*/
|
|
136
|
+
function matrixPico_0_3_1_Flags(): Record<string, boolean> {
|
|
137
|
+
const flags = matrixPico_0_2_2_Flags()
|
|
138
|
+
flags['Model:loading'] = true
|
|
139
|
+
return flags
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* picoOS **PicoWebApp/0.4.90** — OTA0 container animation support.
|
|
144
|
+
*/
|
|
145
|
+
function matrixPico_0_4_90_Flags(): Record<string, boolean> {
|
|
146
|
+
const flags = matrixPico_0_3_1_Flags()
|
|
147
|
+
flags['useAnimation'] = true
|
|
148
|
+
flags['AttachmentEntity:placement'] = true
|
|
149
|
+
return flags
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function visionOsRow_1_5_0(): CapabilityVersionRow {
|
|
153
|
+
return { version: '1.5.0', flags: matrixVision_1_5_0_Flags() }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function visionOsRow_1_6_0(): CapabilityVersionRow {
|
|
157
|
+
return { version: '1.6.0', flags: matrixVision_1_6_0_Flags() }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function visionOsRow_1_7_0(): CapabilityVersionRow {
|
|
161
|
+
return { version: '1.7.0', flags: matrixVision_1_7_0_Flags() }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Build the capability row for visionOS **WSAppShell/1.8.0**.
|
|
166
|
+
*/
|
|
167
|
+
function visionOsRow_1_8_0(): CapabilityVersionRow {
|
|
168
|
+
return { version: '1.8.0', flags: matrixVision_1_8_0_Flags() }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function picoOsRow_0_1_1(): CapabilityVersionRow {
|
|
172
|
+
return { version: '0.1.1', flags: matrixPico_0_1_1_Flags() }
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Pico OS 6.0 Beta 2.0
|
|
176
|
+
function picoOsRow_0_1_2(): CapabilityVersionRow {
|
|
177
|
+
return { version: '0.1.2', flags: matrixPico_0_1_2_Flags() }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function picoOsRow_0_2_2(): CapabilityVersionRow {
|
|
181
|
+
return { version: '0.2.2', flags: matrixPico_0_2_2_Flags() }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Pico OS 6.0 Beta 2.1
|
|
185
|
+
function picoOsRow_0_3_1(): CapabilityVersionRow {
|
|
186
|
+
return { version: '0.3.1', flags: matrixPico_0_3_1_Flags() }
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Build the capability row for picoOS **PicoWebApp/0.4.90** OTA0.
|
|
191
|
+
*/
|
|
192
|
+
function picoOsRow_0_4_90(): CapabilityVersionRow {
|
|
193
|
+
return { version: '0.4.90', flags: matrixPico_0_4_90_Flags() }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const CAPABILITY_TABLE: {
|
|
197
|
+
visionos: CapabilityVersionRow[]
|
|
198
|
+
picoos: CapabilityVersionRow[]
|
|
199
|
+
} = {
|
|
200
|
+
visionos: [
|
|
201
|
+
visionOsRow_1_5_0(),
|
|
202
|
+
visionOsRow_1_6_0(),
|
|
203
|
+
visionOsRow_1_7_0(),
|
|
204
|
+
visionOsRow_1_8_0(),
|
|
205
|
+
],
|
|
206
|
+
picoos: [
|
|
207
|
+
picoOsRow_0_1_1(),
|
|
208
|
+
picoOsRow_0_1_2(),
|
|
209
|
+
picoOsRow_0_2_2(),
|
|
210
|
+
picoOsRow_0_3_1(),
|
|
211
|
+
picoOsRow_0_4_90(),
|
|
212
|
+
],
|
|
213
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, expect, test, vi, beforeEach } from 'vitest'
|
|
2
|
+
import { ELEMENT_DOM_DEPTH_KEYS, WINDOW_DOM_DEPTH_KEYS } from './keys'
|
|
3
|
+
|
|
4
|
+
describe('OpenSpec review.md §3.5.1 — Window DOM depth (xrInnerDepth / xrOuterDepth)', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
vi.resetModules()
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('plain browser UA: unsupported keys absent from window surface', async () => {
|
|
10
|
+
vi.stubGlobal('navigator', {
|
|
11
|
+
userAgent:
|
|
12
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
|
|
13
|
+
} as Navigator)
|
|
14
|
+
const { supports, resetRuntimeCacheForTests } = await import('./supports')
|
|
15
|
+
resetRuntimeCacheForTests()
|
|
16
|
+
|
|
17
|
+
for (const key of WINDOW_DOM_DEPTH_KEYS) {
|
|
18
|
+
expect(supports(key)).toBe(false)
|
|
19
|
+
expect(key in window).toBe(false)
|
|
20
|
+
expect(Object.prototype.hasOwnProperty.call(window, key)).toBe(false)
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('OpenSpec review.md §3.5.2 — Element depth keys must not use Window surface', () => {
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
vi.resetModules()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('plain browser: xrClientDepth / xrOffsetBack are not on window (live on spatialized ref)', async () => {
|
|
31
|
+
vi.stubGlobal('navigator', {
|
|
32
|
+
userAgent:
|
|
33
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
|
|
34
|
+
} as Navigator)
|
|
35
|
+
const { supports, resetRuntimeCacheForTests } = await import('./supports')
|
|
36
|
+
resetRuntimeCacheForTests()
|
|
37
|
+
|
|
38
|
+
for (const key of ELEMENT_DOM_DEPTH_KEYS) {
|
|
39
|
+
expect(supports(key)).toBe(false)
|
|
40
|
+
expect(key in window).toBe(false)
|
|
41
|
+
expect(Object.prototype.hasOwnProperty.call(window, key)).toBe(false)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type { WebSpatialRuntimeSnapshot, WebSpatialRuntimeType } from './types'
|
|
2
|
+
export { WebSpatialRuntimeError } from './WebSpatialRuntimeError'
|
|
3
|
+
export {
|
|
4
|
+
supports,
|
|
5
|
+
getRuntime,
|
|
6
|
+
resetRuntimeCacheForTests,
|
|
7
|
+
VISIONOS_DEBUG_SHELL_VERSION_PLACEHOLDER,
|
|
8
|
+
} from './supports'
|
|
9
|
+
export { compareSemver, parseSemverOrNull } from './semver'
|
|
10
|
+
export { computeRuntimeFromUserAgent, parseShellToken } from './userAgent'
|
|
11
|
+
export {
|
|
12
|
+
resolveJsbAdapterPlatform,
|
|
13
|
+
type JsbAdapterPlatformKind,
|
|
14
|
+
} from './jsbAdapterPlatform'
|
|
15
|
+
export type { CapabilityVersionRow } from './capability-data'
|
|
16
|
+
export { CAPABILITY_TABLE } from './capability-data'
|
|
17
|
+
export type { CapabilityKey } from './keys'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest'
|
|
2
|
+
import { resolveJsbAdapterPlatform } from './jsbAdapterPlatform'
|
|
3
|
+
|
|
4
|
+
describe('resolveJsbAdapterPlatform', () => {
|
|
5
|
+
test('Puppeteer UA maps to puppeteer', () => {
|
|
6
|
+
expect(
|
|
7
|
+
resolveJsbAdapterPlatform(
|
|
8
|
+
'Mozilla/5.0 Puppeteer Chrome/120 WSAppShell/1.5.0 WebSpatial/1.5.0',
|
|
9
|
+
),
|
|
10
|
+
).toBe('puppeteer')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
test('PicoWebApp with WebSpatial > 0.0.1 maps to picoos', () => {
|
|
14
|
+
expect(
|
|
15
|
+
resolveJsbAdapterPlatform(
|
|
16
|
+
'Mozilla/5.0 PicoWebApp/0.1.1 WebSpatial/1.5.0',
|
|
17
|
+
),
|
|
18
|
+
).toBe('picoos')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('Linux without Pico pico branch maps to visionos', () => {
|
|
22
|
+
expect(
|
|
23
|
+
resolveJsbAdapterPlatform(
|
|
24
|
+
'Mozilla/5.0 (X11; Linux x86_64) WSAppShell/1.5.0 WebSpatial/1.5.0',
|
|
25
|
+
),
|
|
26
|
+
).toBe('visionos')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('Mac visionOS-class UA maps to visionos', () => {
|
|
30
|
+
expect(
|
|
31
|
+
resolveJsbAdapterPlatform(
|
|
32
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) WSAppShell/1.5.0 WebSpatial/1.5.0',
|
|
33
|
+
),
|
|
34
|
+
).toBe('visionos')
|
|
35
|
+
})
|
|
36
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { computeRuntimeFromUserAgent } from './userAgent'
|
|
2
|
+
|
|
3
|
+
function getWebSpatialVersion(ua: string): number[] | null {
|
|
4
|
+
const match = ua.match(/WebSpatial\/(\d+)\.(\d+)\.(\d+)/)
|
|
5
|
+
if (!match) {
|
|
6
|
+
return null
|
|
7
|
+
}
|
|
8
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function isVersionGreater(a: number[] | null, b: number[]): boolean {
|
|
12
|
+
if (!a) {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
for (let index = 0; index < 3; index += 1) {
|
|
16
|
+
const diff = a[index] - b[index]
|
|
17
|
+
if (diff > 0) {
|
|
18
|
+
return true
|
|
19
|
+
}
|
|
20
|
+
if (diff < 0) {
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Which native JSB / protocol adapter to load in the browser.
|
|
29
|
+
* Derived from {@link computeRuntimeFromUserAgent} plus legacy fallbacks
|
|
30
|
+
* (Pico WebSpatial semver gate; otherwise default visionOS shell).
|
|
31
|
+
*/
|
|
32
|
+
export type JsbAdapterPlatformKind = 'puppeteer' | 'picoos' | 'visionos'
|
|
33
|
+
|
|
34
|
+
export function resolveJsbAdapterPlatform(
|
|
35
|
+
userAgent: string,
|
|
36
|
+
): JsbAdapterPlatformKind {
|
|
37
|
+
const rt = computeRuntimeFromUserAgent(userAgent)
|
|
38
|
+
if (rt.type === 'puppeteer') {
|
|
39
|
+
return 'puppeteer'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const webSpatialVersion = getWebSpatialVersion(userAgent)
|
|
43
|
+
if (
|
|
44
|
+
userAgent.includes('PicoWebApp') &&
|
|
45
|
+
isVersionGreater(webSpatialVersion, [0, 0, 1])
|
|
46
|
+
) {
|
|
47
|
+
return 'picoos'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return 'visionos'
|
|
51
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical `supports(name)` key registry (OpenSpec `review.md` §3).
|
|
3
|
+
* Aliases are normalized before lookup (see `normalizeCapabilityName`).
|
|
4
|
+
*
|
|
5
|
+
* @internal SDK contract data — not part of the public `@webspatial/react-sdk`
|
|
6
|
+
* surface. Import via `@webspatial/core-sdk/runtime/keys` only for SDK demos,
|
|
7
|
+
* contract tests, and capability-matrix tooling.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const COMPONENT_KEYS = [
|
|
11
|
+
'Model',
|
|
12
|
+
'Reality',
|
|
13
|
+
'Entity',
|
|
14
|
+
'BoxEntity',
|
|
15
|
+
'SphereEntity',
|
|
16
|
+
'ConeEntity',
|
|
17
|
+
'CylinderEntity',
|
|
18
|
+
'PlaneEntity',
|
|
19
|
+
'SceneGraph',
|
|
20
|
+
'ModelAsset',
|
|
21
|
+
'ModelEntity',
|
|
22
|
+
'UnlitMaterial',
|
|
23
|
+
'Material',
|
|
24
|
+
'AttachmentAsset',
|
|
25
|
+
'AttachmentEntity',
|
|
26
|
+
] as const
|
|
27
|
+
|
|
28
|
+
export const CSS_KEYS = [
|
|
29
|
+
'-xr-background-material',
|
|
30
|
+
'-xr-back',
|
|
31
|
+
'-xr-depth',
|
|
32
|
+
'-xr-transform',
|
|
33
|
+
] as const
|
|
34
|
+
|
|
35
|
+
export const GESTURE_KEYS = [
|
|
36
|
+
'SpatialTapEvent',
|
|
37
|
+
'SpatialDragStartEvent',
|
|
38
|
+
'SpatialDragEvent',
|
|
39
|
+
'SpatialDragEndEvent',
|
|
40
|
+
'SpatialRotateEvent',
|
|
41
|
+
'SpatialRotateEndEvent',
|
|
42
|
+
'SpatialMagnifyEvent',
|
|
43
|
+
'SpatialMagnifyEndEvent',
|
|
44
|
+
] as const
|
|
45
|
+
|
|
46
|
+
export const ANIMATION_KEYS = ['useAnimation'] as const
|
|
47
|
+
|
|
48
|
+
export const JS_SCENE_KEYS = [
|
|
49
|
+
'useMetrics',
|
|
50
|
+
'convertCoordinate',
|
|
51
|
+
'initScene',
|
|
52
|
+
'WindowScene',
|
|
53
|
+
'VolumeScene',
|
|
54
|
+
] as const
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Spatialized container `ref` readbacks (`HTMLElement` / React `useDomProxy` Proxy).
|
|
58
|
+
* See `global.d.ts` (`HTMLElement`) and `useDomProxy.ts` (`has` / `get` traps).
|
|
59
|
+
*/
|
|
60
|
+
export const ELEMENT_DOM_DEPTH_KEYS = ['xrClientDepth', 'xrOffsetBack'] as const
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Scene / global readbacks on `Window` (`global.d.ts` → `Window`).
|
|
64
|
+
*/
|
|
65
|
+
export const WINDOW_DOM_DEPTH_KEYS = ['xrInnerDepth', 'xrOuterDepth'] as const
|
|
66
|
+
|
|
67
|
+
export const DOM_DEPTH_KEYS = [
|
|
68
|
+
...ELEMENT_DOM_DEPTH_KEYS,
|
|
69
|
+
...WINDOW_DOM_DEPTH_KEYS,
|
|
70
|
+
] as const
|
|
71
|
+
|
|
72
|
+
/** Top-level names accepted by `supports(name)` (canonical keys after alias normalization). */
|
|
73
|
+
export const TOP_LEVEL_KEYS = [
|
|
74
|
+
...COMPONENT_KEYS,
|
|
75
|
+
...CSS_KEYS,
|
|
76
|
+
...GESTURE_KEYS,
|
|
77
|
+
...ANIMATION_KEYS,
|
|
78
|
+
...JS_SCENE_KEYS,
|
|
79
|
+
...DOM_DEPTH_KEYS,
|
|
80
|
+
] as const
|
|
81
|
+
|
|
82
|
+
/** Union of documented capability keys; unknown strings may still be passed to `supports` (returns `false`). */
|
|
83
|
+
export type CapabilityKey = (typeof TOP_LEVEL_KEYS)[number]
|
|
84
|
+
|
|
85
|
+
const ALIAS_TO_CANONICAL: Record<string, string> = {
|
|
86
|
+
Box: 'BoxEntity',
|
|
87
|
+
Sphere: 'SphereEntity',
|
|
88
|
+
Cone: 'ConeEntity',
|
|
89
|
+
Cylinder: 'CylinderEntity',
|
|
90
|
+
Plane: 'PlaneEntity',
|
|
91
|
+
World: 'SceneGraph',
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function normalizeCapabilityName(name: string): string {
|
|
95
|
+
return ALIAS_TO_CANONICAL[name] ?? name
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Known sub-tokens per canonical top-level `name` (AND semantics). */
|
|
99
|
+
export const SUB_TOKENS_BY_NAME: Readonly<Record<string, readonly string[]>> = {
|
|
100
|
+
Material: ['unlit'],
|
|
101
|
+
WindowScene: ['defaultSize', 'resizability'],
|
|
102
|
+
VolumeScene: [
|
|
103
|
+
'defaultSize',
|
|
104
|
+
'resizability',
|
|
105
|
+
'worldScaling',
|
|
106
|
+
'worldAlignment',
|
|
107
|
+
'baseplateVisibility',
|
|
108
|
+
],
|
|
109
|
+
SpatialRotateEvent: ['constrainedToAxis'],
|
|
110
|
+
// Placement-shaped attachment JSB protocol (placementId + Vec3 transform +
|
|
111
|
+
// meter width/height). Runtimes without it take the legacy payload
|
|
112
|
+
// (parentEntityId + tuple position + point size).
|
|
113
|
+
AttachmentEntity: ['placement'],
|
|
114
|
+
Model: [
|
|
115
|
+
'autoplay',
|
|
116
|
+
'loop',
|
|
117
|
+
'stagemode',
|
|
118
|
+
'poster',
|
|
119
|
+
'loading',
|
|
120
|
+
'source',
|
|
121
|
+
'ready',
|
|
122
|
+
'currentSrc',
|
|
123
|
+
'entityTransform',
|
|
124
|
+
'paused',
|
|
125
|
+
'duration',
|
|
126
|
+
'playbackRate',
|
|
127
|
+
'play',
|
|
128
|
+
'pause',
|
|
129
|
+
'currentTime',
|
|
130
|
+
],
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function isKnownTopLevel(name: string): boolean {
|
|
134
|
+
return (TOP_LEVEL_KEYS as readonly string[]).includes(name)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function isKnownSubToken(name: string, token: string): boolean {
|
|
138
|
+
const allowed = SUB_TOKENS_BY_NAME[name]
|
|
139
|
+
return allowed !== undefined && allowed.includes(token)
|
|
140
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal semver compare for capability table rows (`major.minor.patch`).
|
|
3
|
+
* Returns negative if a < b, zero if equal, positive if a > b.
|
|
4
|
+
*/
|
|
5
|
+
export function compareSemver(a: string, b: string): number {
|
|
6
|
+
const pa = parseSemverParts(a)
|
|
7
|
+
const pb = parseSemverParts(b)
|
|
8
|
+
if (!pa || !pb) {
|
|
9
|
+
return String(a).localeCompare(String(b))
|
|
10
|
+
}
|
|
11
|
+
const len = Math.max(pa.length, pb.length)
|
|
12
|
+
for (let i = 0; i < len; i++) {
|
|
13
|
+
const da = pa[i] ?? 0
|
|
14
|
+
const db = pb[i] ?? 0
|
|
15
|
+
if (da !== db) return da - db
|
|
16
|
+
}
|
|
17
|
+
return 0
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseSemverParts(v: string): number[] | null {
|
|
21
|
+
const m = /^(\d+)(?:\.(\d+)(?:\.(\d+))?)?/.exec(v.trim())
|
|
22
|
+
if (!m) return null
|
|
23
|
+
const major = Number(m[1])
|
|
24
|
+
const minor = m[2] !== undefined ? Number(m[2]) : 0
|
|
25
|
+
const patch = m[3] !== undefined ? Number(m[3]) : 0
|
|
26
|
+
if ([major, minor, patch].some(n => Number.isNaN(n))) return null
|
|
27
|
+
return [major, minor, patch]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function parseSemverOrNull(v: string): string | null {
|
|
31
|
+
const m = /^(\d+(?:\.\d+){0,2})/.exec(v.trim())
|
|
32
|
+
return m ? m[1] : null
|
|
33
|
+
}
|