@synapse-sdk/client 0.3.6 → 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/types.d.ts CHANGED
@@ -41,6 +41,18 @@ export interface ConnectTarget {
41
41
  /**
42
42
  * The runtime, `https://host:4470` (the path to dial is learned from the runtime at every attempt). Through a relay: the relay with
43
43
  * the runtime's path, `https://<relay>/cluster/<cluster>/runtimes/<runtime_id>`, and `token`. A `jwt=` in the URL is taken as the token.
44
+ *
45
+ * Or, in Bun/Node, a target as the CLI's `-t` names it (anything without `<scheme>://`): `"infra-1@devel"` (runtime `infra-1`
46
+ * of cluster `devel`), `"infra-1"` (in the default cluster), `"arm@medatech/devel"` (an org's cluster, by its slug). The relay
47
+ * URL and the token come from the CLI's files on this machine (`~/.synapse/cluster.toml` and the tokens beside it), read again
48
+ * at every attempt, so a token the CLI refreshed is used on the next reconnect (`token` given here wins). The SDK only reads
49
+ * those files: `synapse login` and `synapse cluster login <cluster>` first. A name this machine does not know is
50
+ * `invalid_input`, a missing or expired token `unauthorized`, each naming the CLI command that fixes it.
51
+ *
52
+ * With a person signed in (`node.setAuth`), in a browser or in Bun/Node, the same names are resolved through the key
53
+ * server instead, from your clusters: `"infra-1@devel"`, `"arm@medatech/devel"` (the cluster is always named). A name
54
+ * not in your clusters is `invalid_input`; nobody signed in, or a sign-in the key server does not take, `unauthorized`.
55
+ * In a browser with nobody signed in, a name is refused at once (`invalid_input`): sign in, or pass the relay URL and a token.
44
56
  */
45
57
  url: string;
46
58
  /** The type to declare there; left out keeps the node's current one. */
@@ -51,7 +63,7 @@ export interface ConnectTarget {
51
63
  userId?: string;
52
64
  /** The credential to present there; left out keeps the node's current one. Never printed. */
53
65
  credential?: string;
54
- /** Pin of *this* broker's self-signed certificate (SHA-256 hex). Absent: `SYNAPSE_BROKER_CERT_SHA256`, then the broker's helper, then unpinned (per attempt). */
66
+ /** Pin of *this* runtime's self-signed certificate (SHA-256 hex). Absent: `SYNAPSE_BROKER_CERT_SHA256`, then, for a runtime URL (no path), its helper; a URL naming a root (a relay) connects unpinned against the system's roots (per attempt). */
55
67
  brokerCertSha256?: string;
56
68
  /** The relay token for *this* target; left out = no token (a token for another runtime would be refused). Never printed. */
57
69
  token?: string;
@@ -85,6 +97,42 @@ export type ConnectionState = {
85
97
  status: "failed";
86
98
  error: SynapseError;
87
99
  };
100
+ /**
101
+ * Gives the signed-in person's credential for the key server, fetched each time the node asks it (`setAuth`);
102
+ * `null` or `undefined` means nobody is signed in.
103
+ */
104
+ export type FetchToken = () => Promise<string | null | undefined>;
105
+ /** The key server's answer about the signed-in person (`node.discover()`): the relay to dial and your clusters with their runtimes. */
106
+ export interface Discovery {
107
+ /** The relay a runtime of these clusters is dialed through. */
108
+ relay: string;
109
+ /** The signed-in person. */
110
+ userId: string;
111
+ /** Your clusters: your own, and those of the organizations you belong to. */
112
+ clusters: {
113
+ id: string;
114
+ name: string;
115
+ /** Who owns it: `kind` `user` (yours) or `org`, its `id`, and the organization's `slug` when it has one. */
116
+ owner: {
117
+ kind: string;
118
+ id: string;
119
+ slug?: string;
120
+ };
121
+ /** How `connect()` names it: `name` for yours, `<slug>/<name>` (or `<org id>/<name>`) for an organization's: `"infra-1@" + label`. */
122
+ label: string;
123
+ /** Its runtimes, name → runtime id. */
124
+ runtimes: Record<string, string>;
125
+ }[];
126
+ }
127
+ /**
128
+ * `node.discovery`: `idle` with nobody signed in (or just after `setAuth`), `pending` while the key server is asked,
129
+ * `success` with the answer, `error` with why it failed (`data` still holds the last answer, if there was one).
130
+ */
131
+ export interface DiscoveryState {
132
+ status: "idle" | "pending" | "success" | "error";
133
+ data?: Discovery;
134
+ error?: SynapseError;
135
+ }
88
136
  /** This node's identity and the current session's hello facts; empty strings between sessions. */
89
137
  export interface Info {
90
138
  name: string;
@@ -440,6 +488,8 @@ export interface Hardpoint {
440
488
  /**
441
489
  * An entity of the scene. The fields below are the ones the runtime and the early users read;
442
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).
443
493
  */
444
494
  export interface SceneEntity {
445
495
  /** A ULID; never changes. */
@@ -572,8 +622,8 @@ export interface EntityAuthored {
572
622
  * not have: its `not_found`). A view by name whose name no entity holds has no id to send to: `not_found`
573
623
  * (`data: { name }`), nothing sent. Detached: `project_inactive`.
574
624
  */
575
- set<K extends keyof SceneEntity & string>(component: K, value: SceneEntity[K]): Promise<void>;
576
- set(components: Partial<SceneEntity>): Promise<void>;
625
+ set<K extends keyof SceneEntity & string>(component: K, value: PatchSet[K]): Promise<void>;
626
+ set(components: PatchSet): Promise<void>;
577
627
  }
578
628
  /** An entity view's live plane (`view.live`). Reads as the view does: nothing once the handle is detached or closed. */
579
629
  export interface EntityLive {
@@ -618,6 +668,12 @@ export interface SceneStatus {
618
668
  /** Lane rows dropped because their id's claim was refused (rows parked while it was asked, and rows written while refused). */
619
669
  unclaimedDrops: number;
620
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
+ };
621
677
  /** An authored change as the runtime applied it (a diff op of the scene's `authored` track). */
622
678
  export type SceneDiffOp = {
623
679
  op: "spawn";
@@ -631,7 +687,7 @@ export type SceneDiffOp = {
631
687
  } | {
632
688
  op: "patch";
633
689
  id: string;
634
- set: Partial<SceneEntity>;
690
+ set: PatchSet;
635
691
  rev: number;
636
692
  } | {
637
693
  op: "reparent";
@@ -662,7 +718,7 @@ export type SceneOp = {
662
718
  } | {
663
719
  op: "patch";
664
720
  id: string;
665
- set: Partial<SceneEntity>;
721
+ set: PatchSet;
666
722
  } | {
667
723
  op: "reparent";
668
724
  id: string;
@@ -685,20 +741,22 @@ export type SceneSpawnOptions = {
685
741
  parent?: string | SceneEntityView | null;
686
742
  id?: string;
687
743
  } & Partial<Omit<SceneEntity, "id" | "kind" | "name" | "parent" | "order" | "meta">>;
688
- /** Where `reparent` puts the entity among its new siblings (default: after the last): a sibling by its id or its view. */
689
- export type ScenePlace = {
690
- before: string | SceneEntityView;
691
- } | {
692
- after: string | SceneEntityView;
693
- };
694
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). */
695
745
  export interface SceneTxn {
696
746
  /** Spawns an entity of `kind`; returns its id. */
697
747
  spawn(kind: SceneKind, opts: SceneSpawnOptions): string;
698
- /** Sets components of the entity (an object merges into an object one level deep). */
699
- patch(entity: string | SceneEntityView, set: Partial<SceneEntity>): void;
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;
700
750
  rename(entity: string | SceneEntityView, name: string): void;
701
- reparent(entity: string | SceneEntityView, parent: string | SceneEntityView | null, place?: ScenePlace): void;
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;
702
760
  despawn(entity: string | SceneEntityView, opts?: {
703
761
  cascade?: boolean;
704
762
  }): void;
@@ -749,7 +807,8 @@ export interface SceneAuthored {
749
807
  txn(build: (t: SceneTxn) => void): Promise<void>;
750
808
  /** Spawns an entity; its id, once the entities show it. */
751
809
  spawn(kind: SceneKind, opts: SceneSpawnOptions): Promise<string>;
752
- patch(entity: string | SceneEntityView, set: Partial<SceneEntity>): Promise<void>;
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>;
753
812
  /**
754
813
  * A builder's one verb, keyed by `name`; resolves with the entity's view (by id: that entity) once the entities show
755
814
  * it. The id is the runtime's answer, never the copy's: `spawn(kind, { name, parent, ...components })` (a fresh id) is
@@ -765,7 +824,16 @@ export interface SceneAuthored {
765
824
  id?: never;
766
825
  }): Promise<SceneEntityView>;
767
826
  rename(entity: string | SceneEntityView, name: string): Promise<void>;
768
- reparent(entity: string | SceneEntityView, parent: string | SceneEntityView | null, place?: ScenePlace): Promise<void>;
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>;
769
837
  despawn(entity: string | SceneEntityView, opts?: {
770
838
  cascade?: boolean;
771
839
  }): Promise<void>;
@@ -976,6 +1044,21 @@ export interface Tasks {
976
1044
  /** Stops every project task (also when none ran). Robot tasks are not touched. */
977
1045
  stopProjectTasks(): Promise<void>;
978
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
+ };
979
1062
  export interface Catalog {
980
1063
  readonly topics: Readonly<Record<string, {
981
1064
  desc?: TrackDesc;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synapse-sdk/client",
3
- "version": "0.3.6",
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,8 +14,9 @@
14
14
  "dist"
15
15
  ],
16
16
  "dependencies": {
17
- "@synapse-sdk/core": "0.3.6",
18
- "@moq/net": "0.4.2"
17
+ "@synapse-sdk/core": "0.3.8",
18
+ "@moq/net": "0.4.2",
19
+ "smol-toml": "1.9.0"
19
20
  },
20
21
  "peerDependencies": {
21
22
  "@moq/web-transport": "0.1.5"