@synapse-sdk/client 0.3.7 → 0.3.8
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/scene.d.ts +20 -5
- package/dist/scene.js +48 -11
- package/dist/synapse.d.ts +6 -1
- package/dist/synapse.js +5 -0
- package/dist/types.d.ts +50 -15
- package/package.json +2 -2
package/dist/scene.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { SynapseError, type ErrorBody, type ProjectSnapshot } from "@synapse-sdk
|
|
|
3
3
|
import type { Node } from "./node.ts";
|
|
4
4
|
import { StreamWriter, type Session } from "./session.ts";
|
|
5
5
|
import type { Warn } from "./topics.ts";
|
|
6
|
-
import type { LiveJoints, LivePose, LiveRemoved, LiveState, Quat, SceneAuthored, SceneDiffOp, SceneEntity, SceneEntityLive, SceneEntityRef, SceneEntityView, SceneHandle, SceneKind, SceneLive, SceneOp,
|
|
6
|
+
import type { LiveJoints, LivePose, LiveRemoved, LiveState, Quat, SceneAuthored, SceneDiffOp, SceneEntity, SceneEntityLive, SceneEntityRef, SceneEntityView, SceneHandle, SceneKind, SceneLive, SceneOp, SceneSpawnOptions, SceneState, SceneStatus, SceneTree, SceneTxn, SceneView, Vec3 } from "./types.ts";
|
|
7
7
|
import { AsyncQueue, type Deferred, type StateValue } from "./util.ts";
|
|
8
8
|
/** How many batches a feed may fall behind before it is ended (the store's `STORE_FEED_CAP`). */
|
|
9
9
|
export declare const SCENE_FEED_CAP = 256;
|
|
@@ -12,6 +12,9 @@ export declare const PATCH_PROTECTED: readonly string[];
|
|
|
12
12
|
type Entities = Map<string, SceneEntity>;
|
|
13
13
|
/** An entity named by its id or by a view of it (the id the view names now). */
|
|
14
14
|
type EntityArg = string | SceneEntityView;
|
|
15
|
+
/** A patch's `set` and `reparent`'s options, as the public interfaces take them. */
|
|
16
|
+
type PatchSet = Parameters<SceneTxn["patch"]>[1];
|
|
17
|
+
type ReparentOptions = NonNullable<Parameters<SceneTxn["reparent"]>[2]>;
|
|
15
18
|
/**
|
|
16
19
|
* A fresh entity id: a ULID (26 Crockford base-32 characters) made from a UUIDv7 (48-bit ms, version,
|
|
17
20
|
* 74 random bits, variant), so ids sort by the time they were minted; within one millisecond the
|
|
@@ -30,6 +33,14 @@ export declare function orderBetween(left: string | null | undefined, right: str
|
|
|
30
33
|
* prototype's rule). A cycle cannot come from the runtime; were one there, it is cut where it closes.
|
|
31
34
|
*/
|
|
32
35
|
export declare function treeOf(entities: Readonly<Record<string, SceneEntity>>): SceneTree;
|
|
36
|
+
/**
|
|
37
|
+
* The runtime's patch merge (`merge_set`): merges one level deep; a null deletes the key it names. A top-level null
|
|
38
|
+
* removes the component; an object merges into an object component key by key, a null sub-key removing that sub-key;
|
|
39
|
+
* an object given for a component that is absent or not an object replaces it without its null sub-keys, and nulls
|
|
40
|
+
* alone leave no component (an explicitly given `{}` is kept); any other value replaces. `undefined` is not given (the
|
|
41
|
+
* encoder skips it).
|
|
42
|
+
*/
|
|
43
|
+
export declare function mergeSet(into: Record<string, unknown>, set: Record<string, unknown>): Record<string, unknown>;
|
|
33
44
|
/**
|
|
34
45
|
* One authoring batch being built (`txn`): the ops it sends as one atomic `apply`. Ops on an entity
|
|
35
46
|
* spawned in the same batch fold into its spawn: a patch (of keys a patch may set) or a rename merges
|
|
@@ -41,11 +52,15 @@ export declare class Txn implements SceneTxn {
|
|
|
41
52
|
get ops(): readonly SceneOp[];
|
|
42
53
|
/** Spawns an entity of `kind` under `opts.parent` (default the world root) with the components given (`layer` `authored` when not given, else `calibration`; a live entity is not spawned here, it comes from `scene.live.upsert`); its id is minted here (or `opts.id`, a known one) and returned. No `order` is sent: the runtime appends it after its siblings. */
|
|
43
54
|
spawn(kind: SceneKind, opts: SceneSpawnOptions): string;
|
|
44
|
-
/** Sets components of the entity
|
|
45
|
-
patch(entity: EntityArg, set:
|
|
55
|
+
/** Sets components of the entity: merges one level deep; a null deletes the key it names. */
|
|
56
|
+
patch(entity: EntityArg, set: PatchSet): void;
|
|
46
57
|
rename(entity: EntityArg, name: string): void;
|
|
47
|
-
/**
|
|
48
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Moves the entity under `parent` (`null`: the world root), `before` or `after` a sibling (default: after the last).
|
|
60
|
+
* By default it keeps its world pose (the runtime's default: nothing sent); `preserveWorld: false` sends
|
|
61
|
+
* `preserve_world: false`, and it keeps its local xform.
|
|
62
|
+
*/
|
|
63
|
+
reparent(entity: EntityArg, parent: EntityArg | null, opts?: ReparentOptions): void;
|
|
49
64
|
/** Despawns the entity (`cascade`: with its subtree). One spawned in this batch is cancelled instead, unless it has children spawned in the batch and `cascade` is off (then the runtime decides). */
|
|
50
65
|
despawn(entity: EntityArg, opts?: {
|
|
51
66
|
cascade?: boolean;
|
package/dist/scene.js
CHANGED
|
@@ -231,14 +231,45 @@ export function treeOf(entities) {
|
|
|
231
231
|
return build(null);
|
|
232
232
|
}
|
|
233
233
|
// -------------------------------------------------------------------------------------------- txn
|
|
234
|
-
/**
|
|
235
|
-
|
|
234
|
+
/**
|
|
235
|
+
* The runtime's patch merge (`merge_set`): merges one level deep; a null deletes the key it names. A top-level null
|
|
236
|
+
* removes the component; an object merges into an object component key by key, a null sub-key removing that sub-key;
|
|
237
|
+
* an object given for a component that is absent or not an object replaces it without its null sub-keys, and nulls
|
|
238
|
+
* alone leave no component (an explicitly given `{}` is kept); any other value replaces. `undefined` is not given (the
|
|
239
|
+
* encoder skips it).
|
|
240
|
+
*/
|
|
241
|
+
export function mergeSet(into, set) {
|
|
236
242
|
const out = { ...into };
|
|
237
243
|
for (const [k, v] of Object.entries(set)) {
|
|
238
244
|
if (v === undefined)
|
|
239
245
|
continue;
|
|
246
|
+
if (v === null) {
|
|
247
|
+
delete out[k];
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (!isObject(v)) {
|
|
251
|
+
out[k] = v;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const given = Object.entries(v).filter(([, s]) => s !== undefined);
|
|
240
255
|
const old = out[k];
|
|
241
|
-
|
|
256
|
+
if (isObject(old)) {
|
|
257
|
+
const next = { ...old };
|
|
258
|
+
for (const [s, sv] of given) {
|
|
259
|
+
if (sv === null)
|
|
260
|
+
delete next[s];
|
|
261
|
+
else
|
|
262
|
+
next[s] = sv;
|
|
263
|
+
}
|
|
264
|
+
out[k] = next;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
const kept = given.filter(([, s]) => s !== null);
|
|
268
|
+
if (kept.length === 0 && given.length > 0)
|
|
269
|
+
delete out[k];
|
|
270
|
+
else
|
|
271
|
+
out[k] = Object.fromEntries(kept);
|
|
272
|
+
}
|
|
242
273
|
}
|
|
243
274
|
return out;
|
|
244
275
|
}
|
|
@@ -264,7 +295,7 @@ export class Txn {
|
|
|
264
295
|
this.#ops.push({ op: "spawn", entity });
|
|
265
296
|
return id;
|
|
266
297
|
}
|
|
267
|
-
/** Sets components of the entity
|
|
298
|
+
/** Sets components of the entity: merges one level deep; a null deletes the key it names. */
|
|
268
299
|
patch(entity, set) {
|
|
269
300
|
const id = idOf(entity);
|
|
270
301
|
// A protected key is the runtime's to refuse: such a patch is sent as it is.
|
|
@@ -287,13 +318,19 @@ export class Txn {
|
|
|
287
318
|
}
|
|
288
319
|
this.#ops.push({ op: "rename", id, name });
|
|
289
320
|
}
|
|
290
|
-
/**
|
|
291
|
-
|
|
321
|
+
/**
|
|
322
|
+
* Moves the entity under `parent` (`null`: the world root), `before` or `after` a sibling (default: after the last).
|
|
323
|
+
* By default it keeps its world pose (the runtime's default: nothing sent); `preserveWorld: false` sends
|
|
324
|
+
* `preserve_world: false`, and it keeps its local xform.
|
|
325
|
+
*/
|
|
326
|
+
reparent(entity, parent, opts = {}) {
|
|
292
327
|
const op = { op: "reparent", id: idOf(entity), parent: parent === null ? null : idOf(parent, "parent") };
|
|
293
|
-
if (
|
|
294
|
-
op.before = idOf(
|
|
295
|
-
else if (
|
|
296
|
-
op.after = idOf(
|
|
328
|
+
if (opts.before !== undefined)
|
|
329
|
+
op.before = idOf(opts.before, "before");
|
|
330
|
+
else if (opts.after !== undefined)
|
|
331
|
+
op.after = idOf(opts.after, "after");
|
|
332
|
+
if (opts.preserveWorld === false)
|
|
333
|
+
op.preserve_world = false;
|
|
297
334
|
this.#ops.push(op);
|
|
298
335
|
}
|
|
299
336
|
/** Despawns the entity (`cascade`: with its subtree). One spawned in this batch is cancelled instead, unless it has children spawned in the batch and `cascade` is off (then the runtime decides). */
|
|
@@ -1972,7 +2009,7 @@ export class SceneHandleImpl {
|
|
|
1972
2009
|
patch: (entity, set) => this.#txn(t => t.patch(entity, set)),
|
|
1973
2010
|
upsert: (kind, opts) => this.#upsert(kind, opts),
|
|
1974
2011
|
rename: (entity, name) => this.#txn(t => t.rename(entity, name)),
|
|
1975
|
-
reparent: (entity, parent,
|
|
2012
|
+
reparent: (entity, parent, opts) => this.#txn(t => t.reparent(entity, parent, opts)),
|
|
1976
2013
|
despawn: (entity, opts) => this.#txn(t => t.despawn(entity, opts)),
|
|
1977
2014
|
setLocked: (entity, locked) => this.#txn(t => t.setLocked(entity, locked)),
|
|
1978
2015
|
});
|
package/dist/synapse.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type Age, type ErrorBody, type ProjectSnapshot, type ServiceContract, t
|
|
|
2
2
|
import { Node } from "./node.ts";
|
|
3
3
|
import { StoreHandleImpl } from "./store.ts";
|
|
4
4
|
import { type Warn } from "./topics.ts";
|
|
5
|
-
import type { CallOptions, Catalog, ConnectOptions, ConnectTarget, ConnectionState, Discovery, DiscoveryState, Envelope, FetchToken, Info, Metrics, Publisher, Registration, Run, ServeHandler, ServeOptions, SceneHandle, StoreHandle, StoreOptions, SubscribeOptions, Subscription, Tasks, View, ViewOptions } from "./types.ts";
|
|
5
|
+
import type { CallOptions, Catalog, ConnectOptions, ConnectTarget, ConnectionState, Discovery, DiscoveryState, Envelope, FetchToken, Info, Metrics, ProjectListing, Publisher, Registration, Run, ServeHandler, ServeOptions, SceneHandle, StoreHandle, StoreOptions, SubscribeOptions, Subscription, Tasks, View, ViewOptions } from "./types.ts";
|
|
6
6
|
import { type StateValue } from "./util.ts";
|
|
7
7
|
export { FIRST_CONNECT_GIVE_UP_MS } from "./node.ts";
|
|
8
8
|
export declare class Synapse implements AsyncDisposable {
|
|
@@ -133,6 +133,11 @@ export declare class Synapse implements AsyncDisposable {
|
|
|
133
133
|
* resolves once the demoted session is connected.
|
|
134
134
|
*/
|
|
135
135
|
leaveProject(): Promise<ProjectSnapshot>;
|
|
136
|
+
/**
|
|
137
|
+
* `synapse/project/list {}`: every project the runtime has, sorted by id: what each names (`name` when it has one,
|
|
138
|
+
* `scene_id`, `store_id`, whether it is the active one), or why it cannot be read (`error`). Changes nothing.
|
|
139
|
+
*/
|
|
140
|
+
listProjects(): Promise<ProjectListing>;
|
|
136
141
|
/**
|
|
137
142
|
* The robot's task declarations, what runs (`status`), what the runtime can run (`catalog`), and the verbs; the same
|
|
138
143
|
* object for the node's life. Each handle opens on its first touch and is the node's own (`node.close()` ends it).
|
package/dist/synapse.js
CHANGED
|
@@ -355,6 +355,11 @@ export class Synapse {
|
|
|
355
355
|
* resolves once the demoted session is connected.
|
|
356
356
|
*/
|
|
357
357
|
leaveProject() { return this.#projectCall("leave", {}); }
|
|
358
|
+
/**
|
|
359
|
+
* `synapse/project/list {}`: every project the runtime has, sorted by id: what each names (`name` when it has one,
|
|
360
|
+
* `scene_id`, `store_id`, whether it is the active one), or why it cannot be read (`error`). Changes nothing.
|
|
361
|
+
*/
|
|
362
|
+
listProjects() { return this.call("synapse/project/list", {}).result; }
|
|
358
363
|
// -------------------------------------------------------------------------------- tasks
|
|
359
364
|
#tasks;
|
|
360
365
|
/**
|
package/dist/types.d.ts
CHANGED
|
@@ -488,6 +488,8 @@ export interface Hardpoint {
|
|
|
488
488
|
/**
|
|
489
489
|
* An entity of the scene. The fields below are the ones the runtime and the early users read;
|
|
490
490
|
* every other key passes through untouched.
|
|
491
|
+
* A component is absent (none), `{}` (there, nothing specified yet: every field at its default) or
|
|
492
|
+
* specified; a null component or sub-key is never stored (a patch deletes the key it names, a spawn drops it).
|
|
491
493
|
*/
|
|
492
494
|
export interface SceneEntity {
|
|
493
495
|
/** A ULID; never changes. */
|
|
@@ -620,8 +622,8 @@ export interface EntityAuthored {
|
|
|
620
622
|
* not have: its `not_found`). A view by name whose name no entity holds has no id to send to: `not_found`
|
|
621
623
|
* (`data: { name }`), nothing sent. Detached: `project_inactive`.
|
|
622
624
|
*/
|
|
623
|
-
set<K extends keyof SceneEntity & string>(component: K, value:
|
|
624
|
-
set(components:
|
|
625
|
+
set<K extends keyof SceneEntity & string>(component: K, value: PatchSet[K]): Promise<void>;
|
|
626
|
+
set(components: PatchSet): Promise<void>;
|
|
625
627
|
}
|
|
626
628
|
/** An entity view's live plane (`view.live`). Reads as the view does: nothing once the handle is detached or closed. */
|
|
627
629
|
export interface EntityLive {
|
|
@@ -666,6 +668,12 @@ export interface SceneStatus {
|
|
|
666
668
|
/** Lane rows dropped because their id's claim was refused (rows parked while it was asked, and rows written while refused). */
|
|
667
669
|
unclaimedDrops: number;
|
|
668
670
|
}
|
|
671
|
+
type NullSubKeys<T> = T extends readonly unknown[] ? T : T extends object ? {
|
|
672
|
+
[S in keyof T]?: T[S] | null;
|
|
673
|
+
} : T;
|
|
674
|
+
type PatchSet = {
|
|
675
|
+
[K in keyof SceneEntity]?: unknown extends SceneEntity[K] ? unknown : NullSubKeys<NonNullable<SceneEntity[K]>> | null;
|
|
676
|
+
};
|
|
669
677
|
/** An authored change as the runtime applied it (a diff op of the scene's `authored` track). */
|
|
670
678
|
export type SceneDiffOp = {
|
|
671
679
|
op: "spawn";
|
|
@@ -679,7 +687,7 @@ export type SceneDiffOp = {
|
|
|
679
687
|
} | {
|
|
680
688
|
op: "patch";
|
|
681
689
|
id: string;
|
|
682
|
-
set:
|
|
690
|
+
set: PatchSet;
|
|
683
691
|
rev: number;
|
|
684
692
|
} | {
|
|
685
693
|
op: "reparent";
|
|
@@ -710,7 +718,7 @@ export type SceneOp = {
|
|
|
710
718
|
} | {
|
|
711
719
|
op: "patch";
|
|
712
720
|
id: string;
|
|
713
|
-
set:
|
|
721
|
+
set: PatchSet;
|
|
714
722
|
} | {
|
|
715
723
|
op: "reparent";
|
|
716
724
|
id: string;
|
|
@@ -733,20 +741,22 @@ export type SceneSpawnOptions = {
|
|
|
733
741
|
parent?: string | SceneEntityView | null;
|
|
734
742
|
id?: string;
|
|
735
743
|
} & Partial<Omit<SceneEntity, "id" | "kind" | "name" | "parent" | "order" | "meta">>;
|
|
736
|
-
/** Where `reparent` puts the entity among its new siblings (default: after the last): a sibling by its id or its view. */
|
|
737
|
-
export type ScenePlace = {
|
|
738
|
-
before: string | SceneEntityView;
|
|
739
|
-
} | {
|
|
740
|
-
after: string | SceneEntityView;
|
|
741
|
-
};
|
|
742
744
|
/** One authoring batch being built (`txn`): sent as one atomic `apply`. An entity is named by its id or by a view of it (`upsert`'s result). */
|
|
743
745
|
export interface SceneTxn {
|
|
744
746
|
/** Spawns an entity of `kind`; returns its id. */
|
|
745
747
|
spawn(kind: SceneKind, opts: SceneSpawnOptions): string;
|
|
746
|
-
/** Sets components of the entity
|
|
747
|
-
patch(entity: string | SceneEntityView, set:
|
|
748
|
+
/** Sets components of the entity: merges one level deep; a null deletes the key it names. */
|
|
749
|
+
patch(entity: string | SceneEntityView, set: PatchSet): void;
|
|
748
750
|
rename(entity: string | SceneEntityView, name: string): void;
|
|
749
|
-
|
|
751
|
+
/**
|
|
752
|
+
* Moves the entity under `parent` (`null`: the world root), `before` or `after` a sibling (default: after the last).
|
|
753
|
+
* By default it keeps its world pose (its local xform is recomputed); `preserveWorld: false` keeps its local xform.
|
|
754
|
+
*/
|
|
755
|
+
reparent(entity: string | SceneEntityView, parent: string | SceneEntityView | null, opts?: {
|
|
756
|
+
before?: string | SceneEntityView;
|
|
757
|
+
after?: string | SceneEntityView;
|
|
758
|
+
preserveWorld?: boolean;
|
|
759
|
+
}): void;
|
|
750
760
|
despawn(entity: string | SceneEntityView, opts?: {
|
|
751
761
|
cascade?: boolean;
|
|
752
762
|
}): void;
|
|
@@ -797,7 +807,8 @@ export interface SceneAuthored {
|
|
|
797
807
|
txn(build: (t: SceneTxn) => void): Promise<void>;
|
|
798
808
|
/** Spawns an entity; its id, once the entities show it. */
|
|
799
809
|
spawn(kind: SceneKind, opts: SceneSpawnOptions): Promise<string>;
|
|
800
|
-
|
|
810
|
+
/** Sets components of the entity: merges one level deep; a null deletes the key it names. */
|
|
811
|
+
patch(entity: string | SceneEntityView, set: PatchSet): Promise<void>;
|
|
801
812
|
/**
|
|
802
813
|
* A builder's one verb, keyed by `name`; resolves with the entity's view (by id: that entity) once the entities show
|
|
803
814
|
* it. The id is the runtime's answer, never the copy's: `spawn(kind, { name, parent, ...components })` (a fresh id) is
|
|
@@ -813,7 +824,16 @@ export interface SceneAuthored {
|
|
|
813
824
|
id?: never;
|
|
814
825
|
}): Promise<SceneEntityView>;
|
|
815
826
|
rename(entity: string | SceneEntityView, name: string): Promise<void>;
|
|
816
|
-
|
|
827
|
+
/**
|
|
828
|
+
* Moves the entity under `parent` (`null`: the world root), `before` or `after` a sibling (default: after the last).
|
|
829
|
+
* By default the entity keeps its world pose (its local xform is recomputed). With `preserveWorld: false` it keeps its
|
|
830
|
+
* local xform instead, so a tool moved to another flange snaps to it.
|
|
831
|
+
*/
|
|
832
|
+
reparent(entity: string | SceneEntityView, parent: string | SceneEntityView | null, opts?: {
|
|
833
|
+
before?: string | SceneEntityView;
|
|
834
|
+
after?: string | SceneEntityView;
|
|
835
|
+
preserveWorld?: boolean;
|
|
836
|
+
}): Promise<void>;
|
|
817
837
|
despawn(entity: string | SceneEntityView, opts?: {
|
|
818
838
|
cascade?: boolean;
|
|
819
839
|
}): Promise<void>;
|
|
@@ -1024,6 +1044,21 @@ export interface Tasks {
|
|
|
1024
1044
|
/** Stops every project task (also when none ran). Robot tasks are not touched. */
|
|
1025
1045
|
stopProjectTasks(): Promise<void>;
|
|
1026
1046
|
}
|
|
1047
|
+
/** The answer of `node.listProjects()` (`synapse/project/list`): every project the runtime has, sorted by id. */
|
|
1048
|
+
export interface ProjectListing {
|
|
1049
|
+
projects: ProjectEntry[];
|
|
1050
|
+
}
|
|
1051
|
+
/** One project of a {@link ProjectListing}: what its document names (`name` when it has one), or why it cannot be read (`error`). */
|
|
1052
|
+
export type ProjectEntry = {
|
|
1053
|
+
id: string;
|
|
1054
|
+
name?: string;
|
|
1055
|
+
scene_id: string;
|
|
1056
|
+
store_id: string;
|
|
1057
|
+
active: boolean;
|
|
1058
|
+
} | {
|
|
1059
|
+
id: string;
|
|
1060
|
+
error: string;
|
|
1061
|
+
};
|
|
1027
1062
|
export interface Catalog {
|
|
1028
1063
|
readonly topics: Readonly<Record<string, {
|
|
1029
1064
|
desc?: TrackDesc;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synapse-sdk/client",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "Synapse SDK client: connect a node to the runtime; topics, services, calls, store, video.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@synapse-sdk/core": "0.3.
|
|
17
|
+
"@synapse-sdk/core": "0.3.8",
|
|
18
18
|
"@moq/net": "0.4.2",
|
|
19
19
|
"smol-toml": "1.9.0"
|
|
20
20
|
},
|