@pylonsync/functions 0.16.1 → 0.17.1

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/index.d.ts CHANGED
@@ -26,4 +26,4 @@ export type { WorkflowDefinition, WorkflowRun, WorkflowRunRequest, WorkflowRunne
26
26
  export { resetDb, installTestIsolation } from "./testing";
27
27
  export { slugifyName, availableSlug } from "./slugify";
28
28
  export type { SsrResponse, SsrCookieOptions, SsrMetadata, Sitemap, SitemapEntry, Robots, RobotsRule, } from "./ssr-runtime";
29
- export type { QueryCtx, MutationCtx, ActionCtx, DbReader, DbWriter, Stream, Scheduler, AuthInfo, AuthMode, AuthRequirement, FnDefinition, Validator, AnyValidator, ValidatorSchema, InferValidator, InferArgs, RequireMember, RequireMemberOptions, Shards, ShardsReader, ShardInfo, MemberRow, Workflows, VectorSearchQuery, VectorSearchResult, SearchResult, PaginationResult, Llm, LlmMessage, LlmContentBlock, LlmTool, LlmCompleteRequest, LlmCompleteResponse, LlmStreamEvent, Rooms, Domains, TenantDomainResult, TenantDomainDns, DomainAvailability, DomainContact, RegisterDomainOptions, RegisteredDomainResult, } from "./types";
29
+ export type { QueryCtx, MutationCtx, ActionCtx, DbReader, DbWriter, Stream, Scheduler, AuthInfo, AuthMode, AuthRequirement, FnDefinition, Validator, AnyValidator, ValidatorSchema, InferValidator, InferArgs, RequireMember, RequireMemberOptions, Shards, ShardsReader, ShardsWriter, ShardInfo, ShardTransfer, MemberRow, Workflows, VectorSearchQuery, VectorSearchResult, SearchResult, PaginationResult, Llm, LlmMessage, LlmContentBlock, LlmTool, LlmCompleteRequest, LlmCompleteResponse, LlmStreamEvent, Rooms, Domains, TenantDomainResult, TenantDomainDns, DomainAvailability, DomainContact, RegisterDomainOptions, RegisteredDomainResult, } from "./types";
package/dist/types.d.ts CHANGED
@@ -790,9 +790,63 @@ export interface Shards {
790
790
  get(shardId: string): Promise<ShardInfo | null>;
791
791
  /** Every running shard. */
792
792
  list(): Promise<ShardInfo[]>;
793
+ /**
794
+ * Move a player from shard `from` to shard `to` (a zone line, a dungeon,
795
+ * a match), possibly on another machine. The source module's
796
+ * `transfer_out` removes the player's entity and the target's
797
+ * `transfer_in` adds it, with its state. The player's connections get a
798
+ * transfer frame with a ticket for `to` (for the same user, with
799
+ * `opts.claims`), and the client libraries reconnect there. The target's
800
+ * `transfer_in` sees that ticket to decide. Actions only.
801
+ *
802
+ * On an error the player stays in `from`. Throws
803
+ * `SHARD_TRANSFER_REFUSED` when a module refuses,
804
+ * `SHARD_TRANSFER_NO_PLAYER` when `from` has no entity for the
805
+ * subscriber, `SHARD_TRANSFER_BUSY` while it is already moving,
806
+ * `SHARD_TRANSFER_UNSUPPORTED`, or `SHARD_NOT_FOUND`.
807
+ */
808
+ transfer(from: string, subscriberId: string, to: string, opts?: {
809
+ claims?: Record<string, unknown>;
810
+ }): Promise<ShardTransfer>;
811
+ /**
812
+ * Send a message to shards on any machine: `"shard:<id>"` for one,
813
+ * `"group:<name>"` for the shards whose module lists that group, `"all"`
814
+ * for every shard. The module's `on_message` gets `topic` and `data` as
815
+ * JSON bytes at the start of its next tick, with an empty sender. For a
816
+ * GM command, a realm-wide event, or a server-side alert. Actions only.
817
+ *
818
+ * Delivery is at most once: a shard that is stopped, busy (1024 messages
819
+ * waiting), or on a machine that cannot be reached, misses it. Throws
820
+ * `SHARD_MESSAGE_INVALID` for a bad target, an empty topic (at most 128
821
+ * bytes), or data over 64 KB.
822
+ */
823
+ publish(to: string, topic: string, data?: unknown): Promise<void>;
824
+ /**
825
+ * Send `input` to shard `shardId`, on any machine. The module's
826
+ * `apply_input` gets it on the shard's next tick, from the empty
827
+ * subscriber id (no connection can have it), in the shard's input
828
+ * format. For a GM command, or a keep claimed on the website.
829
+ *
830
+ * In a mutation the input is sent after the mutation commits, and not
831
+ * at all when it rolls back. Delivery is at most once: a shard that
832
+ * stops, a full input queue, or a machine that cannot be reached loses
833
+ * it. In an action, a shard on this machine has it when this resolves.
834
+ * Throws `SHARD_INPUT_INVALID` for a bad id or an input over 64 KB of
835
+ * JSON, and in an action `SHARD_NOT_FOUND` or `SHARD_BUSY`.
836
+ */
837
+ send(shardId: string, input: unknown): Promise<void>;
793
838
  }
794
- /** `ctx.shards` in a query or mutation: tickets and reads, no start or stop. */
839
+ /** A finished `ctx.shards.transfer`. */
840
+ export interface ShardTransfer {
841
+ /** The shard the player is in now. */
842
+ shard: string;
843
+ /** A ticket for it, which the transfer frame also carried. */
844
+ ticket: string;
845
+ }
846
+ /** `ctx.shards` in a query: tickets and reads, no start or stop. */
795
847
  export type ShardsReader = Pick<Shards, "ticket" | "get" | "list">;
848
+ /** `ctx.shards` in a mutation: a query's, and inputs sent after the commit. */
849
+ export type ShardsWriter = Pick<Shards, "ticket" | "get" | "list" | "send">;
796
850
  /** A running shard, from `ctx.shards.create`, `get`, or `list`. */
797
851
  export interface ShardInfo {
798
852
  id: string;
@@ -863,8 +917,8 @@ export interface MutationCtx<R extends AuthRequirement = "optional"> {
863
917
  workflows: Workflows;
864
918
  /** Signed file-download URLs — see {@link Files}. */
865
919
  files: Files;
866
- /** Shard tickets and reads — see {@link Shards}. */
867
- shards: ShardsReader;
920
+ /** Shard tickets, reads, and inputs after the commit — see {@link Shards}. */
921
+ shards: ShardsWriter;
868
922
  /** Create a typed error that triggers rollback. */
869
923
  error(code: string, message: string): Error;
870
924
  /** Assert org membership (optionally a role) — see {@link RequireMember}. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pylonsync/functions",
3
- "version": "0.16.1",
3
+ "version": "0.17.1",
4
4
  "description": "TypeScript function runtime for pylon — defines server-side queries, mutations, and actions.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/index.ts CHANGED
@@ -75,7 +75,9 @@ export type {
75
75
  RequireMemberOptions,
76
76
  Shards,
77
77
  ShardsReader,
78
+ ShardsWriter,
78
79
  ShardInfo,
80
+ ShardTransfer,
79
81
  MemberRow,
80
82
  Workflows,
81
83
  VectorSearchQuery,
package/src/runtime.ts CHANGED
@@ -24,6 +24,7 @@ import type {
24
24
  Files,
25
25
  Shards,
26
26
  ShardInfo,
27
+ ShardTransfer,
27
28
  Stream,
28
29
  Scheduler,
29
30
  Llm,
@@ -555,6 +556,33 @@ function buildShards(callId: string): Shards {
555
556
  async list() {
556
557
  return rpc(callId, { type: "shard_op", op: "list" }) as Promise<ShardInfo[]>;
557
558
  },
559
+ async publish(to, topic, data) {
560
+ await rpc(callId, {
561
+ type: "shard_op",
562
+ op: "publish",
563
+ to,
564
+ topic,
565
+ params: data ?? null,
566
+ });
567
+ },
568
+ async send(shardId, input) {
569
+ await rpc(callId, {
570
+ type: "shard_op",
571
+ op: "send",
572
+ id: shardId,
573
+ params: input ?? null,
574
+ });
575
+ },
576
+ async transfer(from, subscriberId, to, opts) {
577
+ return rpc(callId, {
578
+ type: "shard_op",
579
+ op: "transfer",
580
+ id: from,
581
+ subscriber: subscriberId,
582
+ to,
583
+ claims: opts?.claims ?? null,
584
+ }) as Promise<ShardTransfer>;
585
+ },
558
586
  };
559
587
  }
560
588
 
package/src/types.ts CHANGED
@@ -892,11 +892,73 @@ export interface Shards {
892
892
 
893
893
  /** Every running shard. */
894
894
  list(): Promise<ShardInfo[]>;
895
+
896
+ /**
897
+ * Move a player from shard `from` to shard `to` (a zone line, a dungeon,
898
+ * a match), possibly on another machine. The source module's
899
+ * `transfer_out` removes the player's entity and the target's
900
+ * `transfer_in` adds it, with its state. The player's connections get a
901
+ * transfer frame with a ticket for `to` (for the same user, with
902
+ * `opts.claims`), and the client libraries reconnect there. The target's
903
+ * `transfer_in` sees that ticket to decide. Actions only.
904
+ *
905
+ * On an error the player stays in `from`. Throws
906
+ * `SHARD_TRANSFER_REFUSED` when a module refuses,
907
+ * `SHARD_TRANSFER_NO_PLAYER` when `from` has no entity for the
908
+ * subscriber, `SHARD_TRANSFER_BUSY` while it is already moving,
909
+ * `SHARD_TRANSFER_UNSUPPORTED`, or `SHARD_NOT_FOUND`.
910
+ */
911
+ transfer(
912
+ from: string,
913
+ subscriberId: string,
914
+ to: string,
915
+ opts?: { claims?: Record<string, unknown> },
916
+ ): Promise<ShardTransfer>;
917
+
918
+ /**
919
+ * Send a message to shards on any machine: `"shard:<id>"` for one,
920
+ * `"group:<name>"` for the shards whose module lists that group, `"all"`
921
+ * for every shard. The module's `on_message` gets `topic` and `data` as
922
+ * JSON bytes at the start of its next tick, with an empty sender. For a
923
+ * GM command, a realm-wide event, or a server-side alert. Actions only.
924
+ *
925
+ * Delivery is at most once: a shard that is stopped, busy (1024 messages
926
+ * waiting), or on a machine that cannot be reached, misses it. Throws
927
+ * `SHARD_MESSAGE_INVALID` for a bad target, an empty topic (at most 128
928
+ * bytes), or data over 64 KB.
929
+ */
930
+ publish(to: string, topic: string, data?: unknown): Promise<void>;
931
+
932
+ /**
933
+ * Send `input` to shard `shardId`, on any machine. The module's
934
+ * `apply_input` gets it on the shard's next tick, from the empty
935
+ * subscriber id (no connection can have it), in the shard's input
936
+ * format. For a GM command, or a keep claimed on the website.
937
+ *
938
+ * In a mutation the input is sent after the mutation commits, and not
939
+ * at all when it rolls back. Delivery is at most once: a shard that
940
+ * stops, a full input queue, or a machine that cannot be reached loses
941
+ * it. In an action, a shard on this machine has it when this resolves.
942
+ * Throws `SHARD_INPUT_INVALID` for a bad id or an input over 64 KB of
943
+ * JSON, and in an action `SHARD_NOT_FOUND` or `SHARD_BUSY`.
944
+ */
945
+ send(shardId: string, input: unknown): Promise<void>;
946
+ }
947
+
948
+ /** A finished `ctx.shards.transfer`. */
949
+ export interface ShardTransfer {
950
+ /** The shard the player is in now. */
951
+ shard: string;
952
+ /** A ticket for it, which the transfer frame also carried. */
953
+ ticket: string;
895
954
  }
896
955
 
897
- /** `ctx.shards` in a query or mutation: tickets and reads, no start or stop. */
956
+ /** `ctx.shards` in a query: tickets and reads, no start or stop. */
898
957
  export type ShardsReader = Pick<Shards, "ticket" | "get" | "list">;
899
958
 
959
+ /** `ctx.shards` in a mutation: a query's, and inputs sent after the commit. */
960
+ export type ShardsWriter = Pick<Shards, "ticket" | "get" | "list" | "send">;
961
+
900
962
  /** A running shard, from `ctx.shards.create`, `get`, or `list`. */
901
963
  export interface ShardInfo {
902
964
  id: string;
@@ -969,8 +1031,8 @@ export interface MutationCtx<R extends AuthRequirement = "optional"> {
969
1031
  workflows: Workflows;
970
1032
  /** Signed file-download URLs — see {@link Files}. */
971
1033
  files: Files;
972
- /** Shard tickets and reads — see {@link Shards}. */
973
- shards: ShardsReader;
1034
+ /** Shard tickets, reads, and inputs after the commit — see {@link Shards}. */
1035
+ shards: ShardsWriter;
974
1036
  /** Create a typed error that triggers rollback. */
975
1037
  error(code: string, message: string): Error;
976
1038
  /** Assert org membership (optionally a role) — see {@link RequireMember}. */