lecodes-cli 0.19.0 → 0.20.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 (270) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +1069 -396
  3. package/package.json +14 -13
  4. package/runtime/scene-harness.json +1 -1
  5. package/runtime/sdk-types.json +1 -1
  6. package/runtime/web/assets/Roboto-Variable-DHm9jpd-.woff2 +0 -0
  7. package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  8. package/runtime/web/assets/basis-C64VHDVD.js +1 -0
  9. package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
  10. package/runtime/web/assets/createViewerLite-BvHobVhp.js +852 -0
  11. package/runtime/web/assets/draco-BiISTFcR.js +118 -0
  12. package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
  13. package/runtime/web/assets/index-CfNCCBjN.js +2 -0
  14. package/runtime/web/assets/mapViewImpl-B2JcES8l.js +810 -0
  15. package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +8 -0
  16. package/runtime/web/assets/neutral_ibl128-D-lzdkLN.ktx +0 -0
  17. package/runtime/web/assets/worker-Caf-yYEI.js +2 -0
  18. package/runtime/web/embed.html +32 -0
  19. package/runtime/web/embed.js +171 -0
  20. package/src/api.ts +302 -0
  21. package/src/browserAuth.ts +87 -0
  22. package/src/cmgenTool.ts +104 -0
  23. package/src/commands/app.ts +896 -0
  24. package/src/commands/appAndroid.ts +603 -0
  25. package/src/commands/appDesktop.ts +339 -0
  26. package/src/commands/appDesktopMac.ts +470 -0
  27. package/src/commands/appIcon.ts +187 -0
  28. package/src/commands/appShared.ts +542 -0
  29. package/src/commands/appTemplates.ts +907 -0
  30. package/src/commands/appTemplatesAndroid.ts +599 -0
  31. package/src/commands/appTemplatesGradlew.ts +9 -0
  32. package/src/commands/assets.ts +28 -0
  33. package/src/commands/clone.ts +60 -0
  34. package/src/commands/compile.ts +253 -0
  35. package/src/commands/create.ts +59 -0
  36. package/src/commands/design.ts +863 -0
  37. package/src/commands/designTemplates.ts +11 -0
  38. package/src/commands/desktop.ts +127 -0
  39. package/src/commands/dev.ts +236 -0
  40. package/src/commands/diff.ts +59 -0
  41. package/src/commands/init.ts +191 -0
  42. package/src/commands/install.ts +198 -0
  43. package/src/commands/lightmap.ts +290 -0
  44. package/src/commands/link.ts +147 -0
  45. package/src/commands/login.ts +24 -0
  46. package/src/commands/navmesh.ts +225 -0
  47. package/src/commands/pn.ts +305 -0
  48. package/src/commands/projectTemplates.ts +130 -0
  49. package/src/commands/pull.ts +109 -0
  50. package/src/commands/push.ts +173 -0
  51. package/src/commands/render.ts +416 -0
  52. package/src/commands/scene.ts +148 -0
  53. package/src/commands/shaders.ts +157 -0
  54. package/src/commands/status.ts +29 -0
  55. package/src/commands/test.ts +371 -0
  56. package/src/commands/thumbs.ts +178 -0
  57. package/src/commands/types.ts +87 -0
  58. package/src/commands/update.ts +190 -0
  59. package/src/compile/assetIcons.ts +214 -0
  60. package/src/compile/collect.ts +46 -0
  61. package/src/compile/collectLocal.ts +37 -0
  62. package/src/compile/designCompile.ts +104 -0
  63. package/src/compile/fonts.ts +156 -0
  64. package/src/compile/headlessBundle.ts +129 -0
  65. package/src/compile/nativeStack.ts +21 -0
  66. package/src/compile/projectCompile.ts +109 -0
  67. package/src/compile/sceneCompile.ts +113 -0
  68. package/src/compile/screenEntry.ts +127 -0
  69. package/src/compile/shaders.ts +245 -0
  70. package/src/config.ts +42 -0
  71. package/src/designMeta.ts +35 -0
  72. package/src/desktopRenderer.ts +545 -0
  73. package/src/desktopScript.ts +276 -0
  74. package/src/dev/clientTemplates.ts +160 -0
  75. package/src/dev/devServer.ts +333 -0
  76. package/src/dev/webRunner.ts +22 -0
  77. package/src/dev/wsServer.ts +144 -0
  78. package/src/distRoot.ts +20 -0
  79. package/src/ignore.ts +163 -0
  80. package/src/index.ts +494 -0
  81. package/src/lecodes-3d-editor.d.ts +41 -0
  82. package/src/lecodes-assets.d.ts +7 -0
  83. package/src/lecodes-design.d.ts +191 -0
  84. package/src/lecodes-renderer.d.ts +131 -0
  85. package/src/localFiles.ts +144 -0
  86. package/src/manifest.ts +46 -0
  87. package/src/matcTool.ts +137 -0
  88. package/src/peers.ts +40 -0
  89. package/src/project.ts +61 -0
  90. package/src/projectEnv.ts +94 -0
  91. package/src/qrcode-terminal.d.ts +9 -0
  92. package/src/releases.ts +125 -0
  93. package/src/serverDiff.ts +78 -0
  94. package/src/textDiff.ts +103 -0
  95. package/src/types.ts +0 -0
  96. package/src/util.ts +146 -0
  97. package/runtime/sdk/animate/animate.ts +0 -238
  98. package/runtime/sdk/animate/bezier.ts +0 -138
  99. package/runtime/sdk/animate/easings.ts +0 -126
  100. package/runtime/sdk/canvas/Canvas.ts +0 -305
  101. package/runtime/sdk/compile/aspectMacro.ts +0 -86
  102. package/runtime/sdk/compile/assetIconMacro.ts +0 -384
  103. package/runtime/sdk/compile/assetMacro.ts +0 -146
  104. package/runtime/sdk/compile/assetName.ts +0 -50
  105. package/runtime/sdk/compile/bundler.ts +0 -287
  106. package/runtime/sdk/compile/compileProject.ts +0 -129
  107. package/runtime/sdk/compile/detectEntry.ts +0 -128
  108. package/runtime/sdk/compile/fontMacro.ts +0 -459
  109. package/runtime/sdk/compile/fontRegistry.ts +0 -78
  110. package/runtime/sdk/compile/header.ts +0 -67
  111. package/runtime/sdk/compile/index.ts +0 -100
  112. package/runtime/sdk/compile/libraryImports.ts +0 -52
  113. package/runtime/sdk/compile/liteMaterial.ts +0 -247
  114. package/runtime/sdk/compile/sceneEditor.ts +0 -88
  115. package/runtime/sdk/compile/serverSplit.ts +0 -233
  116. package/runtime/sdk/compile/serverTypes.ts +0 -227
  117. package/runtime/sdk/compile/sfnt.ts +0 -98
  118. package/runtime/sdk/compile/shaderSchema.ts +0 -202
  119. package/runtime/sdk/compile/shaderTargets.ts +0 -81
  120. package/runtime/sdk/compile/sourcemap.ts +0 -25
  121. package/runtime/sdk/core/Aspect.ts +0 -568
  122. package/runtime/sdk/core/InspectorUI.ts +0 -212
  123. package/runtime/sdk/core/StateMachine.ts +0 -308
  124. package/runtime/sdk/core/color.ts +0 -66
  125. package/runtime/sdk/core/compWrite.ts +0 -42
  126. package/runtime/sdk/core/events.ts +0 -38
  127. package/runtime/sdk/core/fields.ts +0 -120
  128. package/runtime/sdk/core/registry.ts +0 -23
  129. package/runtime/sdk/core/signals.ts +0 -277
  130. package/runtime/sdk/core/time.ts +0 -84
  131. package/runtime/sdk/g2/Camera2D.ts +0 -40
  132. package/runtime/sdk/g2/CharacterController2D.ts +0 -276
  133. package/runtime/sdk/g2/Node2D.ts +0 -267
  134. package/runtime/sdk/g2/OneWay2D.ts +0 -66
  135. package/runtime/sdk/g2/Physics2D.ts +0 -346
  136. package/runtime/sdk/g2/Scene2D.ts +0 -209
  137. package/runtime/sdk/g2/Shape2D.ts +0 -259
  138. package/runtime/sdk/g2/Sprite.ts +0 -89
  139. package/runtime/sdk/g2/SpriteAnimation.ts +0 -171
  140. package/runtime/sdk/g2/SpriteSheet.ts +0 -166
  141. package/runtime/sdk/g2/Texture2D.ts +0 -47
  142. package/runtime/sdk/g2/Tilemap.ts +0 -41
  143. package/runtime/sdk/g2/Tileset.ts +0 -71
  144. package/runtime/sdk/g2/Trigger2D.ts +0 -77
  145. package/runtime/sdk/g2/autotile.ts +0 -433
  146. package/runtime/sdk/g2/cells.ts +0 -91
  147. package/runtime/sdk/g2/defineScene2d.ts +0 -381
  148. package/runtime/sdk/g2/groups2d.ts +0 -106
  149. package/runtime/sdk/g2/loop.ts +0 -50
  150. package/runtime/sdk/g2/scenarios2d.ts +0 -69
  151. package/runtime/sdk/g2/touch.ts +0 -83
  152. package/runtime/sdk/gl/Camera.ts +0 -160
  153. package/runtime/sdk/gl/CameraPlace.ts +0 -52
  154. package/runtime/sdk/gl/CharacterController.ts +0 -238
  155. package/runtime/sdk/gl/Gearbox.ts +0 -212
  156. package/runtime/sdk/gl/Geometry.ts +0 -279
  157. package/runtime/sdk/gl/IK.ts +0 -193
  158. package/runtime/sdk/gl/InstancedMesh.ts +0 -132
  159. package/runtime/sdk/gl/Light.ts +0 -107
  160. package/runtime/sdk/gl/Lightmap.ts +0 -256
  161. package/runtime/sdk/gl/Material.ts +0 -260
  162. package/runtime/sdk/gl/Mesh.ts +0 -83
  163. package/runtime/sdk/gl/Model.ts +0 -124
  164. package/runtime/sdk/gl/NavAgent.ts +0 -337
  165. package/runtime/sdk/gl/NavMesh.ts +0 -397
  166. package/runtime/sdk/gl/Node.ts +0 -350
  167. package/runtime/sdk/gl/Noise.ts +0 -30
  168. package/runtime/sdk/gl/Particles.ts +0 -676
  169. package/runtime/sdk/gl/Physics.ts +0 -222
  170. package/runtime/sdk/gl/Plane.ts +0 -53
  171. package/runtime/sdk/gl/Ragdoll.ts +0 -270
  172. package/runtime/sdk/gl/Ray.ts +0 -16
  173. package/runtime/sdk/gl/Scene.ts +0 -486
  174. package/runtime/sdk/gl/Shape.ts +0 -409
  175. package/runtime/sdk/gl/Terrain.ts +0 -1092
  176. package/runtime/sdk/gl/Texture.ts +0 -63
  177. package/runtime/sdk/gl/Trigger.ts +0 -45
  178. package/runtime/sdk/gl/Vehicle.ts +0 -473
  179. package/runtime/sdk/gl/Wheel.ts +0 -240
  180. package/runtime/sdk/gl/animation/AnimationClip.ts +0 -204
  181. package/runtime/sdk/gl/animation/Animator.ts +0 -120
  182. package/runtime/sdk/gl/animation/Layer.ts +0 -31
  183. package/runtime/sdk/gl/animation/Loop.ts +0 -30
  184. package/runtime/sdk/gl/animation/Playback.ts +0 -44
  185. package/runtime/sdk/gl/animation/core.ts +0 -336
  186. package/runtime/sdk/gl/controls.ts +0 -95
  187. package/runtime/sdk/gl/physicsEvents.ts +0 -20
  188. package/runtime/sdk/gl/scenarios.ts +0 -291
  189. package/runtime/sdk/gl/state.ts +0 -6
  190. package/runtime/sdk/gl/terrainMesh.ts +0 -219
  191. package/runtime/sdk/gl/touch.ts +0 -68
  192. package/runtime/sdk/inject.ts +0 -197
  193. package/runtime/sdk/math/Mathf.ts +0 -118
  194. package/runtime/sdk/math/mat4.ts +0 -278
  195. package/runtime/sdk/math/quat.ts +0 -232
  196. package/runtime/sdk/math/vec.ts +0 -255
  197. package/runtime/sdk/net/codec.ts +0 -119
  198. package/runtime/sdk/net/core.ts +0 -384
  199. package/runtime/sdk/net/index.ts +0 -181
  200. package/runtime/sdk/net/replication.ts +0 -622
  201. package/runtime/sdk/plugins/camera.ts +0 -81
  202. package/runtime/sdk/plugins/geolocation.ts +0 -123
  203. package/runtime/sdk/plugins/oauth.ts +0 -61
  204. package/runtime/sdk/plugins/permission.ts +0 -7
  205. package/runtime/sdk/plugins/push.ts +0 -132
  206. package/runtime/sdk/plugins/qr.ts +0 -73
  207. package/runtime/sdk/plugins/service.ts +0 -47
  208. package/runtime/sdk/runtime/app.ts +0 -101
  209. package/runtime/sdk/runtime/appEvents.ts +0 -54
  210. package/runtime/sdk/runtime/channel.ts +0 -61
  211. package/runtime/sdk/runtime/clipboard.ts +0 -20
  212. package/runtime/sdk/runtime/datetime.ts +0 -329
  213. package/runtime/sdk/runtime/device.ts +0 -293
  214. package/runtime/sdk/runtime/fetch.ts +0 -77
  215. package/runtime/sdk/runtime/files.ts +0 -23
  216. package/runtime/sdk/runtime/input.ts +0 -175
  217. package/runtime/sdk/runtime/media.ts +0 -111
  218. package/runtime/sdk/runtime/misc.ts +0 -16
  219. package/runtime/sdk/runtime/net.ts +0 -36
  220. package/runtime/sdk/runtime/rpc.ts +0 -218
  221. package/runtime/sdk/runtime/service.ts +0 -83
  222. package/runtime/sdk/runtime/share.ts +0 -9
  223. package/runtime/sdk/runtime/storage.ts +0 -13
  224. package/runtime/sdk/runtime/touch.ts +0 -76
  225. package/runtime/sdk/scene/defineScene.ts +0 -1353
  226. package/runtime/sdk/scene/editorPlugins.ts +0 -110
  227. package/runtime/sdk/scene/gizmos.ts +0 -148
  228. package/runtime/sdk/scene/grammar.ts +0 -120
  229. package/runtime/sdk/scene/material.ts +0 -188
  230. package/runtime/sdk/server/auth/appConfig.ts +0 -12
  231. package/runtime/sdk/server/auth/global.ts +0 -80
  232. package/runtime/sdk/server/auth/host.ts +0 -318
  233. package/runtime/sdk/server/auth/models.ts +0 -83
  234. package/runtime/sdk/server/auth/types.ts +0 -50
  235. package/runtime/sdk/server/channel.ts +0 -56
  236. package/runtime/sdk/server/context.ts +0 -36
  237. package/runtime/sdk/server/db/defineDb.ts +0 -237
  238. package/runtime/sdk/server/db/fields.ts +0 -132
  239. package/runtime/sdk/server/db/httpTransport.ts +0 -93
  240. package/runtime/sdk/server/db/index.ts +0 -7
  241. package/runtime/sdk/server/db/marci/query.ts +0 -412
  242. package/runtime/sdk/server/db/types.ts +0 -202
  243. package/runtime/sdk/server/errors.ts +0 -12
  244. package/runtime/sdk/server/host.ts +0 -74
  245. package/runtime/sdk/server/inject.ts +0 -13
  246. package/runtime/sdk/server/runtime.ts +0 -133
  247. package/runtime/sdk/server/validate.ts +0 -87
  248. package/runtime/sdk/ui/NativeView.ts +0 -142
  249. package/runtime/sdk/ui/UI.ts +0 -39
  250. package/runtime/sdk/ui/UIBottomSheet.ts +0 -139
  251. package/runtime/sdk/ui/UIButton.ts +0 -101
  252. package/runtime/sdk/ui/UIContainer.ts +0 -60
  253. package/runtime/sdk/ui/UIImage.ts +0 -83
  254. package/runtime/sdk/ui/UIInput.ts +0 -185
  255. package/runtime/sdk/ui/UIModal.ts +0 -139
  256. package/runtime/sdk/ui/UINode.ts +0 -830
  257. package/runtime/sdk/ui/UIPager.ts +0 -362
  258. package/runtime/sdk/ui/UIPopover.ts +0 -100
  259. package/runtime/sdk/ui/UIScreen.ts +0 -123
  260. package/runtime/sdk/ui/UIScrollable.ts +0 -87
  261. package/runtime/sdk/ui/UISpacer.ts +0 -14
  262. package/runtime/sdk/ui/UITabs.ts +0 -236
  263. package/runtime/sdk/ui/UIText.ts +0 -51
  264. package/runtime/sdk/ui/UIVideo.ts +0 -88
  265. package/runtime/sdk/ui/UIVirtualizedList.ts +0 -241
  266. package/runtime/sdk/ui/UIWidget.ts +0 -127
  267. package/runtime/sdk/ui/fonts.ts +0 -13
  268. package/runtime/sdk/ui/presentable.ts +0 -117
  269. package/runtime/sdk/ui/router.ts +0 -132
  270. package/runtime/sdk/ui/theme.ts +0 -84
@@ -1,16 +0,0 @@
1
- // Small platform globals that are real (not engine-specific). Grown in Phase 1.
2
-
3
- /** Show a transient toast notification. */
4
- export const toast = (msg: string): void => _creatorUI.toast(msg)
5
-
6
- /** Open `url` in the system browser / external handler (fire-and-forget, like `share`). Silent
7
- * no-op on hosts without one (headless). */
8
- export const openURL = (url: string): void => _creatorUtils.openUrl?.(url)
9
-
10
- export type SvgSourceValue = {
11
- readonly svg: string
12
- tintColor: string | null
13
- }
14
-
15
- /** Wrap raw SVG XML so it can be used as an image source. */
16
- export const SvgSource = (svg: string): SvgSourceValue => ({ svg, tintColor: null })
@@ -1,36 +0,0 @@
1
- // WebSocket over the host bridge. Same event surface as the browser's (open/message/close/error)
2
- // via the shared Emitter. Ported from worker/src/WebSocket.ts.
3
-
4
- import { Emitter } from "../core/events"
5
-
6
- type SocketEvents = {
7
- open: () => void
8
- message: (data: any) => void
9
- close: (code?: number) => void
10
- error: () => void
11
- }
12
-
13
- export class WebSocket extends Emitter<SocketEvents> {
14
- private _id: number | null = null
15
-
16
- constructor(url: string, headers?: Record<string, string>) {
17
- super()
18
- this._id = _creatorUtils.websocketOpen(url, (channel, data) => this._onMessage(channel, data), headers)
19
- }
20
-
21
- send(message: string | ArrayBuffer): void {
22
- if (this._id !== null) _creatorUtils.websocketSend(this._id, message)
23
- }
24
-
25
- close(): void {
26
- if (this._id !== null) {
27
- _creatorUtils.websocketClose(this._id)
28
- this._id = null
29
- }
30
- }
31
-
32
- private _onMessage(channel: string, data: any): void {
33
- if (data !== undefined && data !== null) this.dispatch(channel as keyof SocketEvents, data)
34
- else this.dispatch(channel as keyof SocketEvents)
35
- }
36
- }
@@ -1,218 +0,0 @@
1
- /**
2
- * Client transport for the app backend (docs/backend-plan.md §3.2 / §3.3). The compiler replaces
3
- * every `*.server.ts` module in the client bundle with a stub whose exports are built by the three
4
- * globals below — user code never calls them; it imports the server function and calls it.
5
- *
6
- * export const listNotes = __rpc("<serverUrl>", "notes.server.ts#listNotes")
7
- * export const chat = __channel("<serverUrl>", "chat.server.ts#chat")
8
- * export const db = __serverOnly("schema.server.ts#db")
9
- *
10
- * Wire (implemented by the runner):
11
- * POST <serverUrl>/api/<id> body {"args":[…]}, `authorization: Bearer <session>` when known
12
- * → 200 {"ok":true,"result":…,"session"?:"…"} | {"ok":false,"status":n,"message":"…","session"?:"…"}
13
- * WS <serverUrl>/ws frames: → {t:"hello",session} {t:"sub",id,ch,topic} {t:"unsub",id}
14
- * ← {t:"session",session} {t:"ok",id} {t:"err",id,status,message} {t:"ev",ch,topic,event,data}
15
- * (`ev` is addressed by channel + topic, not by subscription id, so the server can fan one publish out
16
- * to every socket of a topic natively; the client delivers it to each matching subscription.)
17
- *
18
- * The session token is transport-owned (cookie-like): stored under `lecodes.session:<serverUrl>` in
19
- * localStorage, sent on every call and on the socket, replaced whenever a response carries `session`.
20
- * User code never sees it — "am I logged in" is an endpoint (`me()`), see the plan.
21
- */
22
-
23
- import { fetch } from "./fetch"
24
- import { localStorage } from "./storage"
25
- import { WebSocket } from "./net"
26
-
27
- /** Rejection value of a failed endpoint call: `status` mirrors the server's `ApiError`
28
- * (0 = the request itself failed: no network / no server). */
29
- export class RpcError extends Error {
30
- readonly status: number
31
- constructor(status: number, message: string) {
32
- super(message)
33
- this.name = "RpcError"
34
- this.status = status
35
- }
36
- }
37
-
38
- // ───────────────────────────── session token ─────────────────────────────
39
-
40
- const sessionKey = (serverUrl: string) => `lecodes.session:${serverUrl}`
41
- const getSession = (serverUrl: string): string | null => {
42
- try { return localStorage.getItem(sessionKey(serverUrl)) } catch { return null }
43
- }
44
- const setSession = (serverUrl: string, token: string | null) => {
45
- try {
46
- if (token) localStorage.setItem(sessionKey(serverUrl), token)
47
- else localStorage.removeItem(sessionKey(serverUrl))
48
- } catch { /* storage-less host: the session lives for this run only */ }
49
- sockets.get(serverUrl)?.onSessionChanged(token)
50
- }
51
-
52
- // ───────────────────────────── endpoints ─────────────────────────────
53
-
54
- const noServer = (id: string) => new RpcError(0, `Endpoint ${id}: the project has no deployed server (compile with serverUrl)`)
55
-
56
- /** Build the client proxy of endpoint `id`. Positional args travel as a JSON array. */
57
- export const __rpc = (serverUrl: string, id: string) => {
58
- const call = async (...args: unknown[]): Promise<any> => {
59
- if (!serverUrl) throw noServer(id)
60
- const headers: Record<string, string> = { "content-type": "application/json" }
61
- const session = getSession(serverUrl)
62
- if (session) headers.authorization = `Bearer ${session}`
63
- let res
64
- try {
65
- res = await fetch(`${serverUrl}/api/${encodeURIComponent(id)}`, { method: "POST", headers, body: JSON.stringify({ args }) })
66
- } catch (e) {
67
- throw new RpcError(0, `Endpoint ${id}: request failed (${(e as Error)?.message ?? e})`)
68
- }
69
- let body: any
70
- try { body = res.json() } catch { body = null }
71
- res.dispose()
72
- if (body && typeof body === "object" && "session" in body) setSession(serverUrl, body.session ?? null)
73
- if (body && body.ok === true) return body.result
74
- if (body && body.ok === false) throw new RpcError(body.status ?? res.status, body.message ?? "")
75
- throw new RpcError(res.status, `Endpoint ${id}: unexpected response (HTTP ${res.status})`)
76
- }
77
- return call
78
- }
79
-
80
- /** A server-only export (db, models, helpers) referenced from client code: any use throws. */
81
- export const __serverOnly = (id: string): any =>
82
- new Proxy(function () {} as any, {
83
- get: (_t, prop) => { if (prop === "then") return undefined; throw new RpcError(0, `${id} is server-only — it can't be used in client code`) },
84
- apply: () => { throw new RpcError(0, `${id} is server-only — it can't be used in client code`) },
85
- })
86
-
87
- // ───────────────────────────── channels ─────────────────────────────
88
-
89
- type Handlers = Record<string, ((payload: any) => void) | undefined> & {
90
- /** The socket dropped and came back: subscriptions were re-sent, but events in between are lost — refetch. */
91
- reconnect?: () => void
92
- /** The subscription was refused (`onJoin` threw) or the socket can't connect. */
93
- error?: (e: RpcError) => void
94
- }
95
- type Sub = { id: number, ch: string, topic: string, handlers: Handlers, ready: boolean }
96
-
97
- const BACKOFF_MS = [1000, 2000, 5000, 10000, 30000]
98
-
99
- /** One multiplexed socket per server URL, shared by every channel of the app. */
100
- class ChannelSocket {
101
- private ws: WebSocket | null = null
102
- private open = false
103
- private subs = new Map<number, Sub>()
104
- private nextId = 1
105
- private attempts = 0
106
- private timer: ReturnType<typeof setTimeout> | null = null
107
- private closedByUs = false
108
- private everOpened = false
109
- private serverUrl: string
110
-
111
- constructor(serverUrl: string) { this.serverUrl = serverUrl }
112
-
113
- subscribe(ch: string, topic: string, handlers: Handlers): { close(): void } {
114
- const sub: Sub = { id: this.nextId++, ch, topic, handlers, ready: false }
115
- this.subs.set(sub.id, sub)
116
- if (this.open) this.send({ t: "sub", id: sub.id, ch, topic })
117
- else this.connect()
118
- return {
119
- close: () => {
120
- if (!this.subs.delete(sub.id)) return
121
- if (this.open) this.send({ t: "unsub", id: sub.id })
122
- if (this.subs.size === 0) this.shutdown()
123
- },
124
- }
125
- }
126
-
127
- onSessionChanged(token: string | null) {
128
- if (this.open) this.send({ t: "hello", session: token })
129
- }
130
-
131
- private connect() {
132
- if (this.ws || this.timer !== null) return
133
- this.closedByUs = false
134
- const url = this.serverUrl.replace(/^http/, "ws") + "/ws"
135
- const session = getSession(this.serverUrl)
136
- const ws = new WebSocket(url, session ? { authorization: `Bearer ${session}` } : undefined)
137
- this.ws = ws
138
- ws.addEventListener("open", () => {
139
- this.open = true
140
- this.attempts = 0
141
- this.send({ t: "hello", session: getSession(this.serverUrl) })
142
- const reconnected = this.everOpened
143
- this.everOpened = true
144
- for (const sub of this.subs.values()) {
145
- sub.ready = false
146
- this.send({ t: "sub", id: sub.id, ch: sub.ch, topic: sub.topic })
147
- if (reconnected) sub.handlers.reconnect?.()
148
- }
149
- })
150
- ws.addEventListener("message", (data) => {
151
- if (typeof data !== "string") return
152
- let msg: any
153
- try { msg = JSON.parse(data) } catch { return }
154
- this.onFrame(msg)
155
- })
156
- const onDown = () => {
157
- if (this.ws !== ws) return
158
- this.ws = null
159
- this.open = false
160
- if (this.closedByUs || this.subs.size === 0) return
161
- const delay = BACKOFF_MS[Math.min(this.attempts++, BACKOFF_MS.length - 1)]
162
- this.timer = setTimeout(() => { this.timer = null; this.connect() }, delay)
163
- }
164
- ws.addEventListener("close", onDown)
165
- ws.addEventListener("error", onDown)
166
- }
167
-
168
- private onFrame(msg: any) {
169
- switch (msg?.t) {
170
- case "session": setSession(this.serverUrl, msg.session ?? null); break
171
- case "ok": { const s = this.subs.get(msg.id); if (s) s.ready = true; break }
172
- case "err": {
173
- const s = this.subs.get(msg.id)
174
- if (!s) break
175
- this.subs.delete(msg.id)
176
- s.handlers.error?.(new RpcError(msg.status ?? 0, msg.message ?? "subscription refused"))
177
- break
178
- }
179
- case "ev": {
180
- for (const s of this.subs.values()) {
181
- if (s.ch === msg.ch && s.topic === msg.topic) s.handlers[msg.event]?.(msg.data)
182
- }
183
- break
184
- }
185
- }
186
- }
187
-
188
- private send(frame: unknown) { this.ws?.send(JSON.stringify(frame)) }
189
-
190
- private shutdown() {
191
- this.closedByUs = true
192
- if (this.timer !== null) { clearTimeout(this.timer); this.timer = null }
193
- this.ws?.close()
194
- this.ws = null
195
- this.open = false
196
- sockets.delete(this.serverUrl)
197
- }
198
- }
199
-
200
- const sockets = new Map<string, ChannelSocket>()
201
- const socketFor = (serverUrl: string) => {
202
- let s = sockets.get(serverUrl)
203
- if (!s) { s = new ChannelSocket(serverUrl); sockets.set(serverUrl, s) }
204
- return s
205
- }
206
-
207
- export interface ClientChannel<E extends Record<string, unknown> = Record<string, unknown>> {
208
- /** Subscribe to `topic`; handlers are keyed by event name (+ `reconnect`/`error`). Returns `{ close }`. */
209
- subscribe(topic: string, handlers: { [K in keyof E]?: (payload: E[K]) => void } & { reconnect?: () => void, error?: (e: RpcError) => void }): { close(): void }
210
- }
211
-
212
- /** Build the client proxy of channel `id`. */
213
- export const __channel = (serverUrl: string, id: string): ClientChannel<any> => ({
214
- subscribe(topic, handlers) {
215
- if (!serverUrl) throw noServer(id)
216
- return socketFor(serverUrl).subscribe(id, topic, handlers as Handlers)
217
- },
218
- })
@@ -1,83 +0,0 @@
1
- // A host-registered headless service (geolocation, bluetooth, contacts, …) — the UI-less sibling
2
- // of NativeView (docs/service-channel-plan.md). The host registers a *capability*
3
- // (`registerService("geolocation") { params, channel -> ... }`); the SDK talks to it over the
4
- // shared JSON call/event protocol (runtime/channel.ts) via `_creatorUtils.service*`.
5
- //
6
- // Not a public global itself: apps meet services through typed plugin wrappers (Geolocation —
7
- // src/plugins/) or the raw `Service(name)` global (src/plugins/service.ts), both thin layers
8
- // over this exactly like QRScanner wraps NativeViewElement.
9
-
10
- import { _channelCall, _channelEmit, _channelOff, _channelOn, type ChannelListeners } from "./channel"
11
-
12
- /** @internal Base for typed service plugins. The host session opens lazily on the first `call()`
13
- * (`on()` only records listeners), and `close()` releases it — a later `call()` reopens a fresh
14
- * session. Session ids are host-allocated (websocket model): the `onEvent` callback is handed
15
- * over at open, so no SDK-side ref registry is needed. */
16
- export class ServiceClient {
17
- readonly serviceName: string
18
- readonly params: any
19
- private _serviceId: number | null = null
20
- private readonly _listeners: ChannelListeners = {}
21
-
22
- constructor(serviceName: string, params: any = {}) {
23
- this.serviceName = serviceName
24
- this.params = params
25
- }
26
-
27
- /** Whether this host registered a `registerService` factory under `name`. */
28
- static isSupported(name: string): boolean {
29
- return typeof _creatorUtils !== "undefined" && typeof _creatorUtils.isServiceSupported === "function"
30
- && _creatorUtils.isServiceSupported(name)
31
- }
32
-
33
- /** @internal open (or reuse) the host session; throws when the host has no channel/factory. */
34
- private _ensureOpen(): number {
35
- if (this._serviceId !== null) return this._serviceId
36
- if (typeof _creatorUtils === "undefined" || typeof _creatorUtils.serviceOpen !== "function") {
37
- throw new Error(`Service("${this.serviceName}") is not supported on this host (requires _creatorUtils.serviceOpen)`)
38
- }
39
- const id = _creatorUtils.serviceOpen(this.serviceName, JSON.stringify(this.params ?? {}),
40
- (event: string, dataJson?: string) => _channelEmit(this._listeners, event, dataJson))
41
- if (id < 0) {
42
- throw new Error(`Service("${this.serviceName}") is not registered on this host`)
43
- }
44
- this._serviceId = id
45
- return id
46
- }
47
-
48
- /** Invoke a method on the service (`geo.call("getCurrent", options)`). Args and the result are
49
- * JSON-serialized. Rejects if the host has no such service/method. */
50
- call(method: string, ...args: any[]): Promise<any> {
51
- let id: number
52
- try {
53
- id = this._ensureOpen()
54
- } catch (e) {
55
- return Promise.reject(e)
56
- }
57
- return _channelCall(
58
- typeof _creatorUtils !== "undefined" ? _creatorUtils : undefined, "serviceCall",
59
- `Service("${this.serviceName}") is not supported on this host (requires _creatorUtils.serviceCall)`,
60
- id, method, args)
61
- }
62
-
63
- /** Subscribe to an event the service emits (`geo.on("position", cb)`). */
64
- on(event: string, callback: (data?: any) => void): this {
65
- _channelOn(this._listeners, event, callback)
66
- return this
67
- }
68
- off(event: string, callback: (data?: any) => void): this {
69
- _channelOff(this._listeners, event, callback)
70
- return this
71
- }
72
-
73
- /** Close the host session (stops whatever the service was doing). Listeners stay registered —
74
- * a later `call()` opens a fresh session that delivers to them again. */
75
- close(): void {
76
- if (this._serviceId === null) return
77
- const id = this._serviceId
78
- this._serviceId = null
79
- if (typeof _creatorUtils !== "undefined" && typeof _creatorUtils.serviceClose === "function") {
80
- _creatorUtils.serviceClose(id)
81
- }
82
- }
83
- }
@@ -1,9 +0,0 @@
1
- // Share a media File (image/video) via the OS share sheet. Wraps `_creatorUtils.shareMedia`, which
2
- // takes the host buffer id behind the File. On iOS the sheet also lets the user save to Files/Photos;
3
- // on web it saves (downloads) the file. `text` is an optional caption/message.
4
-
5
- import type { File, FetchResponse } from "./fetch"
6
-
7
- export function share(media: File | FetchResponse, text?: string): void {
8
- _creatorUtils.shareMedia((media as any)._id, text)
9
- }
@@ -1,13 +0,0 @@
1
- // Key/value persistence backed by the host. Same shape as the web localStorage subset projects use.
2
-
3
- export const localStorage = {
4
- getItem(key: string): string | null {
5
- return _creatorUtils.localStorageGetValue(key)
6
- },
7
- setItem(key: string, value: string): void {
8
- _creatorUtils.localStorageSetValue(key, value)
9
- },
10
- removeItem(key: string): void {
11
- _creatorUtils.localStorageRemoveValue(key)
12
- },
13
- }
@@ -1,76 +0,0 @@
1
- // Pointer event objects delivered to 3D scene/node touch handlers. Ported from worker/src/TouchEvent.ts.
2
- // The dispatch wiring (reading the active scene, hit entity) is set up in Phase 4 with the 3D Scene;
3
- // these classes are the injected globals user code receives. `target` is the hit Node (typed loosely
4
- // here to avoid a forward dependency on gl/).
5
-
6
- export class ClickEvent<T = any> {
7
- readonly type = "click"
8
- readonly pointerId: number
9
- readonly clientX: number
10
- readonly clientY: number
11
- /** World-space hit position (2D scenes only; undefined in 3D). */
12
- worldX?: number
13
- worldY?: number
14
- target!: T
15
- constructor(clientX: number, clientY: number, pointerId: number) {
16
- this.clientX = clientX
17
- this.clientY = clientY
18
- this.pointerId = pointerId
19
- }
20
- }
21
-
22
- export interface TrackHandler {
23
- onMove?(pos: { clientX: number, clientY: number, deltaX: number, deltaY: number }): void
24
- onEnd?(pos: { clientX: number, clientY: number, deltaX: number, deltaY: number }): void
25
- onCancel?(): void
26
- claim?: boolean | "pan-x" | "pan-y" | "pan-down" | "pan-up" | "pan-left" | "pan-right"
27
- }
28
-
29
- export class TouchStartEvent<T = any> {
30
- readonly type = "touchstart"
31
- readonly pointerId: number
32
- readonly clientX: number
33
- readonly clientY: number
34
- /** World-space hit position (2D scenes only; undefined in 3D). */
35
- worldX?: number
36
- worldY?: number
37
- target!: T
38
- /** @internal — read by the dispatch system after the handler runs. */
39
- _trackHandler?: TrackHandler
40
- constructor(clientX: number, clientY: number, pointerId: number) {
41
- this.clientX = clientX
42
- this.clientY = clientY
43
- this.pointerId = pointerId
44
- }
45
-
46
- /** Capture subsequent moves/end for this pointer (drag/pan gestures). */
47
- track(handler: TrackHandler): void {
48
- this._trackHandler = handler
49
- }
50
- }
51
-
52
- /** Delivered to a `UIButton` `onLongPress` handler when a finger is held on the button past the
53
- * host's long-press threshold. Like `TouchStartEvent` it can `track(...)` the rest of the gesture —
54
- * so the common "press-and-hold, then drag to move" flow is one handler: start the drag from here. */
55
- export class LongPressEvent<T = any> {
56
- readonly type = "longpress"
57
- readonly pointerId: number
58
- readonly clientX: number
59
- readonly clientY: number
60
- /** World-space hit position (2D scenes only; undefined in 3D). */
61
- worldX?: number
62
- worldY?: number
63
- target!: T
64
- /** @internal — read by the dispatch system after the handler runs. */
65
- _trackHandler?: TrackHandler
66
- constructor(clientX: number, clientY: number, pointerId: number) {
67
- this.clientX = clientX
68
- this.clientY = clientY
69
- this.pointerId = pointerId
70
- }
71
-
72
- /** Capture subsequent moves/end for this pointer — drag the element after the hold. */
73
- track(handler: TrackHandler): void {
74
- this._trackHandler = handler
75
- }
76
- }