Compare commits
79 Commits
sync-msg-d
...
jazz-react
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ff381b8d5 | ||
|
|
ef7931761a | ||
|
|
da30641856 | ||
|
|
01435dc20b | ||
|
|
506256e291 | ||
|
|
6bb0d38b26 | ||
|
|
397ff9ce09 | ||
|
|
df42b2b295 | ||
|
|
aae280b7da | ||
|
|
d1e4ee0fe4 | ||
|
|
7cfd47b7f3 | ||
|
|
c34ce695ea | ||
|
|
7666dc6da2 | ||
|
|
be3ac8aa63 | ||
|
|
b759668022 | ||
|
|
1ada04f6f4 | ||
|
|
f3455bc691 | ||
|
|
044f61e3d7 | ||
|
|
6d63f4cf2e | ||
|
|
b828f41cf0 | ||
|
|
14d24888e1 | ||
|
|
29bdb0a120 | ||
|
|
c7ec6baba8 | ||
|
|
f8cf198a27 | ||
|
|
720435e2f2 | ||
|
|
2dcf6925b4 | ||
|
|
55d49a3435 | ||
|
|
33d1c11909 | ||
|
|
02ee69672d | ||
|
|
743f7d068b | ||
|
|
c0a1bb272e | ||
|
|
a9f08ebbbe | ||
|
|
0d86b132ea | ||
|
|
5114bbec88 | ||
|
|
29deedb163 | ||
|
|
a322a0e3b5 | ||
|
|
4fea86141f | ||
|
|
d923d45a82 | ||
|
|
ff52fb3275 | ||
|
|
c65a8806f6 | ||
|
|
8c8a5b242a | ||
|
|
d020ee2825 | ||
|
|
2e2a13f22d | ||
|
|
b1056c2ed3 | ||
|
|
e00489d8ee | ||
|
|
1e08581049 | ||
|
|
5a5f886bdf | ||
|
|
e5c575ec10 | ||
|
|
68c2b2598e | ||
|
|
c0ba15cca8 | ||
|
|
3e0493f88f | ||
|
|
e511d6d56a | ||
|
|
53f4b23c0a | ||
|
|
749a424cf1 | ||
|
|
33c4ef902d | ||
|
|
e2e3751172 | ||
|
|
6c62f4be5d | ||
|
|
0a2fae3830 | ||
|
|
4ab533af6b | ||
|
|
0fa017d148 | ||
|
|
99cda2f33d | ||
|
|
7c4f519ca1 | ||
|
|
e4fcafd576 | ||
|
|
a9cff03bcb | ||
|
|
26324d4b1e | ||
|
|
bd022ffd5e | ||
|
|
94e3922efc | ||
|
|
dcc9c2e376 | ||
|
|
48edcaff37 | ||
|
|
a18ed077ca | ||
|
|
7780346208 | ||
|
|
699553fe9f | ||
|
|
bdd5ad7eb1 | ||
|
|
28fea37446 | ||
|
|
61915fe3ed | ||
|
|
a6942030d4 | ||
|
|
905c6b312b | ||
|
|
1a4bda09ca | ||
|
|
815f54fafb |
@@ -1,5 +1,44 @@
|
|||||||
# @jazz-e2e/binarycostream
|
# @jazz-e2e/binarycostream
|
||||||
|
|
||||||
|
## 0.0.109
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.107
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.106
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.105
|
## 0.0.105
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@jazz-e2e/filestream",
|
"name": "@jazz-e2e/filestream",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.105",
|
"version": "0.0.109",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -13,11 +13,11 @@
|
|||||||
"test:ui": "playwright test --ui"
|
"test:ui": "playwright test --ui"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"hash-slash": "workspace:0.2.1",
|
"hash-slash": "workspace:0.2.1",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,44 @@
|
|||||||
# @jazz-e2e/covalues
|
# @jazz-e2e/covalues
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.107
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.106
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.105
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.104
|
## 0.0.104
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@jazz-e2e/covalues",
|
"name": "@jazz-e2e/covalues",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.104",
|
"version": "0.0.108",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
# jazz-example-book-shelf
|
# jazz-example-book-shelf
|
||||||
|
|
||||||
|
## 0.1.24
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
- jazz-browser-media-images@0.8.32
|
||||||
|
|
||||||
|
## 0.1.23
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
- jazz-browser-media-images@0.8.31
|
||||||
|
|
||||||
|
## 0.1.22
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
- jazz-browser-media-images@0.8.30
|
||||||
|
|
||||||
|
## 0.1.21
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
- jazz-browser-media-images@0.8.29
|
||||||
|
|
||||||
## 0.1.20
|
## 0.1.20
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-book-shelf",
|
"name": "jazz-example-book-shelf",
|
||||||
"version": "0.1.20",
|
"version": "0.1.24",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"jazz-browser-media-images": "workspace:0.8.28",
|
"jazz-browser-media-images": "workspace:0.8.32",
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
|
|||||||
@@ -1,5 +1,49 @@
|
|||||||
# jazz-example-chat
|
# jazz-example-chat
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- Updated dependencies [1a4bda0]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
- jazz-react-auth-clerk@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.107
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-react-auth-clerk@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.106
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-react-auth-clerk@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.105
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-react-auth-clerk@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.104
|
## 0.0.104
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-chat-clerk",
|
"name": "jazz-example-chat-clerk",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.104",
|
"version": "0.0.108",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -17,11 +17,11 @@
|
|||||||
"@radix-ui/react-toast": "^1.1.4",
|
"@radix-ui/react-toast": "^1.1.4",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"hash-slash": "workspace:0.2.1",
|
"hash-slash": "workspace:0.2.1",
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-react-auth-clerk": "workspace:0.8.28",
|
"jazz-react-auth-clerk": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
@@ -1,5 +1,43 @@
|
|||||||
# chat-rn-clerk
|
# chat-rn-clerk
|
||||||
|
|
||||||
|
## 1.0.24
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [1a4bda0]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-react-auth-clerk@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react-native@0.8.32
|
||||||
|
- jazz-react-native-media-images@0.8.24
|
||||||
|
|
||||||
|
## 1.0.23
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-auth-clerk@0.8.31
|
||||||
|
- jazz-react-native@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
- jazz-react-native-media-images@0.8.23
|
||||||
|
|
||||||
|
## 1.0.22
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-auth-clerk@0.8.30
|
||||||
|
- jazz-react-native@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
- jazz-react-native-media-images@0.8.22
|
||||||
|
|
||||||
|
## 1.0.21
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-native@0.8.29
|
||||||
|
- jazz-react-auth-clerk@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
- jazz-react-native-media-images@0.8.21
|
||||||
|
|
||||||
## 1.0.20
|
## 1.0.20
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-rn-clerk",
|
"name": "chat-rn-clerk",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"version": "1.0.20",
|
"version": "1.0.24",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "expo export -p ios",
|
"build": "expo export -p ios",
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
|
|||||||
@@ -1,5 +1,34 @@
|
|||||||
# chat-rn
|
# chat-rn
|
||||||
|
|
||||||
|
## 1.0.23
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react-native@0.8.32
|
||||||
|
|
||||||
|
## 1.0.22
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-native@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 1.0.21
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-native@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 1.0.20
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react-native@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 1.0.19
|
## 1.0.19
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-rn",
|
"name": "chat-rn",
|
||||||
"version": "1.0.19",
|
"version": "1.0.23",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "expo export -p ios",
|
"build": "expo export -p ios",
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
# chat-vue
|
# chat-vue
|
||||||
|
|
||||||
|
## 0.0.15
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-browser@0.8.32
|
||||||
|
- jazz-vue@0.8.20
|
||||||
|
|
||||||
|
## 0.0.14
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
- jazz-vue@0.8.19
|
||||||
|
|
||||||
|
## 0.0.13
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
- jazz-vue@0.8.18
|
||||||
|
|
||||||
|
## 0.0.12
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
- jazz-vue@0.8.17
|
||||||
|
|
||||||
## 0.0.11
|
## 0.0.11
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "chat-vue",
|
"name": "chat-vue",
|
||||||
"version": "0.0.11",
|
"version": "0.0.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,44 @@
|
|||||||
# jazz-example-chat
|
# jazz-example-chat
|
||||||
|
|
||||||
|
## 0.0.110
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.109
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.108
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.107
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.106
|
## 0.0.106
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-chat",
|
"name": "jazz-example-chat",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.106",
|
"version": "0.0.110",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
"@radix-ui/react-toast": "^1.1.4",
|
"@radix-ui/react-toast": "^1.1.4",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"hash-slash": "workspace:0.2.1",
|
"hash-slash": "workspace:0.2.1",
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
@@ -1,5 +1,39 @@
|
|||||||
# jazz-example-inspector
|
# jazz-example-inspector
|
||||||
|
|
||||||
|
## 0.0.80
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
- cojson-transport-ws@0.8.32
|
||||||
|
|
||||||
|
## 0.0.79
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
- cojson-transport-ws@0.8.31
|
||||||
|
|
||||||
|
## 0.0.78
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
- cojson-transport-ws@0.8.30
|
||||||
|
|
||||||
|
## 0.0.77
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson-transport-ws@0.8.29
|
||||||
|
- cojson@0.8.29
|
||||||
|
|
||||||
## 0.0.76
|
## 0.0.76
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-inspector",
|
"name": "jazz-inspector",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.76",
|
"version": "0.0.80",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
"@radix-ui/react-toast": "^1.1.4",
|
"@radix-ui/react-toast": "^1.1.4",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"cojson-transport-ws": "workspace:0.8.28",
|
"cojson-transport-ws": "workspace:0.8.32",
|
||||||
"hash-slash": "workspace:0.2.1",
|
"hash-slash": "workspace:0.2.1",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
|
|||||||
@@ -1,5 +1,39 @@
|
|||||||
# minimal-auth-clerk
|
# minimal-auth-clerk
|
||||||
|
|
||||||
|
## 0.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [1a4bda0]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-react-auth-clerk@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-react-auth-clerk@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-react-auth-clerk@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-react-auth-clerk@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.5
|
## 0.0.5
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "minimal-auth-clerk",
|
"name": "minimal-auth-clerk",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.5",
|
"version": "0.0.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"@clerk/clerk-react": "^5.4.1",
|
"@clerk/clerk-react": "^5.4.1",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
"jazz-react": "workspace:*",
|
"jazz-react": "workspace:*",
|
||||||
"jazz-react-auth-clerk": "workspace:0.8.28",
|
"jazz-react-auth-clerk": "workspace:0.8.32",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,34 @@
|
|||||||
# minimal-auth-passkey
|
# minimal-auth-passkey
|
||||||
|
|
||||||
|
## 0.0.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.6
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.5
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.4
|
## 0.0.4
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "minimal-auth-passkey",
|
"name": "minimal-auth-passkey",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.4",
|
"version": "0.0.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,5 +1,34 @@
|
|||||||
# jazz-example-musicplayer
|
# jazz-example-musicplayer
|
||||||
|
|
||||||
|
## 0.0.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.28
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.27
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.26
|
## 0.0.26
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-music-player",
|
"name": "jazz-example-music-player",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.26",
|
"version": "0.0.30",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
"@radix-ui/react-toast": "^1.1.4",
|
"@radix-ui/react-toast": "^1.1.4",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
# jazz-example-onboarding
|
# jazz-example-onboarding
|
||||||
|
|
||||||
|
## 0.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
- jazz-browser-media-images@0.8.32
|
||||||
|
|
||||||
|
## 0.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
- jazz-browser-media-images@0.8.31
|
||||||
|
|
||||||
|
## 0.0.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
- jazz-browser-media-images@0.8.30
|
||||||
|
|
||||||
|
## 0.0.8
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
- jazz-browser-media-images@0.8.29
|
||||||
|
|
||||||
## 0.0.7
|
## 0.0.7
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-onboarding",
|
"name": "jazz-example-onboarding",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.7",
|
"version": "0.0.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,5 +1,34 @@
|
|||||||
# jazz-password-manager
|
# jazz-password-manager
|
||||||
|
|
||||||
|
## 0.0.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.28
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.27
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.26
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.25
|
## 0.0.25
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-password-manager",
|
"name": "jazz-password-manager",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.25",
|
"version": "0.0.29",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
|
"clean-install": "rm -rf node_modules pnpm-lock.yaml && pnpm install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hook-form": "^7.41.5",
|
"react-hook-form": "^7.41.5",
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
# jazz-example-pets
|
# jazz-example-pets
|
||||||
|
|
||||||
|
## 0.0.127
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
- jazz-browser-media-images@0.8.32
|
||||||
|
|
||||||
|
## 0.0.126
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
- jazz-browser-media-images@0.8.31
|
||||||
|
|
||||||
|
## 0.0.125
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
- jazz-browser-media-images@0.8.30
|
||||||
|
|
||||||
|
## 0.0.124
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
- jazz-browser-media-images@0.8.29
|
||||||
|
|
||||||
## 0.0.123
|
## 0.0.123
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-pets",
|
"name": "jazz-example-pets",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.123",
|
"version": "0.0.127",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
"@radix-ui/react-toast": "^1.1.4",
|
"@radix-ui/react-toast": "^1.1.4",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"jazz-browser-media-images": "workspace:0.8.28",
|
"jazz-browser-media-images": "workspace:0.8.32",
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"is-ci": "^3.0.1",
|
"is-ci": "^3.0.1",
|
||||||
"jazz-run": "workspace:0.8.28",
|
"jazz-run": "workspace:0.8.32",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
"tailwindcss": "3.3.2",
|
"tailwindcss": "3.3.2",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
|
|||||||
@@ -1,5 +1,38 @@
|
|||||||
# todo-vue
|
# todo-vue
|
||||||
|
|
||||||
|
## 0.0.13
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-browser@0.8.32
|
||||||
|
- jazz-vue@0.8.20
|
||||||
|
|
||||||
|
## 0.0.12
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
- jazz-vue@0.8.19
|
||||||
|
|
||||||
|
## 0.0.11
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
- jazz-vue@0.8.18
|
||||||
|
|
||||||
|
## 0.0.10
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
- jazz-vue@0.8.17
|
||||||
|
|
||||||
## 0.0.9
|
## 0.0.9
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "todo-vue",
|
"name": "todo-vue",
|
||||||
"version": "0.0.9",
|
"version": "0.0.13",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,34 @@
|
|||||||
# jazz-example-todo
|
# jazz-example-todo
|
||||||
|
|
||||||
|
## 0.0.126
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-react@0.8.32
|
||||||
|
|
||||||
|
## 0.0.125
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.0.124
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.0.123
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-react@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.0.122
|
## 0.0.122
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-example-todo",
|
"name": "jazz-example-todo",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.122",
|
"version": "0.0.126",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
"@radix-ui/react-toast": "^1.1.4",
|
"@radix-ui/react-toast": "^1.1.4",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"jazz-react": "workspace:0.8.28",
|
"jazz-react": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"lucide-react": "^0.274.0",
|
"lucide-react": "^0.274.0",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@evilmartians/harmony": "^1.0.0",
|
"@evilmartians/harmony": "^1.0.0",
|
||||||
"@headlessui/react": "^2.2.0",
|
"@headlessui/react": "^2.2.0",
|
||||||
|
"@icons-pack/react-simple-icons": "^9.1.0",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"lucide-react": "^0.436.0",
|
"lucide-react": "^0.436.0",
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
"resend": "^4.0.0",
|
||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss-animate": "^1.0.7"
|
"tailwindcss-animate": "^1.0.7"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { clsx } from "clsx";
|
import { clsx } from "clsx";
|
||||||
|
import { LucideIcon } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { Spinner } from "./Spinner";
|
||||||
|
|
||||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@@ -7,6 +9,19 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|||||||
size?: "sm" | "md" | "lg";
|
size?: "sm" | "md" | "lg";
|
||||||
href?: string;
|
href?: string;
|
||||||
newTab?: boolean;
|
newTab?: boolean;
|
||||||
|
icon?: LucideIcon;
|
||||||
|
loading?: boolean;
|
||||||
|
loadingText?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ButtonIcon({ icon: Icon, loading }: ButtonProps) {
|
||||||
|
if (!Icon) return null;
|
||||||
|
|
||||||
|
const className = "size-5";
|
||||||
|
|
||||||
|
if (loading) return <Spinner className={className} />;
|
||||||
|
|
||||||
|
return <Icon strokeWidth={1.5} className={className} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Button(props: ButtonProps) {
|
export function Button(props: ButtonProps) {
|
||||||
@@ -18,6 +33,7 @@ export function Button(props: ButtonProps) {
|
|||||||
href,
|
href,
|
||||||
disabled,
|
disabled,
|
||||||
newTab,
|
newTab,
|
||||||
|
loadingText,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const sizeClasses = {
|
const sizeClasses = {
|
||||||
@@ -37,6 +53,7 @@ export function Button(props: ButtonProps) {
|
|||||||
const classNames = clsx(
|
const classNames = clsx(
|
||||||
className,
|
className,
|
||||||
"inline-flex items-center justify-center gap-2 rounded-lg text-center transition-colors",
|
"inline-flex items-center justify-center gap-2 rounded-lg text-center transition-colors",
|
||||||
|
"disabled:pointer-events-none disabled:opacity-70",
|
||||||
sizeClasses[size],
|
sizeClasses[size],
|
||||||
variantClasses[variant],
|
variantClasses[variant],
|
||||||
disabled && "opacity-50 cursor-not-allowed pointer-events-none",
|
disabled && "opacity-50 cursor-not-allowed pointer-events-none",
|
||||||
@@ -49,14 +66,21 @@ export function Button(props: ButtonProps) {
|
|||||||
target={newTab ? "_blank" : undefined}
|
target={newTab ? "_blank" : undefined}
|
||||||
className={classNames}
|
className={classNames}
|
||||||
>
|
>
|
||||||
|
<ButtonIcon {...props} />
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button {...props} className={classNames}>
|
<button
|
||||||
{children}
|
{...props}
|
||||||
|
disabled={props.disabled || props.loading}
|
||||||
|
className={classNames}
|
||||||
|
>
|
||||||
|
<ButtonIcon {...props} />
|
||||||
|
|
||||||
|
{props.loading && props.loadingText ? props.loadingText : children}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
12
homepage/design-system/src/app/components/atoms/Card.tsx
Normal file
12
homepage/design-system/src/app/components/atoms/Card.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { clsx } from "clsx";
|
||||||
|
|
||||||
|
export function Card({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
}: { children: React.ReactNode; className?: string }) {
|
||||||
|
return (
|
||||||
|
<div className={clsx(className, "border rounded-xl shadow-sm")}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
import { Card } from "../atoms/Card";
|
||||||
|
|
||||||
export function GridCard(props: { children: ReactNode; className?: string }) {
|
export function GridCard(props: { children: ReactNode; className?: string }) {
|
||||||
return (
|
return (
|
||||||
<div
|
<Card
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"col-span-2 p-4 [&>h4]:mt-0 [&>h3]:mt-0 [&>:last-child]:mb-0",
|
"col-span-2 p-4 [&>h4]:mt-0 [&>h3]:mt-0 [&>:last-child]:mb-0",
|
||||||
"border rounded-xl shadow-sm",
|
|
||||||
props.className,
|
props.className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
26
homepage/design-system/src/app/components/atoms/Spinner.tsx
Normal file
26
homepage/design-system/src/app/components/atoms/Spinner.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
export function Spinner({ className }: { className?: string }) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className={clsx(className, "animate-spin")}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
className="opacity-25"
|
||||||
|
cx="12"
|
||||||
|
cy="12"
|
||||||
|
r="10"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="4"
|
||||||
|
></circle>
|
||||||
|
<path
|
||||||
|
className="opacity-75"
|
||||||
|
fill="currentColor"
|
||||||
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import clsx from "clsx";
|
||||||
|
import { LucideIcon } from "lucide-react";
|
||||||
|
import { Card } from "../atoms/Card";
|
||||||
|
import { Prose } from "./Prose";
|
||||||
|
|
||||||
|
export function FeatureCard({
|
||||||
|
label,
|
||||||
|
icon: Icon,
|
||||||
|
explanation,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
label: React.ReactNode;
|
||||||
|
icon?: LucideIcon;
|
||||||
|
explanation?: React.ReactNode;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Card className={clsx(className, "p-4")}>
|
||||||
|
{Icon && (
|
||||||
|
<Icon
|
||||||
|
className="size-8 text-blue p-1.5 rounded-lg bg-blue-50 dark:text-blue-500 dark:bg-stone-900 mb-2.5 md:size-10"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
strokeLinecap="butt"
|
||||||
|
size={80}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<div className="text-stone-900 font-medium md:text-base dark:text-stone-100 mb-2">
|
||||||
|
{label}
|
||||||
|
</div>
|
||||||
|
{explanation && <Prose>{explanation}</Prose>}
|
||||||
|
{children}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,15 +6,23 @@ export function GappedGrid({
|
|||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
title,
|
title,
|
||||||
|
cols = 3,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
cols?: 3 | 4;
|
||||||
}) {
|
}) {
|
||||||
|
const colsClassName =
|
||||||
|
cols === 3
|
||||||
|
? "md:grid-cols-4 lg:grid-cols-6"
|
||||||
|
: "sm:grid-cols-2 lg:grid-cols-4";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4 lg:gap-8",
|
"grid grid-cols-2 gap-4 lg:gap-8",
|
||||||
|
colsClassName,
|
||||||
"items-stretch",
|
"items-stretch",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import clsx from "clsx";
|
|
||||||
import { LucideIcon } from "lucide-react";
|
|
||||||
import { Prose } from "./Prose";
|
|
||||||
|
|
||||||
export function LabelledFeatureIcon({
|
|
||||||
label,
|
|
||||||
icon: Icon,
|
|
||||||
explanation,
|
|
||||||
className,
|
|
||||||
}: {
|
|
||||||
label: string;
|
|
||||||
icon: LucideIcon;
|
|
||||||
explanation: React.ReactNode;
|
|
||||||
className?: string;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={clsx(
|
|
||||||
className,
|
|
||||||
"text-base",
|
|
||||||
"rounded-xl",
|
|
||||||
"border p-4 shadow-sm",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className="size-8 text-blue p-1.5 rounded-lg bg-blue-50 dark:text-blue-500 dark:bg-stone-900 mb-2.5 md:size-10"
|
|
||||||
strokeWidth={1.5}
|
|
||||||
strokeLinecap="butt"
|
|
||||||
size={80}
|
|
||||||
/>
|
|
||||||
<div className="text-stone-900 font-medium md:text-base dark:text-stone-100 mb-2">
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
<Prose>{explanation}</Prose>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,8 @@ import Link from "next/link";
|
|||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
import { ThemeToggle } from "../molecules/ThemeToggle";
|
import { ThemeToggle } from "../molecules/ThemeToggle";
|
||||||
|
import { NewsletterForm } from "./NewsletterForm";
|
||||||
|
import { SocialLinks, SocialLinksProps } from "./SocialLinks";
|
||||||
|
|
||||||
type FooterSection = {
|
type FooterSection = {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -19,6 +21,7 @@ type FooterProps = {
|
|||||||
logo: ReactNode;
|
logo: ReactNode;
|
||||||
companyName: string;
|
companyName: string;
|
||||||
sections: FooterSection[];
|
sections: FooterSection[];
|
||||||
|
socials: SocialLinksProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Copyright({
|
function Copyright({
|
||||||
@@ -35,38 +38,47 @@ function Copyright({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Footer({ logo, companyName, sections }: FooterProps) {
|
export function Footer({ logo, companyName, sections, socials }: FooterProps) {
|
||||||
return (
|
return (
|
||||||
<footer className="w-full border-t bg-stone-100 mt-12 md:mt-20 dark:bg-stone-925">
|
<footer className="w-full border-t py-8 mt-12 md:mt-20">
|
||||||
<div className="container py-8 md:py-16 grid gap-y-8 grid-cols-12">
|
<div className="container grid gap-8 md:gap-12">
|
||||||
<div className="flex flex-col justify-between col-span-full md:col-span-4">
|
<div className=" grid gap-y-8 grid-cols-12">
|
||||||
{logo}
|
<div className="flex flex-col gap-6 justify-between col-span-full md:col-span-7">
|
||||||
|
{logo}
|
||||||
<Copyright className="hidden md:block" companyName={companyName} />
|
<NewsletterForm />
|
||||||
</div>
|
|
||||||
|
|
||||||
{sections.map((section, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="flex flex-col gap-2 text-sm col-span-4 sm:col-span-4 md:col-span-2"
|
|
||||||
>
|
|
||||||
<h2 className="font-medium">{section.title}</h2>
|
|
||||||
{section.links.map((link, linkIndex) => (
|
|
||||||
<FooterLink key={linkIndex} href={link.href} newTab={link.newTab}>
|
|
||||||
{link.label}
|
|
||||||
</FooterLink>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
|
|
||||||
<div className="hidden md:flex justify-end items-end md:col-span-2">
|
{sections.map((section, index) => (
|
||||||
<ThemeToggle />
|
<div
|
||||||
|
key={index}
|
||||||
|
className="flex flex-col gap-2 text-sm col-span-6 md:col-span-2"
|
||||||
|
>
|
||||||
|
<h2 className="font-medium">{section.title}</h2>
|
||||||
|
{section.links.map((link, linkIndex) => (
|
||||||
|
<FooterLink
|
||||||
|
key={linkIndex}
|
||||||
|
href={link.href}
|
||||||
|
newTab={link.newTab}
|
||||||
|
>
|
||||||
|
{link.label}
|
||||||
|
</FooterLink>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<div className="hidden md:flex justify-end items-end md:col-span-1">
|
||||||
|
<ThemeToggle />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Copyright
|
<div className="flex flex-col justify-between gap-y-6 gap-3 md:flex-row">
|
||||||
className="col-span-full md:hidden"
|
<Copyright companyName={companyName} />
|
||||||
companyName={companyName}
|
|
||||||
/>
|
<SocialLinks
|
||||||
|
{...socials}
|
||||||
|
className="order-first md:order-last"
|
||||||
|
></SocialLinks>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { usePathname } from "next/navigation";
|
|||||||
import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from "react";
|
import { ReactNode, useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||||
import { BreadCrumb } from "../molecules/Breadcrumb";
|
import { BreadCrumb } from "../molecules/Breadcrumb";
|
||||||
import { ThemeToggle } from "../molecules/ThemeToggle";
|
import { ThemeToggle } from "../molecules/ThemeToggle";
|
||||||
|
import { SocialLinks, SocialLinksProps } from "./SocialLinks";
|
||||||
|
|
||||||
type NavItemProps = {
|
type NavItemProps = {
|
||||||
href: string;
|
href: string;
|
||||||
@@ -30,6 +31,7 @@ type NavProps = {
|
|||||||
items: NavItemProps[];
|
items: NavItemProps[];
|
||||||
docNav?: ReactNode;
|
docNav?: ReactNode;
|
||||||
cta?: ReactNode;
|
cta?: ReactNode;
|
||||||
|
socials?: SocialLinksProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
function NavItem({
|
function NavItem({
|
||||||
@@ -110,7 +112,7 @@ function NavItem({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MobileNav({ mainLogo, items, docNav, cta }: NavProps) {
|
export function MobileNav({ mainLogo, items, docNav, cta, socials }: NavProps) {
|
||||||
const [menuOpen, setMenuOpen] = useState(false);
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
const [searchOpen, setSearchOpen] = useState(false);
|
const [searchOpen, setSearchOpen] = useState(false);
|
||||||
const searchRef = useRef<HTMLInputElement>(null);
|
const searchRef = useRef<HTMLInputElement>(null);
|
||||||
@@ -170,13 +172,8 @@ export function MobileNav({ mainLogo, items, docNav, cta }: NavProps) {
|
|||||||
>
|
>
|
||||||
{mainLogo}
|
{mainLogo}
|
||||||
</NavLinkLogo>
|
</NavLinkLogo>
|
||||||
{items
|
|
||||||
.filter((item) => "icon" in item)
|
<SocialLinks className="px-2 gap-2" {...socials} />
|
||||||
.map((item, i) => (
|
|
||||||
<NavLinkLogo key={i} href={item.href} newTab={item.newTab}>
|
|
||||||
{item.icon}
|
|
||||||
</NavLinkLogo>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{pathname.startsWith("/docs") && docNav && (
|
{pathname.startsWith("/docs") && docNav && (
|
||||||
@@ -310,6 +307,8 @@ export function Nav(props: NavProps) {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
<SocialLinks {...props.socials} />
|
||||||
|
|
||||||
{cta}
|
{cta}
|
||||||
</PopoverGroup>
|
</PopoverGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,30 +1,37 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { subscribe } from "@/app/actions/resend";
|
import { CheckIcon, MailIcon } from "lucide-react";
|
||||||
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
|
|
||||||
import { Input } from "gcmp-design-system/src/app/components/molecules/Input";
|
|
||||||
import { CheckIcon } from "lucide-react";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { ErrorResponse } from "resend";
|
import { ErrorResponse } from "resend";
|
||||||
|
import { subscribe } from "../../../actions/resend";
|
||||||
|
import { Button } from "../atoms/Button";
|
||||||
|
import { Input } from "../molecules/Input";
|
||||||
|
|
||||||
export function NewsletterForm() {
|
export function NewsletterForm() {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [subscribed, setSubscribed] = useState(false);
|
// const [subscribed, setSubscribed] = useState(false);
|
||||||
const [error, setError] = useState<ErrorResponse | undefined>();
|
const [error, setError] = useState<ErrorResponse | undefined>();
|
||||||
|
|
||||||
|
const [state, setState] = useState<"ready" | "loading" | "success" | "error">(
|
||||||
|
"ready",
|
||||||
|
);
|
||||||
|
|
||||||
const submit = async (e: React.FormEvent) => {
|
const submit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
setState("loading");
|
||||||
|
|
||||||
const res = await subscribe(email);
|
const res = await subscribe(email);
|
||||||
|
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
setError(res.error);
|
setError(res.error);
|
||||||
|
setState("error");
|
||||||
} else {
|
} else {
|
||||||
setSubscribed(true);
|
setState("success");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (subscribed) {
|
if (state === "success") {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-3 items-center">
|
<div className="flex gap-3 items-center">
|
||||||
<CheckIcon className="text-green-500" size={16} />
|
<CheckIcon className="text-green-500" size={16} />
|
||||||
@@ -33,12 +40,12 @@ export function NewsletterForm() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (state === "error" && error?.message) {
|
||||||
return <p className="text-red-700">Error: {error.message}</p>;
|
return <p className="text-red-700">Error: {error.message}</p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form action="" onSubmit={submit} className="flex gap-x-4 w-120 max-w-xl">
|
<form action="" onSubmit={submit} className="flex gap-x-4 w-120 max-w-md">
|
||||||
<Input
|
<Input
|
||||||
id="email-address"
|
id="email-address"
|
||||||
name="email"
|
name="email"
|
||||||
@@ -51,7 +58,13 @@ export function NewsletterForm() {
|
|||||||
className="flex-1 label:sr-only"
|
className="flex-1 label:sr-only"
|
||||||
label="Email address"
|
label="Email address"
|
||||||
/>
|
/>
|
||||||
<Button type="submit" variant="secondary">
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="secondary"
|
||||||
|
loadingText="Subscribing..."
|
||||||
|
loading={state === "loading"}
|
||||||
|
icon={MailIcon}
|
||||||
|
>
|
||||||
Subscribe
|
Subscribe
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { SiDiscord, SiGithub, SiX } from "@icons-pack/react-simple-icons";
|
||||||
|
import { clsx } from "clsx";
|
||||||
|
|
||||||
|
export interface SocialLinksProps {
|
||||||
|
github?: string;
|
||||||
|
x?: string;
|
||||||
|
discord?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const socials = [
|
||||||
|
{
|
||||||
|
name: "Github",
|
||||||
|
icon: SiGithub,
|
||||||
|
key: "github",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Discord",
|
||||||
|
icon: SiDiscord,
|
||||||
|
key: "discord",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "X",
|
||||||
|
icon: SiX,
|
||||||
|
key: "x",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function SocialLinks(props: SocialLinksProps & { className?: string }) {
|
||||||
|
return (
|
||||||
|
<div className={clsx(props.className, "flex gap-6 ")}>
|
||||||
|
{socials.map(
|
||||||
|
(social) =>
|
||||||
|
props[social.key as keyof SocialLinksProps] && (
|
||||||
|
<a
|
||||||
|
key={social.key}
|
||||||
|
href={props[social.key as keyof SocialLinksProps]}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="flex items-center gap-2 hover:text-stone-900 hover:dark:text-white"
|
||||||
|
>
|
||||||
|
<social.icon className="w-5" />
|
||||||
|
<span className="sr-only">{social.name}</span>
|
||||||
|
</a>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Prose } from "@components/molecules/Prose";
|
import { Prose } from "@components/molecules/Prose";
|
||||||
|
import { NewsletterForm } from "@components/organisms/NewsletterForm";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
@@ -63,6 +64,12 @@ export default function Home() {
|
|||||||
</Prose>
|
</Prose>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2>Newsletter Subscription Form</h2>
|
||||||
|
|
||||||
|
<div className="p-3 border">
|
||||||
|
<NewsletterForm />
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { NewsletterForm } from "@/components/NewsletterForm";
|
|
||||||
import { Posts } from "@/components/blog/Posts";
|
import { Posts } from "@/components/blog/Posts";
|
||||||
import { HeroHeader } from "gcmp-design-system/src/app/components/molecules/HeroHeader";
|
import { HeroHeader } from "gcmp-design-system/src/app/components/molecules/HeroHeader";
|
||||||
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
||||||
|
import { NewsletterForm } from "gcmp-design-system/src/app/components/organisms/NewsletterForm";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
|
|||||||
@@ -69,6 +69,15 @@ const team: Array<TeamMember> = [
|
|||||||
github: "marinoska",
|
github: "marinoska",
|
||||||
image: "marina.jpeg",
|
image: "marina.jpeg",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Giordano Ricci",
|
||||||
|
titles: ["Full-Stack Dev", "DevOps"],
|
||||||
|
location: "Lisbon, Portugal ",
|
||||||
|
linkedin: "giordanoricci",
|
||||||
|
github: "Elfo404",
|
||||||
|
website: "https://giordanoricci.com",
|
||||||
|
image: "gio.jpg",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function SocialLink({
|
function SocialLink({
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
"next": "14.2.15",
|
"next": "14.2.15",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"resend": "^4.0.0",
|
|
||||||
"shiki": "^0.14.6",
|
"shiki": "^0.14.6",
|
||||||
"shiki-twoslash": "^3.1.2",
|
"shiki-twoslash": "^3.1.2",
|
||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
|
|||||||
BIN
homepage/gcmp/public/team/gio.jpg
Normal file
BIN
homepage/gcmp/public/team/gio.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
@@ -15,7 +15,7 @@ export default function Layout({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<DocsLayout nav={<ApiNav />}>
|
<DocsLayout nav={<ApiNav />}>
|
||||||
<Prose className="py-8">{children}</Prose>
|
<Prose className="py-8 [&_*]:scroll-mt-[8rem]">{children}</Prose>
|
||||||
</DocsLayout>
|
</DocsLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
import { CodeGroup } from "@/components/forMdx";
|
||||||
|
|
||||||
|
# Authentication methods
|
||||||
|
|
||||||
|
Jazz supports a variety of authentication methods, which you can use to authenticate users in your app.
|
||||||
|
|
||||||
|
- Passphrase (built-in)
|
||||||
|
- Passkey (built-in)
|
||||||
|
- Clerk ([React](https://www.npmjs.com/package/jazz-react-auth-clerk) and [vanilla](https://www.npmjs.com/package/jazz-browser-auth-clerk) packages)
|
||||||
|
|
||||||
|
## Passphrase
|
||||||
|
|
||||||
|
Passphrase authentication allows users to create a new account or log in with an existing one by providing a passphrase.
|
||||||
|
|
||||||
|
Passphrase authentication is supported out of the box and imported from `jazz-react`.
|
||||||
|
|
||||||
|
### How to use
|
||||||
|
|
||||||
|
1. Setup up Jazz as described in the [React setup guide](/docs/project-setup/react).
|
||||||
|
|
||||||
|
2. Use the `usePassphraseAuth` hook to authenticate.
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
```ts
|
||||||
|
import { usePassphraseAuth } from "jazz-react";
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const [passphraseAuth, passphraseState] = usePassphraseAuth({ appName });
|
||||||
|
```
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
|
## Passkey
|
||||||
|
|
||||||
|
Passkey authentication allows users to create a new account or log in with an existing one by providing a passkey.
|
||||||
|
|
||||||
|
Passkey authentication is supported out of the box.
|
||||||
|
|
||||||
|
We have a [minimal example of a passkey authentication setup](https://github.com/garden-co/jazz/tree/main/examples/minimal-auth-passkey).
|
||||||
|
|
||||||
|
### How to use
|
||||||
|
|
||||||
|
1. Setup up Jazz as described in the [React setup guide](/docs/project-setup/react).
|
||||||
|
|
||||||
|
2. Use the `usePasskeyAuth` hook to authenticate.
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
```ts
|
||||||
|
import { usePasskeyAuth } from "jazz-react";
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const [passkeyAuth, passkeyState] = usePasskeyAuth({ appName });
|
||||||
|
```
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
|
## Clerk
|
||||||
|
|
||||||
|
We have a React package `jazz-react-auth-clerk` to add Clerk authentication to your app.
|
||||||
|
|
||||||
|
We have a [minimal example of a Clerk authentication setup](https://github.com/garden-co/jazz/tree/main/examples/minimal-auth-clerk).
|
||||||
|
|
||||||
|
### How to use
|
||||||
|
|
||||||
|
1. Setup up Jazz as described in the [React setup guide](/docs/project-setup/react).
|
||||||
|
|
||||||
|
2. Install Clerk as described in the [Clerk docs](https://clerk.com/docs/components/overview).
|
||||||
|
|
||||||
|
3. Then add the appropriate package to your project (e.g. `jazz-react-auth-clerk`).
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
```bash
|
||||||
|
pnpm install jazz-react-auth-clerk
|
||||||
|
```
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
|
4. Provide a Clerk instance to the `useJazzClerkAuth` hook.
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
```tsx
|
||||||
|
import { useClerk, SignInButton } from "@clerk/clerk-react";
|
||||||
|
import { useJazzClerkAuth } from "jazz-react-auth-clerk";
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||||
|
const clerk = useClerk();
|
||||||
|
const [auth, state] = useJazzClerkAuth(clerk);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{clerk.user && auth ? (
|
||||||
|
<Jazz.Provider auth={auth}></Jazz.Provider>
|
||||||
|
) : (
|
||||||
|
<SignInButton />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
createRoot(document.getElementById("root")!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<ClerkProvider publishableKey={PUBLISHABLE_KEY} afterSignOutUrl="/">
|
||||||
|
<JazzAndAuth>
|
||||||
|
<App />
|
||||||
|
</JazzAndAuth>
|
||||||
|
</ClerkProvider>
|
||||||
|
</StrictMode>,
|
||||||
|
);
|
||||||
|
```
|
||||||
|
</CodeGroup>
|
||||||
@@ -70,7 +70,11 @@ function RenderPackageChild({
|
|||||||
return child.getAllSignatures().map((signature, i) => {
|
return child.getAllSignatures().map((signature, i) => {
|
||||||
const paramTypes = printParamsWithTypes(signature);
|
const paramTypes = printParamsWithTypes(signature);
|
||||||
return (
|
return (
|
||||||
<div key={i} id={child.name} className="not-prose mt-4">
|
<div
|
||||||
|
key={i}
|
||||||
|
id={child.name}
|
||||||
|
className="not-prose mt-4 p-3 rounded bg-stone-50 dark:bg-stone-925"
|
||||||
|
>
|
||||||
{
|
{
|
||||||
<Highlight hide={[0, 2]}>
|
<Highlight hide={[0, 2]}>
|
||||||
{`function \n${printSimpleSignature(child, signature) + ":"}\n {}`}
|
{`function \n${printSimpleSignature(child, signature) + ":"}\n {}`}
|
||||||
@@ -171,10 +175,7 @@ function RenderClassOrInterface({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{classOrInterface.categories?.map((category) => (
|
{classOrInterface.categories?.map((category) => (
|
||||||
<div
|
<div className="flex flex-col mt-6 first:mt-0" key={category.title}>
|
||||||
className="flex flex-col divide-y divide-stone-200 dark:divide-stone-900"
|
|
||||||
key={category.title}
|
|
||||||
>
|
|
||||||
<PropCategory
|
<PropCategory
|
||||||
name={category.title}
|
name={category.title}
|
||||||
description={renderSummary(
|
description={renderSummary(
|
||||||
|
|||||||
@@ -80,15 +80,15 @@ export function ClassOrInterface({
|
|||||||
className="inline-flex items-center gap-2 lg:-ml-[22px]"
|
className="inline-flex items-center gap-2 lg:-ml-[22px]"
|
||||||
>
|
>
|
||||||
<LinkIcon size={14} className="hidden lg:inline" />
|
<LinkIcon size={14} className="hidden lg:inline" />
|
||||||
<h3>
|
<h3 className="text-lg lg:text-xl">
|
||||||
<Highlight>
|
<Highlight>
|
||||||
{(isInterface ? "interface " : "class ") + name + typeParameters}
|
{(isInterface ? "interface " : "class ") + name + typeParameters}
|
||||||
</Highlight>
|
</Highlight>
|
||||||
</h3>
|
</h3>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-5">
|
<div className="flex flex-col gap-5 mt-5">
|
||||||
<div>{doc}</div>
|
{doc && <div>{doc}</div>}
|
||||||
<div>{children}</div>
|
<div>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -119,7 +119,7 @@ export function PropDecl({
|
|||||||
example?: ReactNode;
|
example?: ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="text-sm py-3 flex flex-col gap-5">
|
<div className="text-sm flex flex-col gap-3 my-2 p-3 rounded bg-stone-50 dark:bg-stone-925">
|
||||||
{(name || type) && (
|
{(name || type) && (
|
||||||
<div>
|
<div>
|
||||||
{name && <Highlight>{name + ":"}</Highlight>}
|
{name && <Highlight>{name + ":"}</Highlight>}
|
||||||
@@ -157,7 +157,7 @@ export function FnDecl({
|
|||||||
example: ReactNode;
|
example: ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="text-sm py-3 flex flex-col gap-5">
|
<div className="text-sm flex flex-col gap-3 my-2 p-3 rounded bg-stone-50 dark:bg-stone-925">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div>
|
<div>
|
||||||
{<Highlight>{signature + ":"}</Highlight>}{" "}
|
{<Highlight>{signature + ":"}</Highlight>}{" "}
|
||||||
@@ -201,7 +201,7 @@ export function PropCategory({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="col-span-6 uppercase font-medium tracking-widest text-stone-500 text-xs py-3">
|
<div className="col-span-6 py-3 font-display font-semibold text-lg text-stone-900 dark:text-white">
|
||||||
{name}
|
{name}
|
||||||
</div>
|
</div>
|
||||||
{description && <PropDecl doc={description} example={example} />}
|
{description && <PropDecl doc={description} example={example} />}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { socials } from "@/lib/socials";
|
||||||
import { GcmpLogo } from "gcmp-design-system/src/app/components/atoms/logos/GcmpLogo";
|
import { GcmpLogo } from "gcmp-design-system/src/app/components/atoms/logos/GcmpLogo";
|
||||||
import { Footer } from "gcmp-design-system/src/app/components/organisms/Footer";
|
import { Footer } from "gcmp-design-system/src/app/components/organisms/Footer";
|
||||||
|
|
||||||
@@ -6,6 +7,7 @@ export function JazzFooter() {
|
|||||||
<Footer
|
<Footer
|
||||||
logo={<GcmpLogo monochrome className="w-32" />}
|
logo={<GcmpLogo monochrome className="w-32" />}
|
||||||
companyName="Garden Computing, Inc."
|
companyName="Garden Computing, Inc."
|
||||||
|
socials={socials}
|
||||||
sections={[
|
sections={[
|
||||||
{
|
{
|
||||||
title: "Resources",
|
title: "Resources",
|
||||||
@@ -15,26 +17,6 @@ export function JazzFooter() {
|
|||||||
{ href: "/docs", label: "Docs" },
|
{ href: "/docs", label: "Docs" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "Community",
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
href: "https://github.com/gardencmp/jazz",
|
|
||||||
label: "GitHub",
|
|
||||||
newTab: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: "https://discord.gg/utDMjHYg42",
|
|
||||||
label: "Discord",
|
|
||||||
newTab: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: "https://x.com/jazz_tools",
|
|
||||||
label: "X",
|
|
||||||
newTab: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "News",
|
title: "News",
|
||||||
links: [
|
links: [
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { Card } from "gcmp-design-system/src/app/components/atoms/Card";
|
||||||
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
||||||
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
||||||
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
||||||
@@ -22,7 +23,7 @@ function Iframe(
|
|||||||
const { src, user } = props;
|
const { src, user } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative col-span-2 w-full border rounded-xl shadow-sm overflow-hidden lg:col-span-2 dark:bg-black">
|
<Card className="relative col-span-2 w-full overflow-hidden lg:col-span-2 dark:bg-black">
|
||||||
<iframe
|
<iframe
|
||||||
{...props}
|
{...props}
|
||||||
src={src}
|
src={src}
|
||||||
@@ -31,7 +32,7 @@ function Iframe(
|
|||||||
height="390"
|
height="390"
|
||||||
allowFullScreen
|
allowFullScreen
|
||||||
/>
|
/>
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Card } from "gcmp-design-system/src/app/components/atoms/Card";
|
||||||
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
||||||
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
||||||
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
||||||
@@ -42,8 +43,8 @@ export function CollaborationFeaturesSection() {
|
|||||||
|
|
||||||
<GappedGrid>
|
<GappedGrid>
|
||||||
{data.map(({ title, description, codeSample: CodeSample }) => (
|
{data.map(({ title, description, codeSample: CodeSample }) => (
|
||||||
<div
|
<Card
|
||||||
className="col-span-2 border rounded-xl shadow-sm pt-4 px-4 flex flex-col gap-3"
|
className="col-span-2 pt-4 px-4 flex flex-col gap-3"
|
||||||
key={title}
|
key={title}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
@@ -57,7 +58,7 @@ export function CollaborationFeaturesSection() {
|
|||||||
<pre className="flex-1 text-sm border-t border-x rounded-t-lg bg-stone-50 dark:bg-stone-925">
|
<pre className="flex-1 text-sm border-t border-x rounded-t-lg bg-stone-50 dark:bg-stone-925">
|
||||||
<CodeSample />
|
<CodeSample />
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</GappedGrid>
|
</GappedGrid>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ import CursorsAndCaretsDescription from "@/app/(home)/toolkit/cursorsAndCarets.m
|
|||||||
import TwoWaySyncDescription from "@/app/(home)/toolkit/twoWaySync.mdx";
|
import TwoWaySyncDescription from "@/app/(home)/toolkit/twoWaySync.mdx";
|
||||||
import VideoPresenceCallsDescription from "@/app/(home)/toolkit/videoPresenceCalls.mdx";
|
import VideoPresenceCallsDescription from "@/app/(home)/toolkit/videoPresenceCalls.mdx";
|
||||||
import { CodeRef } from "gcmp-design-system/src/app/components/atoms/CodeRef";
|
import { CodeRef } from "gcmp-design-system/src/app/components/atoms/CodeRef";
|
||||||
import { GridCard } from "gcmp-design-system/src/app/components/atoms/GridCard";
|
|
||||||
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
|
||||||
import { P } from "gcmp-design-system/src/app/components/atoms/Paragraph";
|
import { P } from "gcmp-design-system/src/app/components/atoms/Paragraph";
|
||||||
|
import { FeatureCard } from "gcmp-design-system/src/app/components/molecules/FeatureCard";
|
||||||
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
||||||
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
||||||
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
||||||
@@ -15,39 +14,40 @@ export function ComingSoonSection() {
|
|||||||
<div>
|
<div>
|
||||||
<SectionHeader title="More features coming soon" />
|
<SectionHeader title="More features coming soon" />
|
||||||
|
|
||||||
<GappedGrid>
|
<GappedGrid cols={4}>
|
||||||
<GridCard>
|
<FeatureCard className="p-4" label={<h3>Cursors & carets</h3>}>
|
||||||
<H3>Cursors & carets</H3>
|
<P>Ready-made spatial presence.</P>
|
||||||
<P className="text-lg">Ready-made spatial presence.</P>
|
|
||||||
<Prose size="sm">
|
<Prose size="sm">
|
||||||
<CursorsAndCaretsDescription />
|
<CursorsAndCaretsDescription />
|
||||||
</Prose>
|
</Prose>
|
||||||
</GridCard>
|
</FeatureCard>
|
||||||
|
|
||||||
<GridCard>
|
<FeatureCard className="p-4" label={<h3>Two-way sync to your DB</h3>}>
|
||||||
<H3>Two-way sync to your DB</H3>
|
<P>Add Jazz to an existing app.</P>
|
||||||
<P className="text-lg">Add Jazz to an existing app.</P>
|
|
||||||
<Prose size="sm">
|
<Prose size="sm">
|
||||||
<TwoWaySyncDescription />
|
<TwoWaySyncDescription />
|
||||||
</Prose>
|
</Prose>
|
||||||
</GridCard>
|
</FeatureCard>
|
||||||
|
|
||||||
<GridCard>
|
<FeatureCard className="p-4" label={<h3>Video presence & calls</h3>}>
|
||||||
<H3>Video presence & calls</H3>
|
<P>Stream and record audio & video.</P>
|
||||||
<P className="text-lg">Stream and record audio & video.</P>
|
|
||||||
<Prose size="sm">
|
<Prose size="sm">
|
||||||
<VideoPresenceCallsDescription />
|
<VideoPresenceCallsDescription />
|
||||||
</Prose>
|
</Prose>
|
||||||
</GridCard>
|
</FeatureCard>
|
||||||
|
|
||||||
<GridCard>
|
<FeatureCard
|
||||||
<H3>
|
className="p-4"
|
||||||
<CodeRef>CoPlainText</CodeRef> & <CodeRef>CoRichText</CodeRef>
|
label={
|
||||||
</H3>
|
<h3>
|
||||||
|
<CodeRef>CoPlainText</CodeRef> & <CodeRef>CoRichText</CodeRef>
|
||||||
|
</h3>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Prose size="sm">
|
<Prose size="sm">
|
||||||
<CoPlainTextDescription />
|
<CoPlainTextDescription />
|
||||||
</Prose>
|
</Prose>
|
||||||
</GridCard>
|
</FeatureCard>
|
||||||
</GappedGrid>
|
</GappedGrid>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
|
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
|
||||||
|
import { Card } from "gcmp-design-system/src/app/components/atoms/Card";
|
||||||
import { H2 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
import { H2 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
||||||
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
||||||
|
|
||||||
export function EarlyAdopterSection() {
|
export function EarlyAdopterSection() {
|
||||||
return (
|
return (
|
||||||
<div className="border rounded-xl shadow-sm p-4 md:py-16">
|
<Card className="p-4 md:py-16">
|
||||||
<div className="lg:max-w-3xl md:text-center mx-auto space-y-6">
|
<div className="lg:max-w-3xl md:text-center mx-auto space-y-6">
|
||||||
<p className="uppercase text-blue tracking-widest text-sm font-medium dark:text-stone-400">
|
<p className="uppercase text-blue tracking-widest text-sm font-medium dark:text-stone-400">
|
||||||
Become an early adopter
|
Become an early adopter
|
||||||
@@ -31,6 +32,6 @@ export function EarlyAdopterSection() {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Card } from "gcmp-design-system/src/app/components/atoms/Card";
|
||||||
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
||||||
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
||||||
import { LockKeyholeIcon } from "lucide-react";
|
import { LockKeyholeIcon } from "lucide-react";
|
||||||
@@ -64,7 +65,7 @@ function Illustration() {
|
|||||||
|
|
||||||
export function EncryptionSection() {
|
export function EncryptionSection() {
|
||||||
return (
|
return (
|
||||||
<div className="border rounded-xl bg-white shadow-sm overflow-hidden dark:bg-stone-925">
|
<Card className="overflow-hidden dark:bg-stone-925">
|
||||||
<div className="flex grid md:grid-cols-3 md:gap-3">
|
<div className="flex grid md:grid-cols-3 md:gap-3">
|
||||||
<div className="md:col-span-2 px-4 pb-4 md:p-8">
|
<div className="md:col-span-2 px-4 pb-4 md:p-8">
|
||||||
<H3 className="mb-0 text-balance">
|
<H3 className="mb-0 text-balance">
|
||||||
@@ -86,6 +87,6 @@ export function EncryptionSection() {
|
|||||||
|
|
||||||
<Illustration />
|
<Illustration />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ServerWorkersDiagram } from "@/components/home/ServerWorkersDiagram";
|
import { ServerWorkersDiagram } from "@/components/home/ServerWorkersDiagram";
|
||||||
import { ClerkLogo } from "@/components/icons/ClerkLogo";
|
import { ClerkLogo } from "@/components/icons/ClerkLogo";
|
||||||
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
|
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
|
||||||
|
import { Card } from "gcmp-design-system/src/app/components/atoms/Card";
|
||||||
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
import { H3 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
||||||
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
|
||||||
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
||||||
@@ -124,10 +125,7 @@ export function FeaturesSection() {
|
|||||||
|
|
||||||
<div className="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-6 gap-4 lg:gap-8">
|
<div className="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-6 gap-4 lg:gap-8">
|
||||||
{features.map(({ title, icon: Icon, description, illustration }) => (
|
{features.map(({ title, icon: Icon, description, illustration }) => (
|
||||||
<div
|
<Card key={title} className="col-span-2 overflow-hidden">
|
||||||
key={title}
|
|
||||||
className="col-span-2 border rounded-xl shadow-sm overflow-hidden"
|
|
||||||
>
|
|
||||||
<div className="h-48 flex w-full items-center justify-center">
|
<div className="h-48 flex w-full items-center justify-center">
|
||||||
{illustration}
|
{illustration}
|
||||||
</div>
|
</div>
|
||||||
@@ -137,7 +135,7 @@ export function FeaturesSection() {
|
|||||||
</h3>
|
</h3>
|
||||||
<Prose size="sm">{description}</Prose>
|
<Prose size="sm">{description}</Prose>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div className="border p-4 sm:p-8 shadow-sm rounded-xl col-span-2 sm:col-span-4 space-y-5">
|
<div className="border p-4 sm:p-8 shadow-sm rounded-xl col-span-2 sm:col-span-4 space-y-5">
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { clsx } from "clsx";
|
import { clsx } from "clsx";
|
||||||
|
import { Card } from "gcmp-design-system/src/app/components/atoms/Card";
|
||||||
import { H2 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
import { H2 } from "gcmp-design-system/src/app/components/atoms/Headings";
|
||||||
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
||||||
import CodeStepAction from "./CodeStepAction.mdx";
|
import CodeStepAction from "./CodeStepAction.mdx";
|
||||||
@@ -48,10 +49,10 @@ function Step({
|
|||||||
className?: string;
|
className?: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div
|
<Card
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
"rounded-lg overflow-hidden shadow-sm flex flex-col gap-6 border",
|
"overflow-hidden flex flex-col gap-6",
|
||||||
"pt-4 sm:pt-6",
|
"pt-4 sm:pt-6",
|
||||||
"col-span-2 lg:col-span-3",
|
"col-span-2 lg:col-span-3",
|
||||||
)}
|
)}
|
||||||
@@ -70,7 +71,7 @@ function Step({
|
|||||||
<p className="max-w-md">{description}</p>
|
<p className="max-w-md">{description}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 pl-4 sm:pl-12">{children}</div>
|
<div className="flex-1 pl-4 sm:pl-12">{children}</div>
|
||||||
</div>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { LabelledFeatureIcon } from "gcmp-design-system/src/app/components/molecules/LabelledFeatureIcon";
|
import { FeatureCard } from "gcmp-design-system/src/app/components/molecules/FeatureCard";
|
||||||
|
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
|
||||||
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
|
||||||
import {
|
import {
|
||||||
GaugeIcon,
|
GaugeIcon,
|
||||||
@@ -64,16 +65,16 @@ export function LocalFirstFeaturesSection() {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div className="grid sm:grid-cols-2 lg:grid-cols-4 gap-4 lg:gap-8">
|
<GappedGrid cols={4}>
|
||||||
{features.map(({ title, icon: Icon, description }) => (
|
{features.map(({ title, icon: Icon, description }) => (
|
||||||
<LabelledFeatureIcon
|
<FeatureCard
|
||||||
label={title}
|
label={title}
|
||||||
icon={Icon}
|
icon={Icon}
|
||||||
explanation={description}
|
explanation={description}
|
||||||
key={title}
|
key={title}
|
||||||
></LabelledFeatureIcon>
|
></FeatureCard>
|
||||||
))}
|
))}
|
||||||
</div>
|
</GappedGrid>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { SiDiscord, SiGithub, SiX } from "@icons-pack/react-simple-icons";
|
import { socials } from "@/lib/socials";
|
||||||
import { Button } from "gcmp-design-system/src/app/components/atoms/Button";
|
|
||||||
import { JazzLogo } from "gcmp-design-system/src/app/components/atoms/logos/JazzLogo";
|
import { JazzLogo } from "gcmp-design-system/src/app/components/atoms/logos/JazzLogo";
|
||||||
import { Nav } from "gcmp-design-system/src/app/components/organisms/Nav";
|
import { Nav } from "gcmp-design-system/src/app/components/organisms/Nav";
|
||||||
import { BookTextIcon, BoxIcon, CodeIcon } from "lucide-react";
|
import { BookTextIcon, BoxIcon, CodeIcon } from "lucide-react";
|
||||||
@@ -68,25 +67,8 @@ export function JazzNav() {
|
|||||||
href: "https://github.com/gardencmp/jazz/releases",
|
href: "https://github.com/gardencmp/jazz/releases",
|
||||||
newTab: true,
|
newTab: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "GitHub",
|
|
||||||
href: "https://github.com/gardencmp/jazz",
|
|
||||||
newTab: true,
|
|
||||||
icon: <SiGithub className="w-5" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Discord",
|
|
||||||
href: "https://discord.gg/utDMjHYg42",
|
|
||||||
newTab: true,
|
|
||||||
icon: <SiDiscord className="w-5" />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "X",
|
|
||||||
href: "https://x.com/jazz_tools",
|
|
||||||
newTab: true,
|
|
||||||
icon: <SiX className="w-5" />,
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
|
socials={socials}
|
||||||
docNav={<DocNav className="block h-auto" />}
|
docNav={<DocNav className="block h-auto" />}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -111,12 +111,27 @@ export const docNavigationItems = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Authentication",
|
name: "Authentication methods",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
name: "Auth methods overview",
|
name: "Overview",
|
||||||
href: "/docs/authentication/auth-methods",
|
href: "/docs/authentication/auth-methods",
|
||||||
done: 0,
|
done: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Passphrase",
|
||||||
|
href: "/docs/authentication/auth-methods#passphrase",
|
||||||
|
done: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Passkey",
|
||||||
|
href: "/docs/authentication/auth-methods#passkey",
|
||||||
|
done: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Clerk",
|
||||||
|
href: "/docs/authentication/auth-methods#clerk",
|
||||||
|
done: 20,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Writing your own",
|
name: "Writing your own",
|
||||||
|
|||||||
5
homepage/homepage/lib/socials.ts
Normal file
5
homepage/homepage/lib/socials.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const socials = {
|
||||||
|
github: "https://github.com/gardencmp/jazz",
|
||||||
|
discord: "https://discord.gg/utDMjHYg42",
|
||||||
|
x: "https://x.com/jazz_tools",
|
||||||
|
};
|
||||||
@@ -10,10 +10,6 @@ const nextConfig = {
|
|||||||
// Configure `pageExtensions`` to include MDX files
|
// Configure `pageExtensions`` to include MDX files
|
||||||
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"],
|
||||||
transpilePackages: ["gcmp-design-system"],
|
transpilePackages: ["gcmp-design-system"],
|
||||||
// Optionally, add any other Next.js config below
|
|
||||||
experimental: {
|
|
||||||
serverActions: true,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const withMDX = createMDX({
|
const withMDX = createMDX({
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "NODE_OPTIONS=--max-old-space-size=8192 next dev",
|
"dev": "NODE_OPTIONS=--max-old-space-size=8192 next dev",
|
||||||
"build": "node genDocs.mjs --build && next build",
|
"build:generate-docs": "node genDocs.mjs --build",
|
||||||
|
"build": "pnpm run build:generate-docs && next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"format-and-lint": "biome check .",
|
"format-and-lint": "biome check .",
|
||||||
"format-and-lint:fix": "biome check . --write"
|
"format-and-lint:fix": "biome check . --write"
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
"mdast-util-from-markdown": "^2.0.0",
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
"mdast-util-mdx": "^3.0.0",
|
"mdast-util-mdx": "^3.0.0",
|
||||||
"micromark-extension-mdxjs": "^3.0.0",
|
"micromark-extension-mdxjs": "^3.0.0",
|
||||||
"next": "13.5.4",
|
"next": "14.2.15",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
|
|||||||
493
homepage/pnpm-lock.yaml
generated
493
homepage/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
|||||||
"happy-dom": "^15.8.3",
|
"happy-dom": "^15.8.3",
|
||||||
"lefthook": "^1.8.2",
|
"lefthook": "^1.8.2",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"turbo": "^1.11.2",
|
"turbo": "^2.3.1",
|
||||||
"typedoc": "^0.25.13",
|
"typedoc": "^0.25.13",
|
||||||
"vitest": "1.5.3"
|
"vitest": "1.5.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,35 @@
|
|||||||
# cojson-storage-indexeddb
|
# cojson-storage-indexeddb
|
||||||
|
|
||||||
|
## 0.8.32
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
|
||||||
|
## 0.8.31
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
|
||||||
|
## 0.8.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
|
||||||
|
## 0.8.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
|
||||||
## 0.8.28
|
## 0.8.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cojson-storage-indexeddb",
|
"name": "cojson-storage-indexeddb",
|
||||||
"version": "0.8.28",
|
"version": "0.8.32",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cojson": "workspace:0.8.28"
|
"cojson": "workspace:0.8.32"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitest/browser": "^0.34.1",
|
"@vitest/browser": "^0.34.1",
|
||||||
|
|||||||
@@ -1,5 +1,35 @@
|
|||||||
# cojson-storage-sqlite
|
# cojson-storage-sqlite
|
||||||
|
|
||||||
|
## 0.8.32
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
|
||||||
|
## 0.8.31
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
|
||||||
|
## 0.8.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
|
||||||
|
## 0.8.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
|
||||||
## 0.8.28
|
## 0.8.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "cojson-storage-sqlite",
|
"name": "cojson-storage-sqlite",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.8.28",
|
"version": "0.8.32",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^8.5.2",
|
"better-sqlite3": "^8.5.2",
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,5 +1,36 @@
|
|||||||
# cojson-transport-nodejs-ws
|
# cojson-transport-nodejs-ws
|
||||||
|
|
||||||
|
## 0.8.32
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
|
||||||
|
## 0.8.31
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
|
||||||
|
## 0.8.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
|
||||||
|
## 0.8.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- dcc9c2e: Clear out the queues when closing a Peer
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
|
||||||
## 0.8.28
|
## 0.8.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cojson-transport-ws",
|
"name": "cojson-transport-ws",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.8.28",
|
"version": "0.8.32",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ function createOutgoingMessagesManager(
|
|||||||
websocket: AnyWebSocket,
|
websocket: AnyWebSocket,
|
||||||
batchingByDefault: boolean,
|
batchingByDefault: boolean,
|
||||||
) {
|
) {
|
||||||
|
let closed = false;
|
||||||
const outgoingMessages = new BatchedOutgoingMessages((messages) => {
|
const outgoingMessages = new BatchedOutgoingMessages((messages) => {
|
||||||
if (websocket.readyState === 1) {
|
if (websocket.readyState === 1) {
|
||||||
websocket.send(messages);
|
websocket.send(messages);
|
||||||
@@ -68,6 +69,10 @@ function createOutgoingMessagesManager(
|
|||||||
let batchingEnabled = batchingByDefault;
|
let batchingEnabled = batchingByDefault;
|
||||||
|
|
||||||
async function sendMessage(msg: SyncMessage) {
|
async function sendMessage(msg: SyncMessage) {
|
||||||
|
if (closed) {
|
||||||
|
return Promise.reject(new Error("WebSocket closed"));
|
||||||
|
}
|
||||||
|
|
||||||
if (websocket.readyState !== 1) {
|
if (websocket.readyState !== 1) {
|
||||||
await waitForWebSocketOpen(websocket);
|
await waitForWebSocketOpen(websocket);
|
||||||
}
|
}
|
||||||
@@ -98,6 +103,7 @@ function createOutgoingMessagesManager(
|
|||||||
batchingEnabled = enabled;
|
batchingEnabled = enabled;
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
|
closed = true;
|
||||||
outgoingMessages.close();
|
outgoingMessages.close();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -153,6 +153,23 @@ describe("createWebSocketPeer", () => {
|
|||||||
expect(mockWebSocket.close).toHaveBeenCalled();
|
expect(mockWebSocket.close).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should return a rejection if a message is sent after the peer is closed", async () => {
|
||||||
|
const { peer } = setup();
|
||||||
|
|
||||||
|
peer.outgoing.close();
|
||||||
|
|
||||||
|
const message: SyncMessage = {
|
||||||
|
action: "known",
|
||||||
|
id: "co_ztest",
|
||||||
|
header: false,
|
||||||
|
sessions: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
await expect(peer.outgoing.push(message)).rejects.toThrow(
|
||||||
|
"WebSocket closed",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
describe("batchingByDefault = true", () => {
|
describe("batchingByDefault = true", () => {
|
||||||
test("should batch outgoing messages", async () => {
|
test("should batch outgoing messages", async () => {
|
||||||
const { peer, mockWebSocket } = setup();
|
const { peer, mockWebSocket } = setup();
|
||||||
|
|||||||
@@ -1,5 +1,31 @@
|
|||||||
# cojson
|
# cojson
|
||||||
|
|
||||||
|
## 0.8.32
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- df42b2b: Catch hard-to-debug errors when trying to get edits at a CoMap key called "constructor"
|
||||||
|
|
||||||
|
## 0.8.31
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- e511d6d: Performance: make the isUploaded check on the SyncStateManager lazy
|
||||||
|
|
||||||
|
## 0.8.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 0a2fae3: More optimised way to get knownState
|
||||||
|
- 99cda2f: Reduce noise on peer close and increase the load timeout
|
||||||
|
|
||||||
|
## 0.8.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- dcc9c2e: Clear out the queues when closing a Peer
|
||||||
|
- 699553f: Restore offline support and improve loading perfromance when values are cached
|
||||||
|
|
||||||
## 0.8.28
|
## 0.8.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "0.8.28",
|
"version": "0.8.32",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.3",
|
"@types/jest": "^29.5.3",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { TryAddTransactionsError } from "./coValueCore.js";
|
|||||||
import { RawCoID } from "./ids.js";
|
import { RawCoID } from "./ids.js";
|
||||||
import { CO_VALUE_PRIORITY } from "./priority.js";
|
import { CO_VALUE_PRIORITY } from "./priority.js";
|
||||||
import { Peer, SyncMessage } from "./sync.js";
|
import { Peer, SyncMessage } from "./sync.js";
|
||||||
import { logSyncMessage } from "./utils.js";
|
|
||||||
|
|
||||||
export class PeerState {
|
export class PeerState {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -98,7 +97,9 @@ export class PeerState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pushOutgoingMessage(msg: SyncMessage) {
|
pushOutgoingMessage(msg: SyncMessage) {
|
||||||
logSyncMessage("to", this, msg);
|
if (this.closed) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
const promise = this.queue.push(msg);
|
const promise = this.queue.push(msg);
|
||||||
|
|
||||||
@@ -117,8 +118,17 @@ export class PeerState {
|
|||||||
return this.peer.incoming;
|
return this.peer.incoming;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private closeQueue() {
|
||||||
|
let entry: QueueEntry | undefined;
|
||||||
|
while ((entry = this.queue.pull())) {
|
||||||
|
// Using resolve here to avoid unnecessary noise in the logs
|
||||||
|
entry.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gracefulShutdown() {
|
gracefulShutdown() {
|
||||||
console.debug("Gracefully closing", this.id);
|
console.debug("Gracefully closing", this.id);
|
||||||
|
this.closeQueue();
|
||||||
this.peer.outgoing.close();
|
this.peer.outgoing.close();
|
||||||
this.closed = true;
|
this.closed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,29 +6,31 @@ import {
|
|||||||
emptyKnownState,
|
emptyKnownState,
|
||||||
} from "./sync.js";
|
} from "./sync.js";
|
||||||
|
|
||||||
|
export type SyncStateGetter = {
|
||||||
|
isUploaded: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GlobalSyncStateListenerCallback = (
|
||||||
|
peerId: PeerID,
|
||||||
|
knownState: CoValueKnownState,
|
||||||
|
sync: SyncStateGetter,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
export type PeerSyncStateListenerCallback = (
|
||||||
|
knownState: CoValueKnownState,
|
||||||
|
sync: SyncStateGetter,
|
||||||
|
) => void;
|
||||||
|
|
||||||
export class SyncStateSubscriptionManager {
|
export class SyncStateSubscriptionManager {
|
||||||
constructor(private syncManager: SyncManager) {}
|
constructor(private syncManager: SyncManager) {}
|
||||||
|
|
||||||
private listeners = new Set<
|
private listeners = new Set<GlobalSyncStateListenerCallback>();
|
||||||
(
|
|
||||||
peerId: PeerID,
|
|
||||||
knownState: CoValueKnownState,
|
|
||||||
uploadCompleted: boolean,
|
|
||||||
) => void
|
|
||||||
>();
|
|
||||||
|
|
||||||
private listenersByPeers = new Map<
|
private listenersByPeers = new Map<
|
||||||
PeerID,
|
PeerID,
|
||||||
Set<(knownState: CoValueKnownState, uploadCompleted: boolean) => void>
|
Set<PeerSyncStateListenerCallback>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
subscribeToUpdates(
|
subscribeToUpdates(listener: GlobalSyncStateListenerCallback) {
|
||||||
listener: (
|
|
||||||
peerId: PeerID,
|
|
||||||
knownState: CoValueKnownState,
|
|
||||||
uploadCompleted: boolean,
|
|
||||||
) => void,
|
|
||||||
) {
|
|
||||||
this.listeners.add(listener);
|
this.listeners.add(listener);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -38,7 +40,7 @@ export class SyncStateSubscriptionManager {
|
|||||||
|
|
||||||
subscribeToPeerUpdates(
|
subscribeToPeerUpdates(
|
||||||
peerId: PeerID,
|
peerId: PeerID,
|
||||||
listener: (knownState: CoValueKnownState, uploadCompleted: boolean) => void,
|
listener: PeerSyncStateListenerCallback,
|
||||||
) {
|
) {
|
||||||
const listeners = this.listenersByPeers.get(peerId) ?? new Set();
|
const listeners = this.listenersByPeers.get(peerId) ?? new Set();
|
||||||
|
|
||||||
@@ -68,19 +70,29 @@ export class SyncStateSubscriptionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const knownState = peer.knownStates.get(id) ?? emptyKnownState(id);
|
const knownState = peer.knownStates.get(id) ?? emptyKnownState(id);
|
||||||
const fullyUploadedIntoPeer = this.getIsCoValueFullyUploadedIntoPeer(
|
|
||||||
peerId,
|
// Build a lazy sync state object to process the isUploaded info
|
||||||
id,
|
// only when requested
|
||||||
|
const syncState = {} as SyncStateGetter;
|
||||||
|
|
||||||
|
const getIsUploaded = simpleMemoize(() =>
|
||||||
|
this.getIsCoValueFullyUploadedIntoPeer(peerId, id),
|
||||||
);
|
);
|
||||||
|
Object.defineProperties(syncState, {
|
||||||
|
isUploaded: {
|
||||||
|
enumerable: true,
|
||||||
|
get: getIsUploaded,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
for (const listener of this.listeners) {
|
for (const listener of this.listeners) {
|
||||||
listener(peerId, knownState, fullyUploadedIntoPeer);
|
listener(peerId, knownState, syncState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!peerListeners) return;
|
if (!peerListeners) return;
|
||||||
|
|
||||||
for (const listener of peerListeners) {
|
for (const listener of peerListeners) {
|
||||||
listener(knownState, fullyUploadedIntoPeer);
|
listener(knownState, syncState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,3 +134,8 @@ function getIsUploadCompleted(
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function simpleMemoize<T>(fn: () => T): () => T {
|
||||||
|
let value: T | undefined;
|
||||||
|
return () => value ?? (value = fn());
|
||||||
|
}
|
||||||
|
|||||||
@@ -155,15 +155,16 @@ export class CoValueCore {
|
|||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
knownStateUncached(): CoValueKnownState {
|
knownStateUncached(): CoValueKnownState {
|
||||||
|
const sessions: CoValueKnownState["sessions"] = {};
|
||||||
|
|
||||||
|
for (const [sessionID, sessionLog] of this.sessionLogs.entries()) {
|
||||||
|
sessions[sessionID] = sessionLog.transactions.length;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
header: true,
|
header: true,
|
||||||
sessions: Object.fromEntries(
|
sessions,
|
||||||
[...this.sessionLogs.entries()].map(([k, v]) => [
|
|
||||||
k,
|
|
||||||
v.transactions.length,
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { RawCoID } from "./ids.js";
|
|||||||
import { PeerID } from "./sync.js";
|
import { PeerID } from "./sync.js";
|
||||||
|
|
||||||
export const CO_VALUE_LOADING_MAX_RETRIES = 5;
|
export const CO_VALUE_LOADING_MAX_RETRIES = 5;
|
||||||
|
export const CO_VALUE_LOADING_TIMEOUT = 30_000;
|
||||||
|
|
||||||
export class CoValueUnknownState {
|
export class CoValueUnknownState {
|
||||||
type = "unknown" as const;
|
type = "unknown" as const;
|
||||||
@@ -264,22 +265,53 @@ async function loadCoValueFromPeers(
|
|||||||
peers: PeerState[],
|
peers: PeerState[],
|
||||||
) {
|
) {
|
||||||
for (const peer of peers) {
|
for (const peer of peers) {
|
||||||
|
if (peer.closed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (coValueEntry.state.type === "available") {
|
if (coValueEntry.state.type === "available") {
|
||||||
await peer.pushOutgoingMessage({
|
/**
|
||||||
action: "load",
|
* We don't need to wait for the message to be delivered here.
|
||||||
...coValueEntry.state.coValue.knownState(),
|
*
|
||||||
});
|
* This way when the coValue becomes available because it's cached we don't wait for the server
|
||||||
|
* peer to consume the messages queue before moving forward.
|
||||||
|
*/
|
||||||
|
peer
|
||||||
|
.pushOutgoingMessage({
|
||||||
|
action: "load",
|
||||||
|
...coValueEntry.state.coValue.knownState(),
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(`Failed to push load message to peer ${peer.id}`, err);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
await peer.pushOutgoingMessage({
|
/**
|
||||||
action: "load",
|
* We only wait for the load state to be resolved.
|
||||||
id: coValueEntry.id,
|
*/
|
||||||
header: false,
|
peer
|
||||||
sessions: {},
|
.pushOutgoingMessage({
|
||||||
});
|
action: "load",
|
||||||
|
id: coValueEntry.id,
|
||||||
|
header: false,
|
||||||
|
sessions: {},
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(`Failed to push load message to peer ${peer.id}`, err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coValueEntry.state.type === "loading") {
|
if (coValueEntry.state.type === "loading") {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
if (coValueEntry.state.type === "loading") {
|
||||||
|
console.error("Failed to load coValue from peer", peer.id);
|
||||||
|
coValueEntry.dispatch({
|
||||||
|
type: "not-found-in-peer",
|
||||||
|
peerId: peer.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, CO_VALUE_LOADING_TIMEOUT);
|
||||||
await coValueEntry.state.waitForPeer(peer.id);
|
await coValueEntry.state.waitForPeer(peer.id);
|
||||||
|
clearTimeout(timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ export class RawCoMapView<
|
|||||||
timeFilteredOps<K extends keyof Shape & string>(
|
timeFilteredOps<K extends keyof Shape & string>(
|
||||||
key: K,
|
key: K,
|
||||||
): MapOp<K, Shape[K]>[] | undefined {
|
): MapOp<K, Shape[K]>[] | undefined {
|
||||||
|
if (key === "constructor") {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.atTimeFilter) {
|
if (this.atTimeFilter) {
|
||||||
return this.ops[key]?.filter((op) => op.madeAt <= this.atTimeFilter!);
|
return this.ops[key]?.filter((op) => op.madeAt <= this.atTimeFilter!);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { Signature } from "./crypto/crypto.js";
|
|||||||
import { RawCoID, SessionID } from "./ids.js";
|
import { RawCoID, SessionID } from "./ids.js";
|
||||||
import { LocalNode } from "./localNode.js";
|
import { LocalNode } from "./localNode.js";
|
||||||
import { CoValuePriority } from "./priority.js";
|
import { CoValuePriority } from "./priority.js";
|
||||||
import { logSyncMessage } from "./utils.js";
|
|
||||||
|
|
||||||
export type CoValueKnownState = {
|
export type CoValueKnownState = {
|
||||||
id: RawCoID;
|
id: RawCoID;
|
||||||
@@ -143,7 +142,6 @@ export class SyncManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleSyncMessage(msg: SyncMessage, peer: PeerState) {
|
async handleSyncMessage(msg: SyncMessage, peer: PeerState) {
|
||||||
logSyncMessage("from", peer, msg);
|
|
||||||
if (peer.erroredCoValues.has(msg.id)) {
|
if (peer.erroredCoValues.has(msg.id)) {
|
||||||
console.error(
|
console.error(
|
||||||
`Skipping message ${msg.action} on errored coValue ${msg.id} from peer ${peer.id}`,
|
`Skipping message ${msg.action} on errored coValue ${msg.id} from peer ${peer.id}`,
|
||||||
@@ -453,12 +451,17 @@ export class SyncManager {
|
|||||||
dependencyEntry.state.type === "available" ||
|
dependencyEntry.state.type === "available" ||
|
||||||
dependencyEntry.state.type === "loading"
|
dependencyEntry.state.type === "loading"
|
||||||
) {
|
) {
|
||||||
this.local.loadCoValueCore(msg.id, peer.id).catch((e) => {
|
this.local
|
||||||
console.error(
|
.loadCoValueCore(
|
||||||
`Error loading coValue ${msg.id} to create loading state, as dependency of ${msg.asDependencyOf}`,
|
msg.id,
|
||||||
e,
|
peer.role === "storage" ? undefined : peer.id,
|
||||||
);
|
)
|
||||||
});
|
.catch((e) => {
|
||||||
|
console.error(
|
||||||
|
`Error loading coValue ${msg.id} to create loading state, as dependency of ${msg.asDependencyOf}`,
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Expected coValue dependency entry to be created, missing subscribe?",
|
"Expected coValue dependency entry to be created, missing subscribe?",
|
||||||
@@ -715,8 +718,8 @@ export class SyncManager {
|
|||||||
const unsubscribe =
|
const unsubscribe =
|
||||||
this.syncStateSubscriptionManager.subscribeToPeerUpdates(
|
this.syncStateSubscriptionManager.subscribeToPeerUpdates(
|
||||||
peerId,
|
peerId,
|
||||||
(knownState, uploadCompleted) => {
|
(knownState, syncState) => {
|
||||||
if (uploadCompleted && knownState.id === id) {
|
if (syncState.isUploaded && knownState.id === id) {
|
||||||
resolve(true);
|
resolve(true);
|
||||||
unsubscribe?.();
|
unsubscribe?.();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,36 @@ describe("PeerState", () => {
|
|||||||
consoleSpy.mockRestore();
|
consoleSpy.mockRestore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should empty the queue when closing", async () => {
|
||||||
|
const { mockPeer, peerState } = setup();
|
||||||
|
|
||||||
|
mockPeer.outgoing.push = vi.fn().mockImplementation((message) => {
|
||||||
|
return new Promise<void>((resolve) => {
|
||||||
|
setTimeout(resolve, 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const message1 = peerState.pushOutgoingMessage({
|
||||||
|
action: "content",
|
||||||
|
id: "co_z1",
|
||||||
|
new: {},
|
||||||
|
priority: CO_VALUE_PRIORITY.HIGH,
|
||||||
|
});
|
||||||
|
const message2 = peerState.pushOutgoingMessage({
|
||||||
|
action: "content",
|
||||||
|
id: "co_z1",
|
||||||
|
new: {},
|
||||||
|
priority: CO_VALUE_PRIORITY.HIGH,
|
||||||
|
});
|
||||||
|
|
||||||
|
peerState.gracefulShutdown();
|
||||||
|
|
||||||
|
await Promise.allSettled([message1, message2]);
|
||||||
|
|
||||||
|
await expect(message1).resolves.toBe(undefined);
|
||||||
|
await expect(message2).resolves.toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
test("should schedule outgoing messages based on their priority", async () => {
|
test("should schedule outgoing messages based on their priority", async () => {
|
||||||
const { peerState } = setup();
|
const { peerState } = setup();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { describe, expect, onTestFinished, test, vi } from "vitest";
|
import { describe, expect, onTestFinished, test, vi } from "vitest";
|
||||||
|
import {
|
||||||
|
GlobalSyncStateListenerCallback,
|
||||||
|
PeerSyncStateListenerCallback,
|
||||||
|
} from "../SyncStateSubscriptionManager.js";
|
||||||
import { connectedPeers } from "../streamUtils.js";
|
import { connectedPeers } from "../streamUtils.js";
|
||||||
import { emptyKnownState } from "../sync.js";
|
import { emptyKnownState } from "../sync.js";
|
||||||
import { createTestNode, waitFor } from "./testUtils.js";
|
import { createTestNode, waitFor } from "./testUtils.js";
|
||||||
@@ -29,7 +33,7 @@ describe("SyncStateSubscriptionManager", () => {
|
|||||||
|
|
||||||
const subscriptionManager = client.syncManager.syncStateSubscriptionManager;
|
const subscriptionManager = client.syncManager.syncStateSubscriptionManager;
|
||||||
|
|
||||||
const updateSpy = vi.fn();
|
const updateSpy: GlobalSyncStateListenerCallback = vi.fn();
|
||||||
const unsubscribe = subscriptionManager.subscribeToUpdates(updateSpy);
|
const unsubscribe = subscriptionManager.subscribeToUpdates(updateSpy);
|
||||||
|
|
||||||
await client.syncManager.actuallySyncCoValue(map.core);
|
await client.syncManager.actuallySyncCoValue(map.core);
|
||||||
@@ -37,7 +41,7 @@ describe("SyncStateSubscriptionManager", () => {
|
|||||||
expect(updateSpy).toHaveBeenCalledWith(
|
expect(updateSpy).toHaveBeenCalledWith(
|
||||||
"jazzCloudConnection",
|
"jazzCloudConnection",
|
||||||
emptyKnownState(map.core.id),
|
emptyKnownState(map.core.id),
|
||||||
false,
|
{ isUploaded: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
@@ -52,7 +56,7 @@ describe("SyncStateSubscriptionManager", () => {
|
|||||||
client.syncManager.peers["jazzCloudConnection"]!.knownStates.get(
|
client.syncManager.peers["jazzCloudConnection"]!.knownStates.get(
|
||||||
map.core.id,
|
map.core.id,
|
||||||
)!,
|
)!,
|
||||||
true,
|
{ isUploaded: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
@@ -90,8 +94,8 @@ describe("SyncStateSubscriptionManager", () => {
|
|||||||
|
|
||||||
const subscriptionManager = client.syncManager.syncStateSubscriptionManager;
|
const subscriptionManager = client.syncManager.syncStateSubscriptionManager;
|
||||||
|
|
||||||
const updateToJazzCloudSpy = vi.fn();
|
const updateToJazzCloudSpy: PeerSyncStateListenerCallback = vi.fn();
|
||||||
const updateToStorageSpy = vi.fn();
|
const updateToStorageSpy: PeerSyncStateListenerCallback = vi.fn();
|
||||||
const unsubscribe1 = subscriptionManager.subscribeToPeerUpdates(
|
const unsubscribe1 = subscriptionManager.subscribeToPeerUpdates(
|
||||||
"jazzCloudConnection",
|
"jazzCloudConnection",
|
||||||
updateToJazzCloudSpy,
|
updateToJazzCloudSpy,
|
||||||
@@ -110,7 +114,7 @@ describe("SyncStateSubscriptionManager", () => {
|
|||||||
|
|
||||||
expect(updateToJazzCloudSpy).toHaveBeenCalledWith(
|
expect(updateToJazzCloudSpy).toHaveBeenCalledWith(
|
||||||
emptyKnownState(map.core.id),
|
emptyKnownState(map.core.id),
|
||||||
false,
|
{ isUploaded: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
@@ -124,12 +128,12 @@ describe("SyncStateSubscriptionManager", () => {
|
|||||||
client.syncManager.peers["jazzCloudConnection"]!.knownStates.get(
|
client.syncManager.peers["jazzCloudConnection"]!.knownStates.get(
|
||||||
map.core.id,
|
map.core.id,
|
||||||
)!,
|
)!,
|
||||||
true,
|
{ isUploaded: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(updateToStorageSpy).toHaveBeenLastCalledWith(
|
expect(updateToStorageSpy).toHaveBeenLastCalledWith(
|
||||||
emptyKnownState(map.core.id),
|
emptyKnownState(map.core.id),
|
||||||
false,
|
{ isUploaded: false },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -388,6 +388,79 @@ describe("CoValueState", () => {
|
|||||||
|
|
||||||
vi.useRealTimers();
|
vi.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should skip closed peers", async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const mockCoValue = createMockCoValueCore(mockCoValueId);
|
||||||
|
|
||||||
|
const peer1 = createMockPeerState(
|
||||||
|
{
|
||||||
|
id: "peer1",
|
||||||
|
role: "storage",
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
return new Promise(() => {});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const peer2 = createMockPeerState(
|
||||||
|
{
|
||||||
|
id: "peer1",
|
||||||
|
role: "server",
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
state.dispatch({
|
||||||
|
type: "available",
|
||||||
|
coValue: mockCoValue,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
peer1.closed = true;
|
||||||
|
|
||||||
|
const state = CoValueState.Unknown(mockCoValueId);
|
||||||
|
const loadPromise = state.loadFromPeers([peer1, peer2]);
|
||||||
|
|
||||||
|
for (let i = 0; i < CO_VALUE_LOADING_MAX_RETRIES; i++) {
|
||||||
|
await vi.runAllTimersAsync();
|
||||||
|
}
|
||||||
|
await loadPromise;
|
||||||
|
|
||||||
|
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(0);
|
||||||
|
expect(peer2.pushOutgoingMessage).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
expect(state.state.type).toBe("available");
|
||||||
|
await expect(state.getCoValue()).resolves.toEqual({ id: mockCoValueId });
|
||||||
|
|
||||||
|
vi.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should not be stuck in loading state when not getting a response", async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const peer1 = createMockPeerState(
|
||||||
|
{
|
||||||
|
id: "peer1",
|
||||||
|
role: "server",
|
||||||
|
},
|
||||||
|
async () => {},
|
||||||
|
);
|
||||||
|
|
||||||
|
const state = CoValueState.Unknown(mockCoValueId);
|
||||||
|
const loadPromise = state.loadFromPeers([peer1]);
|
||||||
|
|
||||||
|
for (let i = 0; i < CO_VALUE_LOADING_MAX_RETRIES * 2; i++) {
|
||||||
|
await vi.runAllTimersAsync();
|
||||||
|
}
|
||||||
|
await loadPromise;
|
||||||
|
|
||||||
|
expect(peer1.pushOutgoingMessage).toHaveBeenCalledTimes(5);
|
||||||
|
|
||||||
|
expect(state.state.type).toBe("unavailable");
|
||||||
|
await expect(state.getCoValue()).resolves.toEqual("unavailable");
|
||||||
|
|
||||||
|
vi.useRealTimers();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function createMockPeerState(
|
function createMockPeerState(
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { PeerState } from "./PeerState";
|
|
||||||
import type { SyncMessage } from "./sync";
|
|
||||||
|
|
||||||
export function logSyncMessage(
|
|
||||||
direction: "to" | "from",
|
|
||||||
peer: PeerState,
|
|
||||||
msg: SyncMessage,
|
|
||||||
) {
|
|
||||||
const directionBox = `background-color: ${direction === "to" ? "yellow" : "red"}; color: ${direction === "to" ? "black" : "white"}; padding: 1px 2px; margin-bottom: 4px; font-style: italic; border: 1px solid hotpink`;
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`%c${direction === "to" ? "node --->" : "node <----"} ${peer.role}`,
|
|
||||||
directionBox,
|
|
||||||
msg.action,
|
|
||||||
msg.id,
|
|
||||||
`header:`,
|
|
||||||
(msg as any).header,
|
|
||||||
`sessions:`,
|
|
||||||
(msg as any).sessions,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,45 @@
|
|||||||
# jazz-browser-media-images
|
# jazz-browser-media-images
|
||||||
|
|
||||||
|
## 0.8.32
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- 1a4bda0: Document usage in readme
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-browser@0.8.32
|
||||||
|
|
||||||
|
## 0.8.31
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
- jazz-browser@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.8.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
- jazz-browser@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.8.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson@0.8.29
|
||||||
|
- jazz-browser@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.8.28
|
## 0.8.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -2,40 +2,30 @@
|
|||||||
|
|
||||||
This package provides a [Clerk-based](https://clerk.com/) authentication strategy for Jazz.
|
This package provides a [Clerk-based](https://clerk.com/) authentication strategy for Jazz.
|
||||||
|
|
||||||
|
Looking for a React integration? Check out [`jazz-react-auth-clerk`](https://www.npmjs.com/package/jazz-react-auth-clerk).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`useJazzClerkAuth` is a hook that returns a `JazzAuth` object and a `JazzAuthState` object. Provide a Clerk instance to `useJazzClerkAuth`, and it will return the appropriate `JazzAuth` object. Once authenticated, authentication will persist across page reloads, even if the device is offline.
|
`BrowserClerkAuth` is a class that provides a `JazzAuth` object. Provide a Clerk instance to `BrowserClerkAuth`, and it will return the appropriate `JazzAuth` object. Once authenticated, authentication will persist across page reloads, even if the device is offline.
|
||||||
|
|
||||||
|
|
||||||
From [the example chat app](https://github.com/gardencmp/jazz/tree/main/examples/chat-clerk):
|
From [the example chat app](https://github.com/gardencmp/jazz/tree/main/examples/chat-clerk):
|
||||||
|
|
||||||
```typescript
|
```ts
|
||||||
import { ClerkProvider, SignInButton, useClerk } from "@clerk/clerk-react";
|
import { BrowserClerkAuth } from "jazz-browser-auth-clerk";
|
||||||
import { useJazzClerkAuth } from "jazz-react-auth-clerk";
|
|
||||||
|
|
||||||
const Jazz = createJazzReactApp();
|
// ...
|
||||||
export const { useAccount, useCoState } = Jazz;
|
|
||||||
|
|
||||||
function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
const auth = new BrowserClerkAuth(
|
||||||
const clerk = useClerk();
|
{
|
||||||
const [auth, state] = useJazzClerkAuth(clerk);
|
onError: (error) => {
|
||||||
|
void clerk.signOut();
|
||||||
return (
|
setState((state) => ({
|
||||||
<>
|
...state,
|
||||||
{state.errors.map((error) => (
|
errors: [...state.errors, error.toString()],
|
||||||
<div key={error}>{error}</div>
|
}));
|
||||||
))}
|
},
|
||||||
{auth ? (
|
},
|
||||||
<Jazz.Provider
|
clerk,
|
||||||
auth={auth}
|
);
|
||||||
peer="wss://cloud.jazz.tools/?key=chat-example-jazz-clerk@gcmp.io"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Jazz.Provider>
|
|
||||||
) : (
|
|
||||||
<SignInButton />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-browser-auth-clerk",
|
"name": "jazz-browser-auth-clerk",
|
||||||
"version": "0.8.28",
|
"version": "0.8.32",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"jazz-browser": "workspace:0.8.28",
|
"jazz-browser": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28"
|
"jazz-tools": "workspace:0.8.32"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"format-and-lint": "biome check .",
|
"format-and-lint": "biome check .",
|
||||||
|
|||||||
@@ -1,5 +1,34 @@
|
|||||||
# jazz-browser-media-images
|
# jazz-browser-media-images
|
||||||
|
|
||||||
|
## 0.8.32
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- jazz-browser@0.8.32
|
||||||
|
|
||||||
|
## 0.8.31
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.8.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.8.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- jazz-browser@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.8.28
|
## 0.8.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-browser-media-images",
|
"name": "jazz-browser-media-images",
|
||||||
"version": "0.8.28",
|
"version": "0.8.32",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/image-blob-reduce": "^4.1.1",
|
"@types/image-blob-reduce": "^4.1.1",
|
||||||
"image-blob-reduce": "^4.1.0",
|
"image-blob-reduce": "^4.1.0",
|
||||||
"jazz-browser": "workspace:0.8.28",
|
"jazz-browser": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"pica": "^9.0.1",
|
"pica": "^9.0.1",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,48 @@
|
|||||||
# jazz-browser
|
# jazz-browser
|
||||||
|
|
||||||
|
## 0.8.32
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- Updated dependencies [df42b2b]
|
||||||
|
- cojson@0.8.32
|
||||||
|
- jazz-tools@0.8.32
|
||||||
|
- cojson-storage-indexeddb@0.8.32
|
||||||
|
- cojson-transport-ws@0.8.32
|
||||||
|
|
||||||
|
## 0.8.31
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [e511d6d]
|
||||||
|
- cojson@0.8.31
|
||||||
|
- cojson-storage-indexeddb@0.8.31
|
||||||
|
- cojson-transport-ws@0.8.31
|
||||||
|
- jazz-tools@0.8.31
|
||||||
|
|
||||||
|
## 0.8.30
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [0a2fae3]
|
||||||
|
- Updated dependencies [99cda2f]
|
||||||
|
- cojson@0.8.30
|
||||||
|
- cojson-storage-indexeddb@0.8.30
|
||||||
|
- cojson-transport-ws@0.8.30
|
||||||
|
- jazz-tools@0.8.30
|
||||||
|
|
||||||
|
## 0.8.29
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [dcc9c2e]
|
||||||
|
- Updated dependencies [699553f]
|
||||||
|
- cojson-transport-ws@0.8.29
|
||||||
|
- cojson@0.8.29
|
||||||
|
- cojson-storage-indexeddb@0.8.29
|
||||||
|
- jazz-tools@0.8.29
|
||||||
|
|
||||||
## 0.8.28
|
## 0.8.28
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "jazz-browser",
|
"name": "jazz-browser",
|
||||||
"version": "0.8.28",
|
"version": "0.8.32",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scure/bip39": "^1.3.0",
|
"@scure/bip39": "^1.3.0",
|
||||||
"cojson": "workspace:0.8.28",
|
"cojson": "workspace:0.8.32",
|
||||||
"cojson-storage-indexeddb": "workspace:0.8.28",
|
"cojson-storage-indexeddb": "workspace:0.8.32",
|
||||||
"cojson-transport-ws": "workspace:0.8.28",
|
"cojson-transport-ws": "workspace:0.8.32",
|
||||||
"jazz-tools": "workspace:0.8.28",
|
"jazz-tools": "workspace:0.8.32",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -8,6 +8,19 @@ type StorageData = {
|
|||||||
|
|
||||||
const localStorageKey = "demo-auth-logged-in-secret";
|
const localStorageKey = "demo-auth-logged-in-secret";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `BrowserDemoAuth` provides a `JazzAuth` object for demo authentication.
|
||||||
|
*
|
||||||
|
* Demo authentication is useful for quickly testing your app, as it allows you to create new accounts and log in as existing ones. The authentication persists across page reloads, but as the data is stored in `localStorage`, it will be lost when the browser is closed.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* import { BrowserDemoAuth } from "jazz-browser";
|
||||||
|
*
|
||||||
|
* const auth = new BrowserDemoAuth(driver);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @category Auth Providers
|
||||||
|
*/
|
||||||
export class BrowserDemoAuth implements AuthMethod {
|
export class BrowserDemoAuth implements AuthMethod {
|
||||||
constructor(
|
constructor(
|
||||||
public driver: BrowserDemoAuth.Driver,
|
public driver: BrowserDemoAuth.Driver,
|
||||||
@@ -37,6 +50,9 @@ export class BrowserDemoAuth implements AuthMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns A `JazzAuth` object
|
||||||
|
*/
|
||||||
async start() {
|
async start() {
|
||||||
if (localStorage["demo-auth-logged-in-secret"]) {
|
if (localStorage["demo-auth-logged-in-secret"]) {
|
||||||
const localStorageData = JSON.parse(
|
const localStorageData = JSON.parse(
|
||||||
@@ -129,7 +145,7 @@ export class BrowserDemoAuth implements AuthMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @category Auth Providers */
|
/** @internal */
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
export namespace BrowserDemoAuth {
|
export namespace BrowserDemoAuth {
|
||||||
export interface Driver {
|
export interface Driver {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user