@shivaedev/contract 0.0.0 → 0.17.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 (94) hide show
  1. package/CHANGELOG.md +221 -0
  2. package/LICENSE +21 -0
  3. package/README.md +510 -1
  4. package/dist/automaticLive.d.ts +28 -0
  5. package/dist/automaticLive.d.ts.map +1 -0
  6. package/dist/automaticLive.js +63 -0
  7. package/dist/automaticLive.js.map +1 -0
  8. package/dist/bind.d.ts +51 -0
  9. package/dist/bind.d.ts.map +1 -0
  10. package/dist/bind.js +14 -0
  11. package/dist/bind.js.map +1 -0
  12. package/dist/contract.d.ts +33 -0
  13. package/dist/contract.d.ts.map +1 -0
  14. package/dist/contract.js +44 -0
  15. package/dist/contract.js.map +1 -0
  16. package/dist/internal/bindingOwner.d.ts +8 -0
  17. package/dist/internal/bindingOwner.d.ts.map +1 -0
  18. package/dist/internal/bindingOwner.js +16 -0
  19. package/dist/internal/bindingOwner.js.map +1 -0
  20. package/dist/internal/clientOperations.d.ts +21 -0
  21. package/dist/internal/clientOperations.d.ts.map +1 -0
  22. package/dist/internal/clientOperations.js +36 -0
  23. package/dist/internal/clientOperations.js.map +1 -0
  24. package/dist/internal/liveInvalidation.d.ts +12 -0
  25. package/dist/internal/liveInvalidation.d.ts.map +1 -0
  26. package/dist/internal/liveInvalidation.js +14 -0
  27. package/dist/internal/liveInvalidation.js.map +1 -0
  28. package/dist/internal/makeHintPolicy.d.ts +4 -0
  29. package/dist/internal/makeHintPolicy.d.ts.map +1 -0
  30. package/dist/internal/makeHintPolicy.js +25 -0
  31. package/dist/internal/makeHintPolicy.js.map +1 -0
  32. package/dist/internal/queryReactivity.d.ts +5 -0
  33. package/dist/internal/queryReactivity.d.ts.map +1 -0
  34. package/dist/internal/queryReactivity.js +96 -0
  35. package/dist/internal/queryReactivity.js.map +1 -0
  36. package/dist/keys.d.ts +34 -0
  37. package/dist/keys.d.ts.map +1 -0
  38. package/dist/keys.js +25 -0
  39. package/dist/keys.js.map +1 -0
  40. package/dist/live.d.ts +39 -0
  41. package/dist/live.d.ts.map +1 -0
  42. package/dist/live.js +98 -0
  43. package/dist/live.js.map +1 -0
  44. package/dist/makeLiveServer.d.ts +20 -0
  45. package/dist/makeLiveServer.d.ts.map +1 -0
  46. package/dist/makeLiveServer.js +62 -0
  47. package/dist/makeLiveServer.js.map +1 -0
  48. package/dist/operation.d.ts +66 -0
  49. package/dist/operation.d.ts.map +1 -0
  50. package/dist/operation.js +29 -0
  51. package/dist/operation.js.map +1 -0
  52. package/dist/publicConfig.d.ts +20 -0
  53. package/dist/publicConfig.d.ts.map +1 -0
  54. package/dist/publicConfig.js +8 -0
  55. package/dist/publicConfig.js.map +1 -0
  56. package/dist/queryCoalesceWindow.d.ts +4 -0
  57. package/dist/queryCoalesceWindow.d.ts.map +1 -0
  58. package/dist/queryCoalesceWindow.js +11 -0
  59. package/dist/queryCoalesceWindow.js.map +1 -0
  60. package/dist/readPolicy.d.ts +10 -0
  61. package/dist/readPolicy.d.ts.map +1 -0
  62. package/dist/readPolicy.js +24 -0
  63. package/dist/readPolicy.js.map +1 -0
  64. package/dist/rejection.d.ts +41 -0
  65. package/dist/rejection.d.ts.map +1 -0
  66. package/dist/rejection.js +16 -0
  67. package/dist/rejection.js.map +1 -0
  68. package/dist/resume.d.ts +17 -0
  69. package/dist/resume.d.ts.map +1 -0
  70. package/dist/resume.js +28 -0
  71. package/dist/resume.js.map +1 -0
  72. package/dist/serverMetadata.d.ts +42 -0
  73. package/dist/serverMetadata.d.ts.map +1 -0
  74. package/dist/serverMetadata.js +27 -0
  75. package/dist/serverMetadata.js.map +1 -0
  76. package/package.json +73 -4
  77. package/src/automaticLive.ts +93 -0
  78. package/src/bind.ts +103 -0
  79. package/src/contract.ts +140 -0
  80. package/src/internal/bindingOwner.ts +24 -0
  81. package/src/internal/clientOperations.ts +74 -0
  82. package/src/internal/liveInvalidation.ts +21 -0
  83. package/src/internal/makeHintPolicy.ts +40 -0
  84. package/src/internal/queryReactivity.ts +109 -0
  85. package/src/keys.ts +62 -0
  86. package/src/live.ts +122 -0
  87. package/src/makeLiveServer.ts +76 -0
  88. package/src/operation.ts +145 -0
  89. package/src/publicConfig.ts +9 -0
  90. package/src/queryCoalesceWindow.ts +13 -0
  91. package/src/readPolicy.ts +33 -0
  92. package/src/rejection.ts +91 -0
  93. package/src/resume.ts +44 -0
  94. package/src/serverMetadata.ts +50 -0
package/src/resume.ts ADDED
@@ -0,0 +1,44 @@
1
+ import * as Atom from "effect/reactivity/Atom";
2
+
3
+ export type ResumeSource = (resume: () => void) => () => void;
4
+
5
+ type ResumeEvent = "online" | "visibilitychange";
6
+
7
+ export interface ResumeWindow {
8
+ readonly addEventListener: (type: ResumeEvent, listener: () => void) => void;
9
+ readonly document: { readonly visibilityState: string };
10
+ readonly removeEventListener: (type: ResumeEvent, listener: () => void) => void;
11
+ }
12
+
13
+ export interface ResumeOptions {
14
+ readonly native?: ResumeSource;
15
+ readonly window?: ResumeWindow;
16
+ }
17
+
18
+ function whileVisible(target: ResumeWindow, type: ResumeEvent): ResumeSource {
19
+ return (resume) => {
20
+ function visible() {
21
+ if (target.document.visibilityState === "visible") {
22
+ resume();
23
+ }
24
+ }
25
+ target.addEventListener(type, visible);
26
+ return () => target.removeEventListener(type, visible);
27
+ };
28
+ }
29
+
30
+ export function resumeSignal({ window, native }: ResumeOptions): Atom.Atom<number> {
31
+ const browser = window === undefined ? [] : [whileVisible(window, "visibilitychange"), whileVisible(window, "online")];
32
+ const sources = native === undefined ? browser : [...browser, native];
33
+ return Atom.readable((get) => {
34
+ let count = 0;
35
+ function resume() {
36
+ count += 1;
37
+ get.setSelf(count);
38
+ }
39
+ for (const source of sources) {
40
+ get.addFinalizer(source(resume));
41
+ }
42
+ return count;
43
+ });
44
+ }
@@ -0,0 +1,50 @@
1
+ import { Context, Schema } from "effect";
2
+ import { Rpc } from "effect/rpc";
3
+ import type { Key } from "#keys.ts";
4
+ import { LiveHint } from "#live.ts";
5
+ import type { CommandShape, QueryShape } from "#operation.ts";
6
+
7
+ export class QueryReads extends Context.Service<QueryReads, QueryShape["reads"]>()("@shivaedev/contract/QueryReads") {}
8
+
9
+ export class CommandInvalidation extends Context.Service<CommandInvalidation, CommandShape["invalidates"]>()(
10
+ "@shivaedev/contract/CommandInvalidation",
11
+ ) {}
12
+
13
+ export class KeyScope extends Context.Service<KeyScope, "session">()("@shivaedev/contract/KeyScope") {}
14
+
15
+ export interface QueryReference {
16
+ readonly payload: unknown;
17
+ readonly query: string;
18
+ }
19
+
20
+ type ReferenceSchema<TQuery extends QueryShape> = TQuery extends QueryShape
21
+ ? Schema.Struct<{ query: Schema.Literal<TQuery["name"]>; payload: TQuery["payload"] }>
22
+ : never;
23
+
24
+ export class ChangesReads extends Context.Service<ChangesReads, (references: readonly QueryReference[]) => readonly Key[]>()(
25
+ "@shivaedev/contract/ChangesReads",
26
+ ) {}
27
+
28
+ export function queryKeys(queries: readonly QueryShape[], requested: readonly QueryReference[]): readonly Key[] {
29
+ return requested.flatMap((reference) => {
30
+ const declared = queries.find((candidate) => candidate.name === reference.query);
31
+ if (declared === undefined) {
32
+ throw new Error(`Unknown query: ${reference.query}`);
33
+ }
34
+ return declared.reads(reference.payload);
35
+ });
36
+ }
37
+
38
+ function referenceSchemas<const TQueries extends readonly QueryShape[]>(
39
+ queries: TQueries,
40
+ ): Schema.$Array<Schema.Union<readonly ReferenceSchema<TQueries[number]>[]>>;
41
+ function referenceSchemas(queries: readonly QueryShape[]) {
42
+ return Schema.Array(Schema.Union(queries.map((query) => Schema.Struct({ payload: query.payload, query: Schema.Literal(query.name) }))));
43
+ }
44
+
45
+ export function changesRpc<const TName extends string, const TQueries extends readonly QueryShape[]>(name: TName, queries: TQueries) {
46
+ return Rpc.make(`${name}.$changes`, { payload: { queries: referenceSchemas(queries) }, stream: true, success: LiveHint }).annotate(
47
+ ChangesReads,
48
+ (requested) => queryKeys(queries, requested),
49
+ );
50
+ }