jazz-tools 0.19.8 → 0.19.11

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 (154) hide show
  1. package/.turbo/turbo-build.log +56 -50
  2. package/CHANGELOG.md +30 -3
  3. package/dist/{chunk-2S3Z2CN6.js → chunk-HX5S6W5E.js} +372 -103
  4. package/dist/chunk-HX5S6W5E.js.map +1 -0
  5. package/dist/index.js +1 -1
  6. package/dist/inspector/account-switcher.d.ts +4 -0
  7. package/dist/inspector/account-switcher.d.ts.map +1 -0
  8. package/dist/inspector/chunk-C6BJPHBQ.js +4096 -0
  9. package/dist/inspector/chunk-C6BJPHBQ.js.map +1 -0
  10. package/dist/inspector/contexts/node.d.ts +19 -0
  11. package/dist/inspector/contexts/node.d.ts.map +1 -0
  12. package/dist/inspector/{custom-element-P76EIWEV.js → custom-element-GJVBPZES.js} +1011 -884
  13. package/dist/inspector/custom-element-GJVBPZES.js.map +1 -0
  14. package/dist/inspector/{viewer/new-app.d.ts → in-app.d.ts} +3 -3
  15. package/dist/inspector/in-app.d.ts.map +1 -0
  16. package/dist/inspector/index.d.ts +0 -11
  17. package/dist/inspector/index.d.ts.map +1 -1
  18. package/dist/inspector/index.js +56 -3910
  19. package/dist/inspector/index.js.map +1 -1
  20. package/dist/inspector/pages/home.d.ts +2 -0
  21. package/dist/inspector/pages/home.d.ts.map +1 -0
  22. package/dist/inspector/register-custom-element.js +1 -1
  23. package/dist/inspector/router/context.d.ts +12 -0
  24. package/dist/inspector/router/context.d.ts.map +1 -0
  25. package/dist/inspector/router/hash-router.d.ts +7 -0
  26. package/dist/inspector/router/hash-router.d.ts.map +1 -0
  27. package/dist/inspector/router/in-memory-router.d.ts +7 -0
  28. package/dist/inspector/router/in-memory-router.d.ts.map +1 -0
  29. package/dist/inspector/router/index.d.ts +5 -0
  30. package/dist/inspector/router/index.d.ts.map +1 -0
  31. package/dist/inspector/standalone.d.ts +6 -0
  32. package/dist/inspector/standalone.d.ts.map +1 -0
  33. package/dist/inspector/standalone.js +420 -0
  34. package/dist/inspector/standalone.js.map +1 -0
  35. package/dist/inspector/tests/router/hash-router.test.d.ts +2 -0
  36. package/dist/inspector/tests/router/hash-router.test.d.ts.map +1 -0
  37. package/dist/inspector/tests/router/in-memory-router.test.d.ts +2 -0
  38. package/dist/inspector/tests/router/in-memory-router.test.d.ts.map +1 -0
  39. package/dist/inspector/ui/modal.d.ts +1 -0
  40. package/dist/inspector/ui/modal.d.ts.map +1 -1
  41. package/dist/inspector/viewer/breadcrumbs.d.ts +1 -7
  42. package/dist/inspector/viewer/breadcrumbs.d.ts.map +1 -1
  43. package/dist/inspector/viewer/header.d.ts +7 -0
  44. package/dist/inspector/viewer/header.d.ts.map +1 -0
  45. package/dist/inspector/viewer/page-stack.d.ts +4 -13
  46. package/dist/inspector/viewer/page-stack.d.ts.map +1 -1
  47. package/dist/inspector/viewer/page.d.ts.map +1 -1
  48. package/dist/react/hooks.d.ts +1 -1
  49. package/dist/react/hooks.d.ts.map +1 -1
  50. package/dist/react/index.d.ts +1 -1
  51. package/dist/react/index.d.ts.map +1 -1
  52. package/dist/react/index.js +5 -1
  53. package/dist/react/index.js.map +1 -1
  54. package/dist/react-core/hooks.d.ts +59 -0
  55. package/dist/react-core/hooks.d.ts.map +1 -1
  56. package/dist/react-core/index.js +124 -36
  57. package/dist/react-core/index.js.map +1 -1
  58. package/dist/react-core/tests/testUtils.d.ts +1 -0
  59. package/dist/react-core/tests/testUtils.d.ts.map +1 -1
  60. package/dist/react-core/tests/useSuspenseAccount.test.d.ts +2 -0
  61. package/dist/react-core/tests/useSuspenseAccount.test.d.ts.map +1 -0
  62. package/dist/react-core/tests/useSuspenseCoState.test.d.ts +2 -0
  63. package/dist/react-core/tests/useSuspenseCoState.test.d.ts.map +1 -0
  64. package/dist/react-core/use.d.ts +3 -0
  65. package/dist/react-core/use.d.ts.map +1 -0
  66. package/dist/react-native/index.js +5 -1
  67. package/dist/react-native/index.js.map +1 -1
  68. package/dist/react-native-core/crypto/RNCrypto.d.ts +2 -0
  69. package/dist/react-native-core/crypto/RNCrypto.d.ts.map +1 -0
  70. package/dist/react-native-core/crypto/RNCrypto.js +3 -0
  71. package/dist/react-native-core/crypto/RNCrypto.js.map +1 -0
  72. package/dist/react-native-core/hooks.d.ts +1 -1
  73. package/dist/react-native-core/hooks.d.ts.map +1 -1
  74. package/dist/react-native-core/index.js +5 -1
  75. package/dist/react-native-core/index.js.map +1 -1
  76. package/dist/react-native-core/platform.d.ts +2 -1
  77. package/dist/react-native-core/platform.d.ts.map +1 -1
  78. package/dist/testing.js +1 -1
  79. package/dist/testing.js.map +1 -1
  80. package/dist/tools/coValues/account.d.ts +7 -1
  81. package/dist/tools/coValues/account.d.ts.map +1 -1
  82. package/dist/tools/coValues/interfaces.d.ts +1 -1
  83. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  84. package/dist/tools/implementation/ContextManager.d.ts +3 -0
  85. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  86. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +8 -1
  87. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  88. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  89. package/dist/tools/subscribe/CoValueCoreSubscription.d.ts +8 -22
  90. package/dist/tools/subscribe/CoValueCoreSubscription.d.ts.map +1 -1
  91. package/dist/tools/subscribe/SubscriptionCache.d.ts +51 -0
  92. package/dist/tools/subscribe/SubscriptionCache.d.ts.map +1 -0
  93. package/dist/tools/subscribe/SubscriptionScope.d.ts +17 -1
  94. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  95. package/dist/tools/subscribe/utils.d.ts +9 -1
  96. package/dist/tools/subscribe/utils.d.ts.map +1 -1
  97. package/dist/tools/testing.d.ts +2 -2
  98. package/dist/tools/testing.d.ts.map +1 -1
  99. package/dist/tools/tests/SubscriptionCache.test.d.ts +2 -0
  100. package/dist/tools/tests/SubscriptionCache.test.d.ts.map +1 -0
  101. package/package.json +18 -6
  102. package/src/inspector/account-switcher.tsx +440 -0
  103. package/src/inspector/contexts/node.tsx +129 -0
  104. package/src/inspector/custom-element.tsx +2 -2
  105. package/src/inspector/in-app.tsx +61 -0
  106. package/src/inspector/index.tsx +2 -22
  107. package/src/inspector/pages/home.tsx +77 -0
  108. package/src/inspector/router/context.ts +21 -0
  109. package/src/inspector/router/hash-router.tsx +128 -0
  110. package/src/inspector/{viewer/use-page-path.ts → router/in-memory-router.tsx} +31 -29
  111. package/src/inspector/router/index.ts +4 -0
  112. package/src/inspector/standalone.tsx +60 -0
  113. package/src/inspector/tests/router/hash-router.test.tsx +847 -0
  114. package/src/inspector/tests/router/in-memory-router.test.tsx +724 -0
  115. package/src/inspector/ui/modal.tsx +5 -2
  116. package/src/inspector/viewer/breadcrumbs.tsx +5 -11
  117. package/src/inspector/viewer/header.tsx +67 -0
  118. package/src/inspector/viewer/page-stack.tsx +18 -26
  119. package/src/inspector/viewer/page.tsx +0 -1
  120. package/src/react/hooks.tsx +2 -0
  121. package/src/react/index.ts +1 -14
  122. package/src/react-core/hooks.ts +167 -18
  123. package/src/react-core/tests/createCoValueSubscriptionContext.test.tsx +18 -8
  124. package/src/react-core/tests/testUtils.tsx +67 -5
  125. package/src/react-core/tests/useCoState.test.ts +3 -7
  126. package/src/react-core/tests/useSubscriptionSelector.test.ts +3 -7
  127. package/src/react-core/tests/useSuspenseAccount.test.tsx +343 -0
  128. package/src/react-core/tests/useSuspenseCoState.test.tsx +1182 -0
  129. package/src/react-core/use.ts +46 -0
  130. package/src/react-native-core/crypto/RNCrypto.ts +1 -0
  131. package/src/react-native-core/hooks.tsx +2 -0
  132. package/src/react-native-core/platform.ts +2 -1
  133. package/src/tools/coValues/account.ts +13 -2
  134. package/src/tools/coValues/interfaces.ts +2 -3
  135. package/src/tools/implementation/ContextManager.ts +13 -0
  136. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +8 -1
  137. package/src/tools/subscribe/CoValueCoreSubscription.ts +71 -100
  138. package/src/tools/subscribe/SubscriptionCache.ts +272 -0
  139. package/src/tools/subscribe/SubscriptionScope.ts +113 -7
  140. package/src/tools/subscribe/utils.ts +77 -0
  141. package/src/tools/testing.ts +0 -3
  142. package/src/tools/tests/CoValueCoreSubscription.test.ts +46 -12
  143. package/src/tools/tests/ContextManager.test.ts +85 -0
  144. package/src/tools/tests/SubscriptionCache.test.ts +237 -0
  145. package/src/tools/tests/account.test.ts +11 -4
  146. package/src/tools/tests/coMap.test.ts +5 -7
  147. package/src/tools/tests/schema.resolved.test.ts +3 -3
  148. package/tsup.config.ts +2 -0
  149. package/dist/chunk-2S3Z2CN6.js.map +0 -1
  150. package/dist/inspector/custom-element-P76EIWEV.js.map +0 -1
  151. package/dist/inspector/viewer/new-app.d.ts.map +0 -1
  152. package/dist/inspector/viewer/use-page-path.d.ts +0 -10
  153. package/dist/inspector/viewer/use-page-path.d.ts.map +0 -1
  154. package/src/inspector/viewer/new-app.tsx +0 -156
@@ -0,0 +1,77 @@
1
+ import { styled } from "goober";
2
+ import { useNode } from "../contexts/node";
3
+ import { Heading } from "../ui/heading";
4
+ import { Button, Input } from "../ui";
5
+ import { useState } from "react";
6
+ import { CoID, RawCoValue } from "cojson";
7
+ import { useRouter } from "../router";
8
+
9
+ export function HomePage() {
10
+ const { localNode, accountID } = useNode();
11
+ const { path, setPage } = useRouter();
12
+ const [coValueId, setCoValueId] = useState<CoID<RawCoValue> | "">("");
13
+
14
+ if (!localNode || !accountID) {
15
+ return <div>Loading...</div>;
16
+ }
17
+
18
+ const handleCoValueIdSubmit = (e: React.FormEvent) => {
19
+ e.preventDefault();
20
+ if (coValueId) {
21
+ setPage(coValueId);
22
+ }
23
+ setCoValueId("");
24
+ };
25
+
26
+ return (
27
+ <>
28
+ <CenteredForm
29
+ onSubmit={handleCoValueIdSubmit}
30
+ aria-hidden={path.length !== 0}
31
+ >
32
+ <Heading>Jazz CoValue Inspector</Heading>
33
+
34
+ <Input
35
+ label="CoValue ID"
36
+ className="font-mono"
37
+ hideLabel
38
+ placeholder="co_z1234567890abcdef123456789"
39
+ value={coValueId}
40
+ onChange={(e) => setCoValueId(e.target.value as CoID<RawCoValue>)}
41
+ />
42
+
43
+ <Button type="submit" variant="primary">
44
+ Inspect CoValue
45
+ </Button>
46
+
47
+ <OrText>or</OrText>
48
+
49
+ <Button
50
+ variant="secondary"
51
+ onClick={() => {
52
+ setPage(accountID);
53
+ }}
54
+ >
55
+ Inspect my account
56
+ </Button>
57
+ </CenteredForm>
58
+ </>
59
+ );
60
+ }
61
+
62
+ const CenteredForm = styled("form")`
63
+ display: flex;
64
+ flex-direction: column;
65
+ position: relative;
66
+ top: -1.5rem;
67
+ justify-content: center;
68
+ gap: 0.5rem;
69
+ height: 100%;
70
+ width: 100%;
71
+ max-width: 24rem;
72
+ margin: 0 auto;
73
+ `;
74
+
75
+ const OrText = styled("p")`
76
+ text-align: center;
77
+ `;
@@ -0,0 +1,21 @@
1
+ import { CoID, RawCoValue } from "cojson";
2
+ import { PageInfo } from "../viewer/types.js";
3
+ import { createContext, useContext } from "react";
4
+
5
+ export interface Router {
6
+ path: PageInfo[];
7
+ setPage: (coId: CoID<RawCoValue>) => void;
8
+ addPages: (newPages: PageInfo[]) => void;
9
+ goToIndex: (index: number) => void;
10
+ goBack: () => void;
11
+ }
12
+
13
+ export const RouterContext = createContext<Router | null>(null);
14
+
15
+ export function useRouter(): Router {
16
+ const context = useContext(RouterContext);
17
+ if (!context) {
18
+ throw new Error("useRouter must be used within a RouterProvider");
19
+ }
20
+ return context;
21
+ }
@@ -0,0 +1,128 @@
1
+ import React, {
2
+ ReactNode,
3
+ useState,
4
+ useCallback,
5
+ useEffect,
6
+ useMemo,
7
+ } from "react";
8
+ import { Router, RouterContext } from "./context.js";
9
+ import { PageInfo } from "../viewer/types.js";
10
+ import { CoID, RawCoValue } from "cojson";
11
+
12
+ export function HashRouterProvider({
13
+ children,
14
+ defaultPath,
15
+ }: {
16
+ children: ReactNode;
17
+ defaultPath?: PageInfo[];
18
+ }) {
19
+ const [path, setPath] = useState<PageInfo[]>(() => {
20
+ if (typeof window === "undefined") return defaultPath || [];
21
+ const hash = window.location.hash.slice(2); // Remove '#/'
22
+
23
+ const defaultEncoded = encodePathToHash(defaultPath || []);
24
+
25
+ if (defaultPath) {
26
+ window.history.pushState({}, "", `#/${defaultEncoded}`);
27
+ return defaultPath;
28
+ }
29
+
30
+ if (hash) {
31
+ const path = decodePathFromHash(hash);
32
+ return path;
33
+ }
34
+
35
+ window.history.pushState({}, "", `#/${encodePathToHash([])}`);
36
+ return [];
37
+ });
38
+
39
+ const updatePath = useCallback((newPath: PageInfo[]) => {
40
+ setPath(newPath);
41
+ if (typeof window !== "undefined") {
42
+ const hash = encodePathToHash(newPath);
43
+ window.history.pushState({}, "", `#/${hash}`);
44
+ }
45
+ }, []);
46
+
47
+ useEffect(() => {
48
+ if (typeof window === "undefined") return;
49
+
50
+ const handleHashChange = () => {
51
+ const hash = window.location.hash.slice(2);
52
+ const currentPath = encodePathToHash(path);
53
+
54
+ if (hash === currentPath) return;
55
+
56
+ if (hash) {
57
+ try {
58
+ const newPath = decodePathFromHash(hash);
59
+ setPath(newPath);
60
+ } catch (e) {
61
+ console.error("Failed to parse hash:", e);
62
+ }
63
+ } else if (defaultPath) {
64
+ setPath(defaultPath);
65
+ }
66
+ };
67
+
68
+ window.addEventListener("hashchange", handleHashChange);
69
+ return () => window.removeEventListener("hashchange", handleHashChange);
70
+ }, [path, defaultPath]);
71
+
72
+ useEffect(() => {
73
+ if (defaultPath) {
74
+ updatePath(defaultPath);
75
+ }
76
+ }, [defaultPath]);
77
+
78
+ const router: Router = useMemo(() => {
79
+ const addPages = (newPages: PageInfo[]) => {
80
+ updatePath([...path, ...newPages]);
81
+ };
82
+
83
+ const goToIndex = (index: number) => {
84
+ updatePath(path.slice(0, index + 1));
85
+ };
86
+
87
+ const setPage = (coId: CoID<RawCoValue>) => {
88
+ updatePath([{ coId, name: "Root" }]);
89
+ };
90
+
91
+ const goBack = () => {
92
+ updatePath(path.slice(0, path.length - 1));
93
+ };
94
+
95
+ return {
96
+ path,
97
+ addPages,
98
+ goToIndex,
99
+ setPage,
100
+ goBack,
101
+ };
102
+ }, [path, updatePath]);
103
+
104
+ return (
105
+ <RouterContext.Provider value={router}>{children}</RouterContext.Provider>
106
+ );
107
+ }
108
+
109
+ function encodePathToHash(path: PageInfo[]): string {
110
+ return path
111
+ .map((page) => {
112
+ if (page.name && page.name !== "Root") {
113
+ return `${page.coId}:${encodeURIComponent(page.name)}`;
114
+ }
115
+ return page.coId;
116
+ })
117
+ .join("/");
118
+ }
119
+
120
+ function decodePathFromHash(hash: string): PageInfo[] {
121
+ return hash.split("/").map((segment) => {
122
+ const [coId, encodedName] = segment.split(":");
123
+ return {
124
+ coId,
125
+ name: encodedName ? decodeURIComponent(encodedName) : undefined,
126
+ } as PageInfo;
127
+ });
128
+ }
@@ -1,10 +1,17 @@
1
- import { CoID, RawCoValue } from "cojson";
2
- import { useCallback, useEffect, useState } from "react";
3
- import { PageInfo } from "./types.js";
1
+ import { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
2
+ import type { CoID, RawCoValue } from "cojson";
3
+ import { Router, RouterContext } from "./context.js";
4
+ import { PageInfo } from "../viewer/types.js";
4
5
 
5
6
  const STORAGE_KEY = "jazz-inspector-paths";
6
7
 
7
- export function usePagePath(defaultPath?: PageInfo[]) {
8
+ export function InMemoryRouterProvider({
9
+ children,
10
+ defaultPath,
11
+ }: {
12
+ children: ReactNode;
13
+ defaultPath?: PageInfo[];
14
+ }) {
8
15
  const [path, setPath] = useState<PageInfo[]>(() => {
9
16
  if (typeof window === "undefined") return [];
10
17
  const stored = localStorage.getItem(STORAGE_KEY);
@@ -29,38 +36,33 @@ export function usePagePath(defaultPath?: PageInfo[]) {
29
36
  }
30
37
  }, [defaultPath, path, updatePath]);
31
38
 
32
- const addPages = useCallback(
33
- (newPages: PageInfo[]) => {
39
+ const router: Router = useMemo(() => {
40
+ const addPages = (newPages: PageInfo[]) => {
34
41
  updatePath([...path, ...newPages]);
35
- },
36
- [path, updatePath],
37
- );
42
+ };
38
43
 
39
- const goToIndex = useCallback(
40
- (index: number) => {
44
+ const goToIndex = (index: number) => {
41
45
  updatePath(path.slice(0, index + 1));
42
- },
43
- [path, updatePath],
44
- );
46
+ };
45
47
 
46
- const setPage = useCallback(
47
- (coId: CoID<RawCoValue>) => {
48
+ const setPage = (coId: CoID<RawCoValue>) => {
48
49
  updatePath([{ coId, name: "Root" }]);
49
- },
50
- [updatePath],
51
- );
50
+ };
52
51
 
53
- const goBack = useCallback(() => {
54
- if (path.length > 1) {
52
+ const goBack = () => {
55
53
  updatePath(path.slice(0, path.length - 1));
56
- }
54
+ };
55
+
56
+ return {
57
+ path,
58
+ addPages,
59
+ goToIndex,
60
+ setPage,
61
+ goBack,
62
+ };
57
63
  }, [path, updatePath]);
58
64
 
59
- return {
60
- path,
61
- setPage,
62
- addPages,
63
- goToIndex,
64
- goBack,
65
- };
65
+ return (
66
+ <RouterContext.Provider value={router}>{children}</RouterContext.Provider>
67
+ );
66
68
  }
@@ -0,0 +1,4 @@
1
+ export type { Router } from "./context.js";
2
+ export { useRouter } from "./context.js";
3
+ export { InMemoryRouterProvider } from "./in-memory-router.js";
4
+ export { HashRouterProvider } from "./hash-router.js";
@@ -0,0 +1,60 @@
1
+ import React from "react";
2
+ import { HashRouterProvider } from "./router";
3
+ import { setup, styled } from "goober";
4
+ import { NodeContext, NodeProvider } from "./contexts/node";
5
+ import { Header } from "./viewer/header";
6
+ import { GlobalStyles } from "./ui/global-styles";
7
+ import { PageStack } from "./viewer/page-stack";
8
+ import { AccountSwitcher } from "./account-switcher";
9
+
10
+ type InspectorAppProps = {
11
+ defaultSyncServer?: string;
12
+ };
13
+
14
+ setup(React.createElement);
15
+
16
+ export default function InspectorStandalone(props: InspectorAppProps) {
17
+ return (
18
+ <HashRouterProvider>
19
+ <NodeProvider>
20
+ <InspectorContainer as={GlobalStyles}>
21
+ <Header>
22
+ <AccountSwitcher defaultSyncServer={props.defaultSyncServer} />
23
+ </Header>
24
+ <NodeContext.Consumer>
25
+ {({ accountID }) =>
26
+ accountID ? (
27
+ <PageStack />
28
+ ) : (
29
+ <CenteredMessage>
30
+ Select an account to connect to the inspector.
31
+ </CenteredMessage>
32
+ )
33
+ }
34
+ </NodeContext.Consumer>
35
+ </InspectorContainer>
36
+ </NodeProvider>
37
+ </HashRouterProvider>
38
+ );
39
+ }
40
+
41
+ const InspectorContainer = styled("div")`
42
+ height: 100vh;
43
+ overflow: hidden;
44
+ display: flex;
45
+ flex-direction: column;
46
+ color: #44403c; /* text-stone-700 */
47
+ background-color: #fff; /* bg-white */
48
+
49
+ @media (prefers-color-scheme: dark) {
50
+ color: #d6d3d1; /* text-stone-300 */
51
+ background-color: #0c0a09; /* bg-stone-950 */
52
+ }
53
+ `;
54
+
55
+ const CenteredMessage = styled("p")`
56
+ text-align: center;
57
+ margin: 0;
58
+ padding: 1rem;
59
+ color: var(--j-text-color);
60
+ `;