lecodes-sdk 2.2.13 → 2.3.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/dist/global.d.ts +11 -0
- package/dist/types/gl/Scene.d.ts +0 -11
- package/dist/types/gl/postProcessing.d.ts +31 -2
- package/dist/types/inject.d.ts +3 -2
- package/dist/types/plugin.d.ts +3 -0
- package/dist/types/plugins/gen/push/sdk/push.d.ts +10 -3
- package/dist/types/plugins/gen/push/sdk/push.gen.d.ts +11 -3
- package/dist/types/runtime/device.d.ts +7 -19
- package/dist/types/runtime/pushSeam.d.ts +23 -0
- package/dist/types/runtime/rpc.d.ts +15 -1
- package/dist/types/server/auth/models.d.ts +13 -1
- package/dist/types/server/auth/types.d.ts +2 -0
- package/dist/types/server/inject.d.ts +1 -0
- package/dist/types/server/pushChannel.d.ts +79 -0
- package/dist/types/ui/UINode.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/src/animate/tween/Timeline.ts +175 -175
- package/src/bridges/gl.d.ts +5 -13
- package/src/compile/serverSplit.ts +29 -19
- package/src/compile/serverTypes.ts +1 -1
- package/src/gl/CameraPlace.ts +52 -52
- package/src/gl/Light.ts +257 -257
- package/src/gl/Mesh.ts +120 -120
- package/src/gl/Scene.ts +0 -13
- package/src/gl/animation/DynamicBone.ts +486 -486
- package/src/gl/postProcessing.ts +52 -9
- package/src/gl/scenarios.ts +291 -291
- package/src/inject.ts +3 -2
- package/src/plugin.ts +3 -0
- package/src/plugins/gen/push/contract.d.ts +24 -2
- package/src/plugins/gen/push/sdk/push.gen.ts +17 -5
- package/src/plugins/gen/push/sdk/push.ts +159 -55
- package/src/runtime/device.ts +8 -37
- package/src/runtime/pushSeam.ts +22 -0
- package/src/runtime/rpc.ts +35 -1
- package/src/server/auth/host.ts +40 -9
- package/src/server/auth/models.ts +5 -1
- package/src/server/auth/types.ts +2 -0
- package/src/server/host.ts +6 -0
- package/src/server/inject.ts +3 -2
- package/src/server/push/host.ts +143 -0
- package/src/server/pushChannel.ts +121 -0
- package/src/server/runtime.ts +20 -8
- package/src/ui/UIInput.ts +2 -2
- package/src/ui/UINode.ts +1 -1
- package/src/version.ts +1 -1
package/dist/global.d.ts
CHANGED
|
@@ -173,6 +173,8 @@ declare global {
|
|
|
173
173
|
const __channel: typeof SDK.__channel
|
|
174
174
|
const __compOp: typeof SDK.__compOp
|
|
175
175
|
const __compWrite: typeof SDK.__compWrite
|
|
176
|
+
const __pushChannel: typeof SDK.__pushChannel
|
|
177
|
+
const __pushEnable: typeof SDK.__pushEnable
|
|
176
178
|
const __rpc: typeof SDK.__rpc
|
|
177
179
|
const __serverOnly: typeof SDK.__serverOnly
|
|
178
180
|
const __uiMap: typeof SDK.__uiMap
|
|
@@ -478,10 +480,14 @@ declare global {
|
|
|
478
480
|
type Point = SDK.Point
|
|
479
481
|
type PresentOptions = SDK.PresentOptions
|
|
480
482
|
type Presentable = SDK.Presentable
|
|
483
|
+
type PushChannel<D extends Record<string, unknown> | undefined = undefined> = SDK.PushChannel<D>
|
|
481
484
|
type PushEvent = SDK.PushEvent
|
|
485
|
+
type PushMessage<D> = SDK.PushMessage<D>
|
|
486
|
+
type PushNotification<D> = SDK.PushNotification<D>
|
|
482
487
|
type PushPayload = SDK.PushPayload
|
|
483
488
|
type PushRegisterOptions = SDK.PushRegisterOptions
|
|
484
489
|
type PushStatus = SDK.PushStatus
|
|
490
|
+
type PushTarget = SDK.PushTarget
|
|
485
491
|
type QRScanner = SDK.QRScanner
|
|
486
492
|
type Quat = SDK.Quat
|
|
487
493
|
type RTCConfiguration = SDK.RTCConfiguration
|
|
@@ -674,10 +680,15 @@ declare global {
|
|
|
674
680
|
const channel: typeof SERVER.channel
|
|
675
681
|
const defineDb: typeof SERVER.defineDb
|
|
676
682
|
const model: typeof SERVER.model
|
|
683
|
+
const pushChannel: typeof SERVER.pushChannel
|
|
677
684
|
const ref: typeof SERVER.ref
|
|
678
685
|
const request: typeof SERVER.request
|
|
679
686
|
const t: typeof SERVER.t
|
|
680
687
|
type ApiError = SERVER.ApiError
|
|
688
|
+
type PushChannel<D extends Record<string, unknown> | undefined = undefined> = SERVER.PushChannel<D>
|
|
689
|
+
type PushMessage<D> = SERVER.PushMessage<D>
|
|
690
|
+
type PushNotification<D> = SERVER.PushNotification<D>
|
|
691
|
+
type PushTarget = SERVER.PushTarget
|
|
681
692
|
type StoredFile = SERVER.StoredFile
|
|
682
693
|
type StoredImage = SERVER.StoredImage
|
|
683
694
|
}
|
package/dist/types/gl/Scene.d.ts
CHANGED
|
@@ -129,17 +129,6 @@ export type SceneOptions = {
|
|
|
129
129
|
* loses its top mip levels on load, a glTF image is downsampled. Applied before this scene's
|
|
130
130
|
* assets load; like `anisotropy` it does not touch textures already loaded. */
|
|
131
131
|
maxTextureSize?: number;
|
|
132
|
-
/** The look on an HDR display (a screen with headroom above SDR white — Apple XDR panels, the
|
|
133
|
-
* macOS host today); ignored on SDR. `strength` 0..1 is how much of the picture reaches for the
|
|
134
|
-
* display's headroom (0 only what SDR clipped, 1 nearly everything; default 0.35). `paperWhite`
|
|
135
|
-
* 1..8 is where white lands as a multiple of SDR white — the "HDR brightness" of a console
|
|
136
|
-
* calibration screen, where 1.5–2 is the norm; default 1 keeps a white wall at the UI's white,
|
|
137
|
-
* faithful but dim next to what "HDR on" is expected to look like. Engine-wide like `anisotropy`;
|
|
138
|
-
* `device.hdr` is the runtime form and tells you whether the display has any headroom at all. */
|
|
139
|
-
hdr?: {
|
|
140
|
-
strength?: number;
|
|
141
|
-
paperWhite?: number;
|
|
142
|
-
};
|
|
143
132
|
};
|
|
144
133
|
export declare class Scene implements Presentable {
|
|
145
134
|
readonly camera: Camera;
|
|
@@ -95,6 +95,25 @@ export type ColorCurves = {
|
|
|
95
95
|
midPoint?: Rgb;
|
|
96
96
|
highlightScale?: Rgb;
|
|
97
97
|
};
|
|
98
|
+
/** The look on an HDR display — a screen with headroom above SDR white (Apple's XDR panels, an
|
|
99
|
+
* external display in HDR mode), where the operator is stretched past SDR white toward the peak.
|
|
100
|
+
* Ignored on SDR: stored, read back, nothing changes on screen (`device.hdr.available` says which
|
|
101
|
+
* display this is). Part of the grading band — a change is a bake — and quantised to 0.05 steps. */
|
|
102
|
+
export type HdrLook = {
|
|
103
|
+
/** How much of the picture reaches for the display's headroom, 0..1 (default 0.35). 0 touches only
|
|
104
|
+
* what SDR clipped — the SDR grade kept exactly, but a mostly-mid-tone frame then looks flat next
|
|
105
|
+
* to its one bright spot; 1 lifts nearly everything above black toward the peak. A sunlit
|
|
106
|
+
* exterior takes 1, a dim interior wants less. */
|
|
107
|
+
strength?: number;
|
|
108
|
+
/** Where white lands, as a multiple of SDR white, 1..8 (default 1) — the "HDR brightness" of a
|
|
109
|
+
* console game's calibration screen, where 1.5–2 is the norm. It scales the WHOLE picture: at 1
|
|
110
|
+
* a white wall is as bright as the UI's white (faithful, and dim next to what "HDR on" is
|
|
111
|
+
* expected to look like), at 2 twice that, and highlights still climb above it (the engine keeps
|
|
112
|
+
* `headroom / paperWhite` for them, clamped at the peak). `strength` decides how much of the
|
|
113
|
+
* picture reaches for the peak; this decides where the picture starts — a game that wants to read
|
|
114
|
+
* as "HDR on" rather than "SDR with a brighter sun" wants this over `strength`. */
|
|
115
|
+
paperWhite?: number;
|
|
116
|
+
};
|
|
98
117
|
export type PostProcessingOptions = {
|
|
99
118
|
/** The operator that folds the scene's HDR light into the display's range (default 'aces').
|
|
100
119
|
* `'aces'` (filament's ACES legacy) desaturates bright colours towards white — HDR fire reads
|
|
@@ -128,6 +147,11 @@ export type PostProcessingOptions = {
|
|
|
128
147
|
* the operator, in display-referred sRGB — a `.cube` file: `asset('./look.cube')`, or a bare
|
|
129
148
|
* staged filename. `null` removes it. */
|
|
130
149
|
lut?: string | null;
|
|
150
|
+
/** The look on an HDR display: `strength` 0..1 (how much of the picture reaches for the peak:
|
|
151
|
+
* 0 only what SDR clipped … 1 nearly everything; default 0.35), `paperWhite` 1..8 (where white
|
|
152
|
+
* lands × SDR white — the console "HDR brightness", 1.5–2 the norm; default 1). Ignored on SDR.
|
|
153
|
+
* An overlay takes its parent's, like the rest of the grading. */
|
|
154
|
+
hdr?: HdrLook;
|
|
131
155
|
/** `true` = defaults (intensity 0.2), an object = its knobs, `false` = off. */
|
|
132
156
|
bloom?: boolean | BloomOptions;
|
|
133
157
|
/** `true` = defaults (a soft black edge), an object = its knobs, `false` = off. */
|
|
@@ -140,7 +164,8 @@ export type PostProcessingOptions = {
|
|
|
140
164
|
depthOfField?: boolean | DepthOfFieldOptions;
|
|
141
165
|
};
|
|
142
166
|
/** The float layout of `_creator.setColorGrading` — creator.h's ColorGradingParam. Indices never
|
|
143
|
-
* move; a new field goes at the end and COUNT grows
|
|
167
|
+
* move; a new field goes at the end and COUNT grows (the engine takes an older bundle's shorter
|
|
168
|
+
* array, down to the 39 before HDR_*, with the tail at its defaults). */
|
|
144
169
|
export declare const CG: {
|
|
145
170
|
readonly TONE_MAPPING: 0;
|
|
146
171
|
readonly EXPOSURE: 1;
|
|
@@ -160,7 +185,9 @@ export declare const CG: {
|
|
|
160
185
|
readonly MID_POINT: 32;
|
|
161
186
|
readonly HIGHLIGHT_SCALE: 35;
|
|
162
187
|
readonly LUT: 38;
|
|
163
|
-
readonly
|
|
188
|
+
readonly HDR_STRENGTH: 39;
|
|
189
|
+
readonly HDR_PAPER_WHITE: 40;
|
|
190
|
+
readonly COUNT: 41;
|
|
164
191
|
};
|
|
165
192
|
/** The scene's post-processing (`scene.postProcessing`). Read a field for the current value, write
|
|
166
193
|
* one to change it; `apply(options)` writes the named ones; `reset()` is the defaults. */
|
|
@@ -212,6 +239,8 @@ export declare class PostProcessing {
|
|
|
212
239
|
set curves(v: ColorCurves);
|
|
213
240
|
get lut(): string | null;
|
|
214
241
|
set lut(v: string | null);
|
|
242
|
+
get hdr(): Required<HdrLook>;
|
|
243
|
+
set hdr(v: HdrLook);
|
|
215
244
|
get bloom(): Required<BloomOptions> | false;
|
|
216
245
|
set bloom(v: boolean | BloomOptions);
|
|
217
246
|
get vignette(): Required<VignetteOptions> | false;
|
package/dist/types/inject.d.ts
CHANGED
|
@@ -22,9 +22,10 @@ export { device, type HapticStyle, type MotionOptions } from "./runtime/device";
|
|
|
22
22
|
export { Input, InputChannel, type InputKeyEvent, type InputGamepadEvent, type InputEventName, type GamepadState, type GamepadAxisName } from "./runtime/input";
|
|
23
23
|
export { WebSocket } from "./runtime/net";
|
|
24
24
|
export { Net, NetPlayer, Replicated, NetEntity, type NetMessage, type NetRole, type NetStatus, type NetEvents, type NetLaunch, type NetInput, type NetKind, type NetTransform, type NetCorrection } from "./net";
|
|
25
|
-
export { __rpc, __channel, __serverOnly, RpcError } from "./runtime/rpc";
|
|
25
|
+
export { __rpc, __channel, __pushChannel, __serverOnly, RpcError } from "./runtime/rpc";
|
|
26
26
|
export { resource, action, dataOf, failureOf, type Loaded, type Failure, type Resource, type Action } from "./runtime/resource";
|
|
27
27
|
export type { ChannelSubscription } from "./server/channel";
|
|
28
|
+
export type { PushChannel, PushMessage, PushNotification, PushTarget } from "./server/pushChannel";
|
|
28
29
|
export type { StoredFile, StoredImage } from "./server/files/models";
|
|
29
30
|
export { AudioPlayer, VideoPlayer } from "./runtime/media";
|
|
30
31
|
export { Sound, type SoundOptions } from "./audio/Sound";
|
|
@@ -76,7 +77,7 @@ export { ARScene, Anchor, ImageAnchor, ARPlane, type ARSceneOptions, type AROpen
|
|
|
76
77
|
export { AudioRecorder, type AudioRecorderEvents, type RecorderState, type RecordOptions, type Recording, type EndReason } from "./plugins/gen/audio-recorder/sdk/audio-recorder";
|
|
77
78
|
export { SpeechRecognizer, type SpeechRecognizerEvents, type SpeechOptions, type SpeechResult, type SpeechErrorCode } from "./plugins/gen/speech/sdk/speech";
|
|
78
79
|
export { MapView, type MapOptions, type MapStyle, type MapStyleName, type MapCamera, type MapTap, type LngLat, type CameraMove, type FitOptions, type MapPaddingValues, type MarkerItem, type MarkerTap, type MarkerLayer, type MarkerLayerOptions, type LineLayer, type LineLayerOptions, type UserLocationOptions, } from "./plugins/gen/map/sdk/map";
|
|
79
|
-
export { Push, type PushPayload, type PushStatus, type PushRegisterOptions, type PushEvent } from "./plugins/gen/push/sdk/push";
|
|
80
|
+
export { Push, __pushEnable, type PushPayload, type PushStatus, type PushRegisterOptions, type PushEvent } from "./plugins/gen/push/sdk/push";
|
|
80
81
|
export { Browser, WebView, type BrowserOpenOptions, type WebViewParams, type WebViewEvents } from "./plugins/gen/browser/sdk/browser";
|
|
81
82
|
export { RTCPeerConnection, MediaStream, MediaStreamTrack, RTCDataChannel, RTCRtpSender, RTCRtpReceiver, RTCRtpTransceiver, RTCSessionDescription, RTCIceCandidate, RTCEventTarget, mediaDevices, RTCVideoView, type RTCConfiguration, type RTCVideoViewOptions, type MediaStreamConstraints, type RTCIceCandidateInit, type RTCPeerConnectionIceEvent, type RTCTrackEvent, type RTCDataChannelEvent, type RTCMessageEvent, type RTCErrorEvent, type RTCEvent, type RTCEventListener, } from "./plugins/gen/webrtc/sdk/webrtc";
|
|
82
83
|
export { Service } from "./plugins/service";
|
package/dist/types/plugin.d.ts
CHANGED
|
@@ -23,6 +23,9 @@ export { Quat, type QuatLike } from "./math/quat";
|
|
|
23
23
|
export { Mat4 } from "./math/mat4";
|
|
24
24
|
export type { ClickEvent, TouchStartEvent } from "./runtime/touch";
|
|
25
25
|
export type { DismissOptions } from "./ui/presentable";
|
|
26
|
+
/** The seam the push plugin's wrapper installs its runtime on (src/runtime/pushSeam.ts): what the app's transport
|
|
27
|
+
* reads the device's address from, registers through, and a push channel's handlers are kept by. */
|
|
28
|
+
export { _pushRuntime, type PushRuntime } from "./runtime/pushSeam";
|
|
26
29
|
/** Signed 32-bit integer on the wire. */
|
|
27
30
|
export type i32 = number;
|
|
28
31
|
/** Double on the wire — also every integer that can leave 32 bits (a millisecond time stamp). */
|
|
@@ -4,6 +4,11 @@ export type PushEvent = keyof PushEvents;
|
|
|
4
4
|
/**
|
|
5
5
|
* Remote push notifications. `Push.isSupported` reports whether this host registered the
|
|
6
6
|
* service — check it before offering notification features.
|
|
7
|
+
*
|
|
8
|
+
* A project with a backend needs none of this: its `pushChannel()` exports are heard with their
|
|
9
|
+
* own `onTap` / `onMessage`, and the device is registered when the server asks (after a sign-in).
|
|
10
|
+
* `Push` is for the rest — a permission asked at a moment of the app's choosing, and the
|
|
11
|
+
* notifications sent outside a channel (a push key, `lecodes pn send`).
|
|
7
12
|
*/
|
|
8
13
|
export declare const Push: {
|
|
9
14
|
/** Whether this host registered a "push" service. */
|
|
@@ -15,9 +20,11 @@ export declare const Push: {
|
|
|
15
20
|
register(options?: PushRegisterOptions): Promise<PushRegistration>;
|
|
16
21
|
/** Remove this device's registration (the address stops receiving). */
|
|
17
22
|
unregister(): Promise<void>;
|
|
18
|
-
/** The
|
|
19
|
-
|
|
20
|
-
/** "message" = received while the app is open; "tap" = the user tapped one while it ran. */
|
|
23
|
+
/** The notifications sent outside a push channel: "tap" = tapped (the one that started the app
|
|
24
|
+
* too); "message" = arrived while the app is open (the app shows it, the host no banner). */
|
|
21
25
|
addEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void;
|
|
22
26
|
removeEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void;
|
|
23
27
|
};
|
|
28
|
+
/** Installs the push runtime for the SDK's transport and its push-channel proxies (lecodes-sdk/plugin
|
|
29
|
+
* `_pushRuntime`). A line of every server stub of a project with push channels — never app code. */
|
|
30
|
+
export declare const __pushEnable: () => void;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ServiceChannel } from "../../../../plugin";
|
|
2
|
-
import type { PushEvents, PushParams, PushPayload, PushRegisterOptions, PushRegistration, PushStatus } from "../contract";
|
|
2
|
+
import type { PushEvents, PushHandled, PushParams, PushPayload, PushRegisterOptions, PushRegistration, PushStatus } from "../contract";
|
|
3
3
|
/** What the halves register under. */
|
|
4
4
|
export declare const NAME = "push";
|
|
5
5
|
/** The contract's version: the highest `@since` of its members. */
|
|
6
|
-
export declare const VERSION =
|
|
6
|
+
export declare const VERSION = 2;
|
|
7
7
|
/** Permission + registration state. Never prompts. */
|
|
8
8
|
export declare const getStatus: (service: ServiceChannel<PushEvents>) => Promise<PushStatus>;
|
|
9
9
|
/** Ask for the permission (the first time) and register this device. Idempotent.
|
|
@@ -14,8 +14,12 @@ export declare const register: (service: ServiceChannel<PushEvents>, options?: P
|
|
|
14
14
|
export declare const unregister: (service: ServiceChannel<PushEvents>) => Promise<void>;
|
|
15
15
|
/** The notification that cold-started this world, or null. Stable across calls. */
|
|
16
16
|
export declare const getLaunch: (service: ServiceChannel<PushEvents>) => Promise<PushPayload | null>;
|
|
17
|
+
/** Which notifications the app handles itself in the foreground; the rest get the system banner.
|
|
18
|
+
* Until it is called nothing is handled.
|
|
19
|
+
* Contract version 2: an older half rejects the call — ask `supports("setMessageHandled")`. */
|
|
20
|
+
export declare const setMessageHandled: (service: ServiceChannel<PushEvents>, handled: PushHandled) => Promise<void>;
|
|
17
21
|
/** A method of the contract. */
|
|
18
|
-
export type Method = "getStatus" | "register" | "unregister" | "getLaunch";
|
|
22
|
+
export type Method = "getStatus" | "register" | "unregister" | "getLaunch" | "setMessageHandled";
|
|
19
23
|
/** Whether this host has the service "push" — and, given a method, a half new enough for it
|
|
20
24
|
* (a method added after the first version of the contract is tagged `@since`). */
|
|
21
25
|
export declare const supports: (method?: Method) => boolean;
|
|
@@ -32,4 +36,8 @@ export declare class PushBase extends ServiceChannel<PushEvents> {
|
|
|
32
36
|
unregister(): Promise<void>;
|
|
33
37
|
/** The notification that cold-started this world, or null. Stable across calls. */
|
|
34
38
|
getLaunch(): Promise<PushPayload | null>;
|
|
39
|
+
/** Which notifications the app handles itself in the foreground; the rest get the system banner.
|
|
40
|
+
* Until it is called nothing is handled.
|
|
41
|
+
* Contract version 2: an older half rejects the call — ask `supports("setMessageHandled")`. */
|
|
42
|
+
setMessageHandled(handled: PushHandled): Promise<void>;
|
|
35
43
|
}
|
|
@@ -88,11 +88,13 @@ export declare const device: {
|
|
|
88
88
|
* `(0,0,0)` when not running. */
|
|
89
89
|
readonly gravity: Vec3;
|
|
90
90
|
};
|
|
91
|
-
/** The display's extended dynamic range — HDR
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* the
|
|
91
|
+
/** The display's extended dynamic range — HDR: the FACTS about the display. On the macOS desktop
|
|
92
|
+
* host, in a visible window on a screen with headroom above SDR white (Apple's XDR panels, an HDR
|
|
93
|
+
* external display), the 3D surface is float and the engine renders past 1.0: 1.0 is the white of
|
|
94
|
+
* the UI and of a diffuse white surface, and the sun, emissives and speculars climb up to
|
|
95
|
+
* `headroom` times that. Everywhere else it is SDR (the other hosts, a hidden window, a render to
|
|
96
|
+
* PNG): `available` false, `headroom` 1. The LOOK on such a display — how much of the picture
|
|
97
|
+
* reaches for the peak, where white lands — is the scene's: `scene.postProcessing.hdr`.
|
|
96
98
|
*
|
|
97
99
|
* Branch content on `available`, not on `headroom` — the live value ramps up from 1 over the
|
|
98
100
|
* first seconds after launch and follows the brightness keys. Particle `emissive` is the thing
|
|
@@ -108,20 +110,6 @@ export declare const device: {
|
|
|
108
110
|
* white, quantised to half-stops. Moves with brightness and the screen under the window
|
|
109
111
|
* (`hdrchange` event); never below 1. */
|
|
110
112
|
readonly headroom: number;
|
|
111
|
-
/** How much of the picture reaches for the headroom, 0..1 (default 0.35). 0 touches only what
|
|
112
|
-
* SDR clipped — faithful to the SDR grade, but a mostly-mid-tone frame then looks flat next to
|
|
113
|
-
* the one bright spot; 1 lifts nearly everything above black toward the peak. A sunlit exterior
|
|
114
|
-
* takes 1, a dim interior wants less. A host may pin it (`LECODES_HDR_STRENGTH`). */
|
|
115
|
-
strength: number;
|
|
116
|
-
/** Where white lands, as a multiple of SDR white, 1..8 (default 1) — the "HDR brightness" of a
|
|
117
|
-
* console game's calibration screen, where paper white sits at ~200 nits against SDR's ~100.
|
|
118
|
-
* It scales the WHOLE picture: at 1 a white wall is as bright as the UI's white, at 2 it is
|
|
119
|
-
* twice that, and highlights still climb above it (the engine keeps `headroom / paperWhite` for
|
|
120
|
-
* them, clamped at the peak). `strength` decides how much of the picture reaches for the
|
|
121
|
-
* peak; this decides where the picture starts. 1.5–2 is the console norm; a game that wants to
|
|
122
|
-
* read as "HDR on" rather than "SDR with a brighter sun" wants this over `strength`. A host may
|
|
123
|
-
* pin it (`LECODES_HDR_PAPER_WHITE`). */
|
|
124
|
-
paperWhite: number;
|
|
125
113
|
};
|
|
126
114
|
/** Current connectivity — best-effort navigator.onLine semantics: `false` only when the platform
|
|
127
115
|
* is sure there's no network. `true` on hosts that don't track it. Change events: `"online"` /
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The seam between the app's transport (./rpc.ts) and the push plugin's wrapper (src/plugins/gen/push/sdk/push.ts).
|
|
3
|
+
*
|
|
4
|
+
* A push channel (`pushChannel()` of a *.server.ts file — src/server/pushChannel.ts) is heard in the app through
|
|
5
|
+
* the plugin: its taps and foreground arrivals come off the plugin's service. The transport, for its part, tells
|
|
6
|
+
* the server the device's address (the `x-lecodes-push` header of every call) and registers the device when the
|
|
7
|
+
* server asks for it (the envelope's `push: true`). Neither may import the wrapper: an app without push channels
|
|
8
|
+
* would then carry the plugin. So the wrapper installs itself here — `__pushEnable()`, a line the compiler puts at
|
|
9
|
+
* the top of every server stub of a project with push channels — and the transport reads what is installed.
|
|
10
|
+
*/
|
|
11
|
+
export type PushRuntime = {
|
|
12
|
+
/** This device's address for the app, once known (after a registration, or the status of an earlier one). */
|
|
13
|
+
address(): string | null;
|
|
14
|
+
/** The server asked this device to register: once per run, prompt-free when the permission was given,
|
|
15
|
+
* nothing past a refusal. */
|
|
16
|
+
requestRegister(): void;
|
|
17
|
+
/** Hear the taps ("tap") or the foreground arrivals ("message") of one push channel, by its id. Returns the remover. */
|
|
18
|
+
on(kind: "tap" | "message", channel: string, handler: (payload: any) => void): () => void;
|
|
19
|
+
};
|
|
20
|
+
/** What the wrapper installed; null = the app has no push channels (or the plugin is not in the bundle). */
|
|
21
|
+
export declare const _pushRuntime: {
|
|
22
|
+
current: PushRuntime | null;
|
|
23
|
+
};
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* export const db = __serverOnly("schema.server.ts#db")
|
|
9
9
|
*
|
|
10
10
|
* Wire (implemented by the runner):
|
|
11
|
-
* POST <serverUrl>/api/<id> body {"args":[…]}, `authorization: Bearer <session>` when known
|
|
11
|
+
* POST <serverUrl>/api/<id> body {"args":[…]}, `authorization: Bearer <session>` when known,
|
|
12
|
+
* `x-lecodes-push: <address>` once the device registered for notifications
|
|
12
13
|
* — with a `File` among the arguments: multipart, the field `args` is
|
|
13
14
|
* that JSON with `{"$file": <i>}` where the file stood, `file<i>` the files
|
|
14
15
|
* → 200 {"ok":true,"result":…,"session"?:"…"} | {"ok":false,"status":n,"message":"…","session"?:"…"}
|
|
@@ -38,3 +39,16 @@ export declare const __channel: (serverUrl: string, id: string) => {
|
|
|
38
39
|
subscribe(...all: unknown[]): ChannelSubscription;
|
|
39
40
|
publish(): never;
|
|
40
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* Build the client proxy of push channel `id` — what a `pushChannel()` export of a `*.server.ts` file is
|
|
44
|
+
* in the app (its type is the server's: src/server/pushChannel.ts). The notifications come off the push
|
|
45
|
+
* plugin, through the runtime its wrapper installed (`__pushEnable()`, the first line of the stubs of a
|
|
46
|
+
* project with push channels — ./pushSeam.ts): `onTap` hears this channel's taps (the one that started
|
|
47
|
+
* the app included), `onMessage` its arrivals while the app is in the foreground. On a host without the
|
|
48
|
+
* plugin a handler is recorded and never called, like the plugin's own listeners.
|
|
49
|
+
*/
|
|
50
|
+
export declare const __pushChannel: (serverUrl: string, id: string) => {
|
|
51
|
+
onTap: (handler: unknown) => ChannelSubscription;
|
|
52
|
+
onMessage: (handler: unknown) => ChannelSubscription;
|
|
53
|
+
send(): never;
|
|
54
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The two models sign-in adds to a database — `defineDb({...}).withAuth({ model: "User" })`:
|
|
3
3
|
*
|
|
4
|
-
* Session one device: the hash of its token,
|
|
4
|
+
* Session one device: the hash of its token, the user it is signed in as (none = a guest), and the
|
|
5
|
+
* device's push address when it told one (what a push channel's `send` reaches the user by)
|
|
5
6
|
* Identity one way a user signs in: `email:<address>` or `login:<name>` (with the password's hash
|
|
6
7
|
* when one is set) — several per user.
|
|
7
8
|
*
|
|
@@ -85,6 +86,17 @@ export declare const sessionFields: (userModel: string) => {
|
|
|
85
86
|
isId: false;
|
|
86
87
|
model: "";
|
|
87
88
|
}>;
|
|
89
|
+
/** The device's address at the platform's push relay (`x-lecodes-push` of its calls) — the session's own
|
|
90
|
+
* secret, like the token: never read back by a project (../push/host.ts sends by it). */
|
|
91
|
+
pushAddress: import("../db").Field<string, {
|
|
92
|
+
kind: "scalar";
|
|
93
|
+
scalar: "string";
|
|
94
|
+
optional: true;
|
|
95
|
+
hasDefault: false;
|
|
96
|
+
array: false;
|
|
97
|
+
isId: false;
|
|
98
|
+
model: "";
|
|
99
|
+
}>;
|
|
88
100
|
user: import("../db").Field<never, {
|
|
89
101
|
kind: "one";
|
|
90
102
|
scalar: "";
|
|
@@ -11,6 +11,8 @@ import type { RequestContext } from "../context";
|
|
|
11
11
|
export type AuthState = {
|
|
12
12
|
sessionId: number;
|
|
13
13
|
userId: number | null;
|
|
14
|
+
/** The push address of the device, as the session holds it after this request's header was read (null = none). */
|
|
15
|
+
pushAddress?: string | null;
|
|
14
16
|
/** A token to hand back to the client in this response (a new guest session, or a rotation). */
|
|
15
17
|
issuedToken?: string;
|
|
16
18
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { t, model, defineDb, ref } from "./db";
|
|
2
2
|
export { ApiError } from "./errors";
|
|
3
3
|
export { channel } from "./channel";
|
|
4
|
+
export { pushChannel, type PushChannel, type PushMessage, type PushNotification, type PushTarget } from "./pushChannel";
|
|
4
5
|
export { request } from "./context";
|
|
5
6
|
export type { StoredFile, StoredImage } from "./files/models";
|
|
6
7
|
/** The value an SVG source is to the client (`assetIcon(…)` compiles to `SvgSource(…)`): a shared module of
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push channels: the server's notifications to a person's devices — the twin of ./channel.ts for what
|
|
3
|
+
* reaches someone while the app is closed. One export types both sides:
|
|
4
|
+
*
|
|
5
|
+
* export const orderShippedPushChannel = pushChannel<{ orderId: number }>() // pushes.server.ts
|
|
6
|
+
*
|
|
7
|
+
* await orderShippedPushChannel.send(order.owner, { title: "Order shipped", data: { orderId } }) // server
|
|
8
|
+
*
|
|
9
|
+
* orderShippedPushChannel.onTap(({ data }) => Router.push(OrderScreen(data.orderId))) // app
|
|
10
|
+
* orderShippedPushChannel.onMessage(({ title }) => toast(title))
|
|
11
|
+
*
|
|
12
|
+
* `send` reaches every device the user is signed in on. The devices are the sessions of the project's db
|
|
13
|
+
* with sign-in (`defineDb(...).withAuth(...)`): a session carries the address of its device — the app's
|
|
14
|
+
* transport tells it with every call, and the server asks the device to register when a signed-in
|
|
15
|
+
* session has none (the first response after a sign-in; the OS asks the permission then) — and a
|
|
16
|
+
* sign-out leaves the device on a guest session, which no `send` reaches. A user with no device is zero
|
|
17
|
+
* sends, not an error. `send` needs no request: a timer may call it.
|
|
18
|
+
*
|
|
19
|
+
* The server holds no push key: the host sends through the platform (./push/host.ts), reached here over
|
|
20
|
+
* the `globalThis.__lecodesPushSend` seam (the compiled bundle carries its own SDK copy — ./context.ts).
|
|
21
|
+
* A channel's identity is its export (`<path>#<name>`), assigned when the bundle is loaded
|
|
22
|
+
* (`loadServerModules`), and it travels in the notification: the app's side hears each channel's own.
|
|
23
|
+
*
|
|
24
|
+
* In the app the export is another object — the proxy `__pushChannel` of src/runtime/rpc.ts — which is
|
|
25
|
+
* why `onTap` / `onMessage` here only throw.
|
|
26
|
+
*/
|
|
27
|
+
import type { ChannelSubscription } from "./channel";
|
|
28
|
+
export type { ChannelSubscription };
|
|
29
|
+
/** Whom a notification goes to: a user id, or a row that has one (`db.auth.requireUser().select({ id: true })`, a relation). */
|
|
30
|
+
export type PushTarget = number | {
|
|
31
|
+
id: number;
|
|
32
|
+
};
|
|
33
|
+
/** What a notification shows, and what it carries for the app (`data`, the channel's type). */
|
|
34
|
+
export type PushMessage<D> = {
|
|
35
|
+
/** Up to 200 characters. */
|
|
36
|
+
title: string;
|
|
37
|
+
/** The second line, up to 1000 characters. */
|
|
38
|
+
body?: string;
|
|
39
|
+
/** A link for the app to open on a tap (`onTap` gets it — it is not opened by itself). */
|
|
40
|
+
url?: string;
|
|
41
|
+
/** The number on the app's icon (iOS; 0 clears it). */
|
|
42
|
+
badge?: number;
|
|
43
|
+
} & (undefined extends D ? {
|
|
44
|
+
data?: D;
|
|
45
|
+
} : {
|
|
46
|
+
data: D;
|
|
47
|
+
});
|
|
48
|
+
/** A notification as the app receives it: what was sent, and the channel it came through. */
|
|
49
|
+
export type PushNotification<D> = PushMessage<D> & {
|
|
50
|
+
channel: string;
|
|
51
|
+
};
|
|
52
|
+
export interface PushChannel<D extends Record<string, unknown> | undefined = undefined> {
|
|
53
|
+
/** Server: send `message` to every device `user` is signed in on (one id or several). Answers how many
|
|
54
|
+
* devices it went to — none is 0, not an error. */
|
|
55
|
+
send(user: PushTarget | PushTarget[], message: PushMessage<D>): Promise<{
|
|
56
|
+
sent: number;
|
|
57
|
+
}>;
|
|
58
|
+
/** App: a notification of this channel was tapped — while the app ran, or to start it. Lives until `close()`. */
|
|
59
|
+
onTap(handler: (notification: PushNotification<D>) => void): ChannelSubscription;
|
|
60
|
+
/** App: a notification of this channel arrived while the app was in the foreground: the app shows it
|
|
61
|
+
* (the host shows no banner); a channel without this handler gets the system banner. */
|
|
62
|
+
onMessage(handler: (notification: PushNotification<D>) => void): ChannelSubscription;
|
|
63
|
+
}
|
|
64
|
+
/** What the host reads of a push channel (src/server/runtime.ts). */
|
|
65
|
+
export type PushChannelRecord = {
|
|
66
|
+
/** set by the runtime: `<path>#<export>` */
|
|
67
|
+
__id: string | null;
|
|
68
|
+
readonly __pushChannel: true;
|
|
69
|
+
};
|
|
70
|
+
/** The host's sender (./push/host.ts): the channel, the users' ids, the message → how many devices. */
|
|
71
|
+
export type PushSender = (channelId: string, userIds: number[], message: PushMessage<any>) => Promise<{
|
|
72
|
+
sent: number;
|
|
73
|
+
}>;
|
|
74
|
+
/** Host hook (runner / local backend / test harness): where `send` delivers to. */
|
|
75
|
+
export declare const setPushSender: (sender: PushSender | null) => void;
|
|
76
|
+
/** The ids of `send`'s first argument, each once; throws on what is not a user. */
|
|
77
|
+
export declare const pushTargetIds: (user: unknown) => number[];
|
|
78
|
+
export declare const pushChannel: <D extends Record<string, unknown> | undefined = undefined>() => PushChannel<D>;
|
|
79
|
+
export declare const isPushChannel: (v: unknown) => v is PushChannelRecord;
|
|
@@ -138,7 +138,7 @@ export type ElementStyle = PaddingStyle & MarginStyle & BaseStyle & PositionStyl
|
|
|
138
138
|
flex?: number | string;
|
|
139
139
|
flexGrow?: number;
|
|
140
140
|
flexShrink?: number;
|
|
141
|
-
|
|
141
|
+
flexBasis?: UIValue | `${number}%` | "auto";
|
|
142
142
|
alignSelf?: "flex-start" | "center" | "flex-end" | "stretch";
|
|
143
143
|
display?: "none" | "flex";
|
|
144
144
|
};
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "2.
|
|
1
|
+
export declare const SDK_VERSION = "2.3.0";
|
|
2
2
|
/** The major of a semver string, or null when it is not one. */
|
|
3
3
|
export declare const sdkMajor: (version: string | null | undefined) => number | null;
|
|
4
4
|
/** The `// sdk: <version>` line of a compiled bundle's header (sdk/src/compile/header.ts), read from
|