Compare commits
34 Commits
jazz-react
...
jazz-react
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9356ffbd4e | ||
|
|
328227316c | ||
|
|
dd5fe12dfe | ||
|
|
f837cfe994 | ||
|
|
978c30a7ca | ||
|
|
e2c02824e7 | ||
|
|
6dac7c7ce5 | ||
|
|
d0724a2c13 | ||
|
|
4c632e14a4 | ||
|
|
d7238267d9 | ||
|
|
a6cf01f867 | ||
|
|
17d148b1d2 | ||
|
|
2544782988 | ||
|
|
8f42c7a749 | ||
|
|
49784a7e65 | ||
|
|
935cd745ba | ||
|
|
608d06d46f | ||
|
|
7690e19014 | ||
|
|
4626c79c46 | ||
|
|
aad0bd60f4 | ||
|
|
1fbe8d9651 | ||
|
|
6e28ac946b | ||
|
|
cfce22fc63 | ||
|
|
ecfc883419 | ||
|
|
4aded04223 | ||
|
|
3167ff16cd | ||
|
|
2e70b2b295 | ||
|
|
9a5e6eed16 | ||
|
|
28d74d73f8 | ||
|
|
6c9d90449a | ||
|
|
5398978d74 | ||
|
|
53148db482 | ||
|
|
44a0b54026 | ||
|
|
c877d377d2 |
@@ -13,7 +13,9 @@
|
||||
"**/android/**",
|
||||
"packages/jazz-svelte/**",
|
||||
"examples/*svelte*/**",
|
||||
"homepage/homepage/**"
|
||||
"examples/jazz-paper-scissors/src/routeTree.gen.ts",
|
||||
"homepage/homepage/**",
|
||||
"**/package.json"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# chat-rn-expo-clerk
|
||||
|
||||
## 1.0.102
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
- jazz-react-native-media-images@0.13.10
|
||||
|
||||
## 1.0.101
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-expo@0.13.9
|
||||
- jazz-react-native-media-images@0.13.9
|
||||
|
||||
## 1.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "chat-rn-expo-clerk",
|
||||
"main": "index.js",
|
||||
"version": "1.0.100",
|
||||
"version": "1.0.102",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
"start": "expo start",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# chat-rn-expo
|
||||
|
||||
## 1.0.89
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-expo@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 1.0.88
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-expo@0.13.9
|
||||
|
||||
## 1.0.87
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn-expo",
|
||||
"version": "1.0.87",
|
||||
"version": "1.0.89",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "expo export -p ios",
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# chat-rn
|
||||
|
||||
## 1.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
- cojson-transport-ws@0.13.10
|
||||
- jazz-react-native@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 1.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react-native@0.13.9
|
||||
|
||||
## 1.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-rn",
|
||||
"version": "1.0.95",
|
||||
"version": "1.0.97",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# chat-vue
|
||||
|
||||
## 0.0.81
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
- jazz-vue@0.13.10
|
||||
|
||||
## 0.0.80
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-browser@0.13.9
|
||||
- jazz-vue@0.13.9
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chat-vue",
|
||||
"version": "0.0.79",
|
||||
"version": "0.0.81",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-example-chat
|
||||
|
||||
## 0.0.179
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.10
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.178
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-inspector@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.177
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-chat",
|
||||
"private": true,
|
||||
"version": "0.0.177",
|
||||
"version": "0.0.179",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# minimal-auth-clerk
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-react-auth-clerk@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.77
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
- jazz-react-auth-clerk@0.13.9
|
||||
|
||||
## 0.0.76
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "clerk",
|
||||
"private": true,
|
||||
"version": "0.0.76",
|
||||
"version": "0.0.78",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# file-share-svelte
|
||||
|
||||
## 0.0.61
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.60
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-svelte@0.13.9
|
||||
|
||||
## 0.0.59
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "file-share-svelte",
|
||||
"version": "0.0.59",
|
||||
"version": "0.0.61",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-tailwind-demo-auth-starter
|
||||
|
||||
## 0.0.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.10
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-inspector@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "filestream",
|
||||
"private": true,
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.18",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# form
|
||||
|
||||
## 0.1.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.1.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.1.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "form",
|
||||
"private": true,
|
||||
"version": "0.1.17",
|
||||
"version": "0.1.19",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# image-upload
|
||||
|
||||
## 0.0.75
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.74
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.73
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "image-upload",
|
||||
"private": true,
|
||||
"version": "0.0.73",
|
||||
"version": "0.0.75",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-example-inspector
|
||||
|
||||
## 0.0.129
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
- cojson-transport-ws@0.13.10
|
||||
- jazz-inspector@0.13.10
|
||||
|
||||
## 0.0.128
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.9
|
||||
|
||||
## 0.0.127
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-inspector-app",
|
||||
"private": true,
|
||||
"version": "0.0.127",
|
||||
"version": "0.0.129",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
2
examples/jazz-paper-scissors/.env.example
Normal file
2
examples/jazz-paper-scissors/.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
VITE_JAZZ_WORKER_ACCOUNT=
|
||||
JAZZ_WORKER_SECRET=
|
||||
3
examples/jazz-paper-scissors/.gitignore
vendored
Normal file
3
examples/jazz-paper-scissors/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
dist
|
||||
|
||||
.env
|
||||
8
examples/jazz-paper-scissors/.prettierignore
Normal file
8
examples/jazz-paper-scissors/.prettierignore
Normal file
@@ -0,0 +1,8 @@
|
||||
# Ignore artifacts:
|
||||
build
|
||||
coverage
|
||||
|
||||
**/.git
|
||||
**/.svn
|
||||
**/.hg
|
||||
**/node_modules
|
||||
24
examples/jazz-paper-scissors/README.md
Normal file
24
examples/jazz-paper-scissors/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Jazz Paper Scissors
|
||||
|
||||
## Setup
|
||||
|
||||
First of we need to create a new account for the dealer:
|
||||
|
||||
```bash
|
||||
pnpm generate-env
|
||||
```
|
||||
|
||||
This will generate a .env file like this one
|
||||
|
||||
```
|
||||
VITE_JAZZ_WORKER_ACCOUNT=co_zn95yzQd1z24DJCgayN53ShyuMR
|
||||
JAZZ_WORKER_SECRET=sealerSecret_z3Tcq41gtELJRHk3SzQutR2DhkpvEScQQP8DG8yeSh7zJ/signerSecret_zDsLhoNRSxjXrX6oSGzGH3XQQHDyp8QS292p28RToANYq
|
||||
```
|
||||
|
||||
This should be enough the setup everything
|
||||
|
||||
Then run pnpm dev to start both the local build and the worker
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
21
examples/jazz-paper-scissors/components.json
Normal file
21
examples/jazz-paper-scissors/components.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
21
examples/jazz-paper-scissors/generate-env.ts
Normal file
21
examples/jazz-paper-scissors/generate-env.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as fs from "fs";
|
||||
import { createWorkerAccount } from "jazz-run/createWorkerAccount";
|
||||
|
||||
if (fs.existsSync(".env")) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const account = await createWorkerAccount({
|
||||
name: "jazz-paper-scissors-worker",
|
||||
peer: "wss://cloud.jazz.tools/?key=jazz-paper-scissors@garden.co",
|
||||
});
|
||||
|
||||
fs.writeFileSync(
|
||||
".env",
|
||||
`
|
||||
VITE_JAZZ_WORKER_ACCOUNT=${account.accountID}
|
||||
JAZZ_WORKER_SECRET=${account.agentSecret}
|
||||
`,
|
||||
);
|
||||
|
||||
process.exit(0);
|
||||
20
examples/jazz-paper-scissors/index.html
Normal file
20
examples/jazz-paper-scissors/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-tsrouter-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="/logo192.png" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<title>Jazz example - Jazz Paper Scissors</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
44
examples/jazz-paper-scissors/package.json
Normal file
44
examples/jazz-paper-scissors/package.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "jazz-paper-scissors",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "npm-run-all --parallel dev:web dev:worker",
|
||||
"dev:web": "vite",
|
||||
"dev:worker": "tsx --watch --env-file=.env ./src/worker.ts",
|
||||
"build": "vite build && tsc",
|
||||
"serve": "vite preview",
|
||||
"generate-env": "tsx generate-env.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-label": "^2.1.2",
|
||||
"@radix-ui/react-separator": "^1.1.2",
|
||||
"@radix-ui/react-slot": "^1.1.2",
|
||||
"@tailwindcss/vite": "^4.0.17",
|
||||
"@tanstack/react-router": "^1.115.0",
|
||||
"@tanstack/react-router-devtools": "^1.114.29",
|
||||
"@tanstack/router-plugin": "^1.114.30",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"jazz-inspector": "workspace:*",
|
||||
"jazz-nodejs": "workspace:*",
|
||||
"jazz-react": "workspace:*",
|
||||
"jazz-tools": "workspace:*",
|
||||
"lucide-react": "^0.485.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwindcss": "^4.0.17",
|
||||
"tw-animate-css": "^1.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"jazz-run": "workspace:*",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "~5.6.2",
|
||||
"vite": "6.0.11"
|
||||
}
|
||||
}
|
||||
BIN
examples/jazz-paper-scissors/public/favicon.ico
Normal file
BIN
examples/jazz-paper-scissors/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
15
examples/jazz-paper-scissors/public/manifest.json
Normal file
15
examples/jazz-paper-scissors/public/manifest.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "TanStack App",
|
||||
"name": "Create TanStack App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
3
examples/jazz-paper-scissors/public/robots.txt
Normal file
3
examples/jazz-paper-scissors/public/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
33
examples/jazz-paper-scissors/src/app.tsx
Normal file
33
examples/jazz-paper-scissors/src/app.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import { RouterProvider, createRouter } from "@tanstack/react-router";
|
||||
import { useAccount } from "jazz-react";
|
||||
import { routeTree } from "./routeTree.gen";
|
||||
|
||||
// Create a new router instance
|
||||
const router = createRouter({
|
||||
routeTree,
|
||||
context: {
|
||||
// @ts-expect-error - just a placeholder - me is set in the App component down below
|
||||
me: undefined,
|
||||
},
|
||||
defaultPreload: "intent",
|
||||
scrollRestoration: true,
|
||||
defaultStructuralSharing: true,
|
||||
defaultPreloadStaleTime: 0,
|
||||
});
|
||||
|
||||
// Register the router instance for type safety
|
||||
declare module "@tanstack/react-router" {
|
||||
interface Register {
|
||||
router: typeof router;
|
||||
}
|
||||
}
|
||||
|
||||
export function App() {
|
||||
const { me } = useAccount();
|
||||
|
||||
if (!me) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
return <RouterProvider router={router} context={{ me }} />;
|
||||
}
|
||||
79
examples/jazz-paper-scissors/src/components/ui/button.tsx
Normal file
79
examples/jazz-paper-scissors/src/components/ui/button.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Slot } from "@radix-ui/react-slot";
|
||||
import { type VariantProps, cva } from "class-variance-authority";
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Loader2Icon } from "lucide-react";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
||||
outline:
|
||||
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
ghost:
|
||||
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
||||
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
||||
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
||||
icon: "size-9",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
interface Props
|
||||
extends React.ComponentProps<"button">,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean;
|
||||
loading?: boolean;
|
||||
loadingText?: string;
|
||||
}
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant,
|
||||
size,
|
||||
asChild = false,
|
||||
loading = false,
|
||||
disabled,
|
||||
loadingText = "Loading...",
|
||||
children,
|
||||
...props
|
||||
}: Props) {
|
||||
const Comp = asChild ? Slot : "button";
|
||||
|
||||
return (
|
||||
<Comp
|
||||
data-slot="button"
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
disabled={loading || disabled}
|
||||
{...props}
|
||||
>
|
||||
{loading ? (
|
||||
<>
|
||||
<Loader2Icon className="mr-2 h-4 w-4 animate-spin" />
|
||||
{loadingText}
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</Comp>
|
||||
);
|
||||
}
|
||||
|
||||
export { Button, buttonVariants };
|
||||
109
examples/jazz-paper-scissors/src/components/ui/card.tsx
Normal file
109
examples/jazz-paper-scissors/src/components/ui/card.tsx
Normal file
@@ -0,0 +1,109 @@
|
||||
import type * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card"
|
||||
className={cn(
|
||||
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-header"
|
||||
className={cn(
|
||||
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-title"
|
||||
className={cn("leading-none font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-description"
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-action"
|
||||
className={cn(
|
||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardSmall({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-small"
|
||||
className={cn(
|
||||
"sm-card grid grid-flow-col justify-items-center gap-6 rounded-xl border py-6 shadow-sm m-4",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-content"
|
||||
className={cn("px-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-footer"
|
||||
className={cn(
|
||||
"flex items-center px-6 [.border-t]:pt-6 border-t",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
CardSmall,
|
||||
};
|
||||
21
examples/jazz-paper-scissors/src/components/ui/input.tsx
Normal file
21
examples/jazz-paper-scissors/src/components/ui/input.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
data-slot="input"
|
||||
className={cn(
|
||||
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { Input };
|
||||
@@ -0,0 +1,13 @@
|
||||
import { JazzProvider } from "jazz-react";
|
||||
|
||||
export function JazzAndAuth({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<JazzProvider
|
||||
sync={{
|
||||
peer: "wss://cloud.jazz.tools/?key=jazz-paper-scissors@garden.co",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</JazzProvider>
|
||||
);
|
||||
}
|
||||
22
examples/jazz-paper-scissors/src/components/ui/label.tsx
Normal file
22
examples/jazz-paper-scissors/src/components/ui/label.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import * as LabelPrimitive from "@radix-ui/react-label";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Label({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
||||
return (
|
||||
<LabelPrimitive.Root
|
||||
data-slot="label"
|
||||
className={cn(
|
||||
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { Label };
|
||||
28
examples/jazz-paper-scissors/src/components/ui/separator.tsx
Normal file
28
examples/jazz-paper-scissors/src/components/ui/separator.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Separator({
|
||||
className,
|
||||
orientation = "horizontal",
|
||||
decorative = true,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
||||
return (
|
||||
<SeparatorPrimitive.Root
|
||||
data-slot="separator-root"
|
||||
decorative={decorative}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { Separator };
|
||||
5
examples/jazz-paper-scissors/src/constants.ts
Normal file
5
examples/jazz-paper-scissors/src/constants.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
if (!import.meta.env.VITE_JAZZ_WORKER_ACCOUNT) {
|
||||
throw new Error(".env missing, run `pnpm generate-env`");
|
||||
}
|
||||
|
||||
export const WORKER_ID = import.meta.env.VITE_JAZZ_WORKER_ACCOUNT;
|
||||
120
examples/jazz-paper-scissors/src/index.css
Normal file
120
examples/jazz-paper-scissors/src/index.css
Normal file
@@ -0,0 +1,120 @@
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
23
examples/jazz-paper-scissors/src/lib/utils.ts
Normal file
23
examples/jazz-paper-scissors/src/lib/utils.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a player selections, returns the winner of the current game.
|
||||
*/
|
||||
export function determineWinner(player1Choice: string, player2Choice: string) {
|
||||
if (player1Choice === player2Choice) {
|
||||
return "draw";
|
||||
} else if (
|
||||
(player1Choice === "rock" && player2Choice === "scissors") ||
|
||||
(player1Choice === "paper" && player2Choice === "rock") ||
|
||||
(player1Choice === "scissors" && player2Choice === "paper")
|
||||
) {
|
||||
return "player1";
|
||||
} else {
|
||||
return "player2";
|
||||
}
|
||||
}
|
||||
24
examples/jazz-paper-scissors/src/main.tsx
Normal file
24
examples/jazz-paper-scissors/src/main.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { JazzInspector } from "jazz-inspector";
|
||||
import { StrictMode } from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
|
||||
import "./index.css";
|
||||
import { JazzProvider } from "jazz-react";
|
||||
import { App } from "./app";
|
||||
|
||||
const rootElement = document.getElementById("app");
|
||||
if (rootElement && !rootElement.innerHTML) {
|
||||
const root = ReactDOM.createRoot(rootElement);
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<JazzProvider
|
||||
sync={{
|
||||
peer: "wss://cloud.jazz.tools/?key=jazz-paper-scissors@garden.co",
|
||||
}}
|
||||
>
|
||||
<JazzInspector />
|
||||
<App />
|
||||
</JazzProvider>
|
||||
</StrictMode>,
|
||||
);
|
||||
}
|
||||
177
examples/jazz-paper-scissors/src/routeTree.gen.ts
Normal file
177
examples/jazz-paper-scissors/src/routeTree.gen.ts
Normal file
@@ -0,0 +1,177 @@
|
||||
/* eslint-disable */
|
||||
|
||||
// @ts-nocheck
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
// This file was automatically generated by TanStack Router.
|
||||
// You should NOT make any changes in this file as it will be overwritten.
|
||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||
|
||||
// Import Routes
|
||||
|
||||
import { Route as rootRoute } from "./routes/__root";
|
||||
import { Route as AuthenticatedImport } from "./routes/_authenticated";
|
||||
import { Route as IndexImport } from "./routes/index";
|
||||
import { Route as AuthenticatedWaitingRoomWaitingRoomIdImport } from "./routes/_authenticated/waiting-room.$waitingRoomId";
|
||||
import { Route as AuthenticatedGameGameIdImport } from "./routes/_authenticated/game.$gameId";
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
const AuthenticatedRoute = AuthenticatedImport.update({
|
||||
id: "/_authenticated",
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any);
|
||||
|
||||
const IndexRoute = IndexImport.update({
|
||||
id: "/",
|
||||
path: "/",
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any);
|
||||
|
||||
const AuthenticatedWaitingRoomWaitingRoomIdRoute =
|
||||
AuthenticatedWaitingRoomWaitingRoomIdImport.update({
|
||||
id: "/waiting-room/$waitingRoomId",
|
||||
path: "/waiting-room/$waitingRoomId",
|
||||
getParentRoute: () => AuthenticatedRoute,
|
||||
} as any);
|
||||
|
||||
const AuthenticatedGameGameIdRoute = AuthenticatedGameGameIdImport.update({
|
||||
id: "/game/$gameId",
|
||||
path: "/game/$gameId",
|
||||
getParentRoute: () => AuthenticatedRoute,
|
||||
} as any);
|
||||
|
||||
// Populate the FileRoutesByPath interface
|
||||
|
||||
declare module "@tanstack/react-router" {
|
||||
interface FileRoutesByPath {
|
||||
"/": {
|
||||
id: "/";
|
||||
path: "/";
|
||||
fullPath: "/";
|
||||
preLoaderRoute: typeof IndexImport;
|
||||
parentRoute: typeof rootRoute;
|
||||
};
|
||||
"/_authenticated": {
|
||||
id: "/_authenticated";
|
||||
path: "";
|
||||
fullPath: "";
|
||||
preLoaderRoute: typeof AuthenticatedImport;
|
||||
parentRoute: typeof rootRoute;
|
||||
};
|
||||
"/_authenticated/game/$gameId": {
|
||||
id: "/_authenticated/game/$gameId";
|
||||
path: "/game/$gameId";
|
||||
fullPath: "/game/$gameId";
|
||||
preLoaderRoute: typeof AuthenticatedGameGameIdImport;
|
||||
parentRoute: typeof AuthenticatedImport;
|
||||
};
|
||||
"/_authenticated/waiting-room/$waitingRoomId": {
|
||||
id: "/_authenticated/waiting-room/$waitingRoomId";
|
||||
path: "/waiting-room/$waitingRoomId";
|
||||
fullPath: "/waiting-room/$waitingRoomId";
|
||||
preLoaderRoute: typeof AuthenticatedWaitingRoomWaitingRoomIdImport;
|
||||
parentRoute: typeof AuthenticatedImport;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export the route tree
|
||||
|
||||
interface AuthenticatedRouteChildren {
|
||||
AuthenticatedGameGameIdRoute: typeof AuthenticatedGameGameIdRoute;
|
||||
AuthenticatedWaitingRoomWaitingRoomIdRoute: typeof AuthenticatedWaitingRoomWaitingRoomIdRoute;
|
||||
}
|
||||
|
||||
const AuthenticatedRouteChildren: AuthenticatedRouteChildren = {
|
||||
AuthenticatedGameGameIdRoute: AuthenticatedGameGameIdRoute,
|
||||
AuthenticatedWaitingRoomWaitingRoomIdRoute:
|
||||
AuthenticatedWaitingRoomWaitingRoomIdRoute,
|
||||
};
|
||||
|
||||
const AuthenticatedRouteWithChildren = AuthenticatedRoute._addFileChildren(
|
||||
AuthenticatedRouteChildren,
|
||||
);
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
"/": typeof IndexRoute;
|
||||
"": typeof AuthenticatedRouteWithChildren;
|
||||
"/game/$gameId": typeof AuthenticatedGameGameIdRoute;
|
||||
"/waiting-room/$waitingRoomId": typeof AuthenticatedWaitingRoomWaitingRoomIdRoute;
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
"/": typeof IndexRoute;
|
||||
"": typeof AuthenticatedRouteWithChildren;
|
||||
"/game/$gameId": typeof AuthenticatedGameGameIdRoute;
|
||||
"/waiting-room/$waitingRoomId": typeof AuthenticatedWaitingRoomWaitingRoomIdRoute;
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRoute;
|
||||
"/": typeof IndexRoute;
|
||||
"/_authenticated": typeof AuthenticatedRouteWithChildren;
|
||||
"/_authenticated/game/$gameId": typeof AuthenticatedGameGameIdRoute;
|
||||
"/_authenticated/waiting-room/$waitingRoomId": typeof AuthenticatedWaitingRoomWaitingRoomIdRoute;
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath;
|
||||
fullPaths: "/" | "" | "/game/$gameId" | "/waiting-room/$waitingRoomId";
|
||||
fileRoutesByTo: FileRoutesByTo;
|
||||
to: "/" | "" | "/game/$gameId" | "/waiting-room/$waitingRoomId";
|
||||
id:
|
||||
| "__root__"
|
||||
| "/"
|
||||
| "/_authenticated"
|
||||
| "/_authenticated/game/$gameId"
|
||||
| "/_authenticated/waiting-room/$waitingRoomId";
|
||||
fileRoutesById: FileRoutesById;
|
||||
}
|
||||
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute;
|
||||
AuthenticatedRoute: typeof AuthenticatedRouteWithChildren;
|
||||
}
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
AuthenticatedRoute: AuthenticatedRouteWithChildren,
|
||||
};
|
||||
|
||||
export const routeTree = rootRoute
|
||||
._addFileChildren(rootRouteChildren)
|
||||
._addFileTypes<FileRouteTypes>();
|
||||
|
||||
/* ROUTE_MANIFEST_START
|
||||
{
|
||||
"routes": {
|
||||
"__root__": {
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/",
|
||||
"/_authenticated"
|
||||
]
|
||||
},
|
||||
"/": {
|
||||
"filePath": "index.tsx"
|
||||
},
|
||||
"/_authenticated": {
|
||||
"filePath": "_authenticated.tsx",
|
||||
"children": [
|
||||
"/_authenticated/game/$gameId",
|
||||
"/_authenticated/waiting-room/$waitingRoomId"
|
||||
]
|
||||
},
|
||||
"/_authenticated/game/$gameId": {
|
||||
"filePath": "_authenticated/game.$gameId.tsx",
|
||||
"parent": "/_authenticated"
|
||||
},
|
||||
"/_authenticated/waiting-room/$waitingRoomId": {
|
||||
"filePath": "_authenticated/waiting-room.$waitingRoomId.tsx",
|
||||
"parent": "/_authenticated"
|
||||
}
|
||||
}
|
||||
}
|
||||
ROUTE_MANIFEST_END */
|
||||
19
examples/jazz-paper-scissors/src/routes/__root.tsx
Normal file
19
examples/jazz-paper-scissors/src/routes/__root.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Outlet, createRootRouteWithContext } from "@tanstack/react-router";
|
||||
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
|
||||
import type { Account } from "jazz-tools";
|
||||
import { JazzAndAuth } from "../components/ui/jazz-and-auth";
|
||||
|
||||
interface RouterContext {
|
||||
me: Account;
|
||||
}
|
||||
|
||||
export const Route = createRootRouteWithContext<RouterContext>()({
|
||||
component: () => (
|
||||
<>
|
||||
<JazzAndAuth>
|
||||
<Outlet />
|
||||
<TanStackRouterDevtools />
|
||||
</JazzAndAuth>
|
||||
</>
|
||||
),
|
||||
});
|
||||
12
examples/jazz-paper-scissors/src/routes/_authenticated.tsx
Normal file
12
examples/jazz-paper-scissors/src/routes/_authenticated.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Outlet, createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/_authenticated")({
|
||||
component: RouteComponent,
|
||||
beforeLoad: ({ context }) => {
|
||||
return context;
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return <Outlet />;
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardSmall,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { WORKER_ID } from "@/constants";
|
||||
import { Game, NewGameIntent, PlayIntent } from "@/schema";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { experimental_useInboxSender, useCoState } from "jazz-react";
|
||||
import { type ID } from "jazz-tools";
|
||||
import { Badge, CircleHelp, Scissors, ScrollText } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const playIcon = (selection: string | undefined) => {
|
||||
switch (selection) {
|
||||
case "rock":
|
||||
return <Badge className="w-5 h-5" />;
|
||||
case "paper":
|
||||
return <ScrollText className="w-5 h-5" />;
|
||||
case "scissors":
|
||||
return <Scissors className="w-5 h-5" />;
|
||||
default:
|
||||
return <CircleHelp className="w-5 h-5" />;
|
||||
}
|
||||
};
|
||||
|
||||
export const Route = createFileRoute("/_authenticated/game/$gameId")({
|
||||
component: RouteComponent,
|
||||
loader: async ({ context: { me }, params: { gameId } }) => {
|
||||
const game = await Game.load(gameId as ID<Game>, {
|
||||
resolve: {
|
||||
player1: true,
|
||||
player2: true,
|
||||
},
|
||||
});
|
||||
if (!game) {
|
||||
throw redirect({ to: "/" });
|
||||
}
|
||||
|
||||
return { gameId, me, loaderGame: game };
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { gameId, me, loaderGame } = Route.useLoaderData();
|
||||
|
||||
const isPlayer1 = loaderGame.player1?.account?.isMe;
|
||||
const player = isPlayer1 ? "player1" : "player2";
|
||||
|
||||
const [playSelection, setPlaySelection] = useState(
|
||||
loaderGame[player]?.playSelection ?? "",
|
||||
);
|
||||
const sendInboxMessage = experimental_useInboxSender(WORKER_ID);
|
||||
|
||||
const game = useCoState(Game, gameId as ID<Game>);
|
||||
|
||||
useEffect(() => {
|
||||
let gameCompleted = Boolean(loaderGame.outcome);
|
||||
|
||||
return loaderGame.subscribe((game) => {
|
||||
if (gameCompleted && !game.outcome) {
|
||||
setPlaySelection(""); // Reset play selection when one player clicks on "Start a new game"
|
||||
}
|
||||
|
||||
gameCompleted = Boolean(game.outcome);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (!game) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gameComplete = game.outcome !== undefined;
|
||||
|
||||
const opponent = isPlayer1 ? "player2" : "player1";
|
||||
|
||||
const currentPlayer = game[player];
|
||||
const opponentPlayer = game[opponent];
|
||||
|
||||
const opponentSelection = opponentPlayer?.playSelection;
|
||||
|
||||
const onSubmit = async (playSelection: string) => {
|
||||
sendInboxMessage(
|
||||
PlayIntent.create({ type: "play", gameId, player, playSelection }),
|
||||
);
|
||||
};
|
||||
|
||||
const onNewGame = async () => {
|
||||
sendInboxMessage(NewGameIntent.create({ type: "newGame", gameId }));
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="mx-auto max-w-5xl">
|
||||
<div className="mx-auto text-center">
|
||||
<CardHeader>
|
||||
<CardTitle>Jazz, Paper, Scissors!</CardTitle>
|
||||
<span>Welcome {isPlayer1 ? "Player 1" : "Player 2"}</span>
|
||||
<span>
|
||||
{game?.player1Score ?? 0} - {game?.player2Score ?? 0}
|
||||
</span>
|
||||
</CardHeader>
|
||||
{gameComplete ? (
|
||||
<>
|
||||
<div className="border">
|
||||
Game Over,{" "}
|
||||
{game?.outcome === player
|
||||
? "You Win!"
|
||||
: game?.outcome === "draw"
|
||||
? "It's a Draw!"
|
||||
: "You Lose!"}
|
||||
</div>
|
||||
<Button onClick={onNewGame}>Start a new game</Button>
|
||||
</>
|
||||
) : null}
|
||||
<CardContent>
|
||||
<div>
|
||||
{playSelection === "" ? "Make Your Selection" : "Your Selection: "}
|
||||
</div>
|
||||
<CardSmall>{playIcon(playSelection)}</CardSmall>
|
||||
{gameComplete ? null : (
|
||||
<>
|
||||
<dl className="grid grid-cols-3 gap-x-8 gap-y-16 text-center">
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size={"icon"}
|
||||
onClick={() => setPlaySelection("rock")}
|
||||
>
|
||||
<Badge className="w-5 h-5" />
|
||||
</Button>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size={"icon"}
|
||||
onClick={() => setPlaySelection("paper")}
|
||||
>
|
||||
<ScrollText className="w-5 h-5" />
|
||||
</Button>
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size={"icon"}
|
||||
onClick={() => setPlaySelection("scissors")}
|
||||
>
|
||||
<Scissors className="w-5 h-5" />
|
||||
</Button>
|
||||
</dl>
|
||||
<div className="m-4">
|
||||
<Button
|
||||
disabled={
|
||||
playSelection === "" ||
|
||||
Boolean(currentPlayer?.playSelection)
|
||||
}
|
||||
onClick={() => onSubmit(playSelection)}
|
||||
>
|
||||
Go!
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div>Your Opponent Selected:</div>
|
||||
<CardSmall>{playIcon(opponentSelection)}</CardSmall>
|
||||
</CardContent>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { WORKER_ID } from "@/constants";
|
||||
import { JoinGameRequest, WaitingRoom } from "@/schema";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
import { Group, type ID, InboxSender } from "jazz-tools";
|
||||
import { ClipboardCopyIcon, Loader2Icon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticated/waiting-room/$waitingRoomId",
|
||||
)({
|
||||
component: RouteComponent,
|
||||
loader: async ({ context: { me }, params: { waitingRoomId } }) => {
|
||||
const waitingRoom = await WaitingRoom.load(
|
||||
waitingRoomId as ID<WaitingRoom>,
|
||||
{
|
||||
resolve: {
|
||||
game: true,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!waitingRoom) {
|
||||
throw redirect({ to: "/" });
|
||||
}
|
||||
if (!waitingRoom?.account1?.isMe) {
|
||||
const sender = await InboxSender.load<JoinGameRequest, WaitingRoom>(
|
||||
WORKER_ID,
|
||||
me,
|
||||
// { account1: {}, account2: {}, me, game: {} },
|
||||
);
|
||||
sender.sendMessage(
|
||||
JoinGameRequest.create(
|
||||
{ type: "joinGame", waitingRoom },
|
||||
{ owner: Group.create({ owner: me }) },
|
||||
),
|
||||
);
|
||||
// If the waiting room already has a game, redirect to the game
|
||||
if (waitingRoom?.game) {
|
||||
throw redirect({ to: `/game/${waitingRoom.game.id}` as string });
|
||||
}
|
||||
}
|
||||
|
||||
return { waitingRoom };
|
||||
},
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { waitingRoom } = Route.useLoaderData();
|
||||
const navigate = Route.useNavigate();
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!waitingRoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
return waitingRoom.subscribe(
|
||||
{
|
||||
resolve: {
|
||||
game: true,
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
if (waitingRoom.game) {
|
||||
navigate({ to: `/game/${waitingRoom.game.id}` });
|
||||
}
|
||||
},
|
||||
);
|
||||
}, [waitingRoom]);
|
||||
|
||||
const onCopyClick = () => {
|
||||
navigator.clipboard.writeText(window.location.toString());
|
||||
setCopied(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col w-full place-items-center justify-center p-2">
|
||||
<Card className="w-[500px]">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center">
|
||||
<Loader2Icon className="animate-spin inline h-8 w-8 mr-2" />
|
||||
Waiting for opponent to join the game
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Share this link with your friend to join the game. The game will
|
||||
automatically start once they join.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex">
|
||||
<Input
|
||||
className="w-full border bg-muted rounded-e-none"
|
||||
readOnly
|
||||
value={`${window.location}`}
|
||||
/>
|
||||
<Button onClick={onCopyClick} className="rounded-s-none w-25">
|
||||
{copied ? (
|
||||
"Copied!"
|
||||
) : (
|
||||
<>
|
||||
<ClipboardCopyIcon className="w-5 h-5" />
|
||||
Copy
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
54
examples/jazz-paper-scissors/src/routes/index.tsx
Normal file
54
examples/jazz-paper-scissors/src/routes/index.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { WORKER_ID } from "@/constants";
|
||||
import { CreateGameRequest } from "@/schema";
|
||||
import { createFileRoute, useNavigate } from "@tanstack/react-router";
|
||||
import { experimental_useInboxSender as useInboxSender } from "jazz-react";
|
||||
import { useState } from "react";
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: HomeComponent,
|
||||
});
|
||||
|
||||
function HomeComponent() {
|
||||
const createGame = useInboxSender(WORKER_ID);
|
||||
const navigate = useNavigate({ from: "/" });
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const onNewGameClick = async () => {
|
||||
setIsLoading(true);
|
||||
|
||||
const waitingRoomId = await createGame(
|
||||
CreateGameRequest.create({
|
||||
type: "createGame",
|
||||
}),
|
||||
);
|
||||
if (!waitingRoomId) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
navigate({ to: `/waiting-room/$waitingRoomId`, params: { waitingRoomId } });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-screen flex flex-col w-full place-items-center justify-center p-2">
|
||||
<Card className="w-[500px]">
|
||||
<CardHeader>
|
||||
<CardTitle>Welcome to Jazz, Paper, Scissors!</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<div className="flex items-center p-4">
|
||||
<Button
|
||||
onClick={onNewGameClick}
|
||||
loading={isLoading}
|
||||
loadingText="Creating game..."
|
||||
className="w-full"
|
||||
>
|
||||
New Game
|
||||
</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
65
examples/jazz-paper-scissors/src/schema.ts
Normal file
65
examples/jazz-paper-scissors/src/schema.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Account, CoMap, SchemaUnion, co } from "jazz-tools";
|
||||
|
||||
export class Game extends CoMap {
|
||||
player1 = co.ref(Player);
|
||||
player2? = co.ref(Player);
|
||||
outcome? = co.literal("player1", "player2", "draw");
|
||||
player1Score = co.number;
|
||||
player2Score = co.number;
|
||||
|
||||
/**
|
||||
* Given a player, returns the opponent in the current game.
|
||||
*/
|
||||
getOpponent(player: Player) {
|
||||
// TODO: player may be unrelated to this game
|
||||
const opponent =
|
||||
player.account?.id === this.player1?.account?.id
|
||||
? this.player2
|
||||
: this.player1;
|
||||
|
||||
if (!opponent) {
|
||||
throw new Error("Opponent not found");
|
||||
}
|
||||
|
||||
return opponent.ensureLoaded({
|
||||
// account: {},
|
||||
resolve: {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class Player extends CoMap {
|
||||
account = co.ref(Account);
|
||||
playSelection? = co.string;
|
||||
}
|
||||
|
||||
export class WaitingRoom extends CoMap {
|
||||
account1 = co.ref(Account);
|
||||
account2 = co.optional.ref(Account);
|
||||
game = co.optional.ref(Game);
|
||||
}
|
||||
|
||||
export class InboxMessage extends CoMap {
|
||||
type = co.literal("play", "createGame", "joinGame", "newGame");
|
||||
}
|
||||
|
||||
export class PlayIntent extends InboxMessage {
|
||||
type = co.literal("play");
|
||||
gameId = co.string;
|
||||
player = co.literal("player1", "player2");
|
||||
playSelection = co.string;
|
||||
}
|
||||
|
||||
export class NewGameIntent extends InboxMessage {
|
||||
type = co.literal("newGame");
|
||||
gameId = co.string;
|
||||
}
|
||||
|
||||
export class CreateGameRequest extends InboxMessage {
|
||||
type = co.literal("createGame");
|
||||
}
|
||||
|
||||
export class JoinGameRequest extends InboxMessage {
|
||||
type = co.literal("joinGame");
|
||||
waitingRoom = co.ref(WaitingRoom);
|
||||
}
|
||||
201
examples/jazz-paper-scissors/src/worker.ts
Normal file
201
examples/jazz-paper-scissors/src/worker.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
import {
|
||||
Game,
|
||||
InboxMessage,
|
||||
JoinGameRequest,
|
||||
NewGameIntent,
|
||||
PlayIntent,
|
||||
Player,
|
||||
WaitingRoom,
|
||||
} from "@/schema";
|
||||
import { startWorker } from "jazz-nodejs";
|
||||
import { Account, Group, type ID } from "jazz-tools";
|
||||
import { determineWinner } from "./lib/utils";
|
||||
|
||||
if (!process.env.VITE_JAZZ_WORKER_ACCOUNT || !process.env.JAZZ_WORKER_SECRET) {
|
||||
throw new Error(".env missing, run `pnpm generate-env`");
|
||||
}
|
||||
|
||||
const {
|
||||
worker,
|
||||
experimental: { inbox },
|
||||
} = await startWorker({
|
||||
accountID: process.env.VITE_JAZZ_WORKER_ACCOUNT,
|
||||
syncServer: "wss://cloud.jazz.tools/?key=jazz-paper-scissors@garden.co ",
|
||||
});
|
||||
|
||||
inbox.subscribe(
|
||||
InboxMessage,
|
||||
async (message, senderID) => {
|
||||
const playerAccount = await Account.load(senderID, { loadAs: worker });
|
||||
if (!playerAccount) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.type) {
|
||||
case "play":
|
||||
handlePlayIntent(senderID, message.castAs(PlayIntent));
|
||||
break;
|
||||
|
||||
case "newGame":
|
||||
handleNewGameIntent(senderID, message.castAs(NewGameIntent));
|
||||
break;
|
||||
|
||||
case "createGame":
|
||||
const waitingRoomGroup = Group.create({ owner: worker });
|
||||
waitingRoomGroup.addMember("everyone", "reader");
|
||||
const waitingRoom = WaitingRoom.create(
|
||||
{ account1: playerAccount },
|
||||
{ owner: waitingRoomGroup },
|
||||
);
|
||||
|
||||
console.log("waiting room created with id:", waitingRoom.id);
|
||||
return waitingRoom;
|
||||
|
||||
case "joinGame":
|
||||
const joinGameRequest = message.castAs(JoinGameRequest);
|
||||
if (
|
||||
!joinGameRequest.waitingRoom ||
|
||||
!joinGameRequest.waitingRoom.account1
|
||||
) {
|
||||
console.error("No waiting room in join game request");
|
||||
return;
|
||||
}
|
||||
joinGameRequest.waitingRoom.account2 = playerAccount;
|
||||
|
||||
const game = await createGame({
|
||||
account1: joinGameRequest.waitingRoom.account1,
|
||||
account2: joinGameRequest.waitingRoom.account2,
|
||||
});
|
||||
console.log("game created with id:", game.id);
|
||||
|
||||
joinGameRequest.waitingRoom.game = game;
|
||||
return joinGameRequest.waitingRoom.game;
|
||||
}
|
||||
},
|
||||
{ retries: 3 },
|
||||
);
|
||||
|
||||
console.log("worker", worker.id, "started");
|
||||
|
||||
interface CreateGameParams {
|
||||
account1: Account;
|
||||
account2: Account;
|
||||
}
|
||||
|
||||
async function createGame({ account1, account2 }: CreateGameParams) {
|
||||
const publicReadOnly = Group.create({ owner: worker });
|
||||
publicReadOnly.addMember(account1, "reader");
|
||||
publicReadOnly.addMember(account2, "reader");
|
||||
|
||||
const player1 = createPlayer({ account: account1 });
|
||||
const player2 = createPlayer({ account: account2 });
|
||||
|
||||
const game = Game.create(
|
||||
{
|
||||
player1: player1,
|
||||
player2: player2,
|
||||
player1Score: 0,
|
||||
player2Score: 0,
|
||||
},
|
||||
{ owner: publicReadOnly },
|
||||
);
|
||||
|
||||
await game.waitForSync();
|
||||
|
||||
return game;
|
||||
}
|
||||
|
||||
interface CreatePlayerParams {
|
||||
account: Account;
|
||||
}
|
||||
|
||||
function createPlayer({ account }: CreatePlayerParams) {
|
||||
const publicRead = Group.create({ owner: worker });
|
||||
publicRead.addMember("everyone", "reader");
|
||||
|
||||
const player = Player.create(
|
||||
{
|
||||
account,
|
||||
},
|
||||
{ owner: publicRead },
|
||||
);
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
async function handleNewGameIntent(_: ID<Account>, message: NewGameIntent) {
|
||||
const gameId = message.gameId;
|
||||
|
||||
const game = await Game.load(gameId as ID<Game>, {
|
||||
loadAs: worker,
|
||||
resolve: {
|
||||
player1: true,
|
||||
player2: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!game) {
|
||||
throw new Error("Game not found");
|
||||
}
|
||||
|
||||
if (game.outcome) {
|
||||
game.outcome = undefined;
|
||||
game.player1.playSelection = undefined;
|
||||
|
||||
if (game.player2) {
|
||||
game.player2.playSelection = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePlayIntent(_: ID<Account>, message: PlayIntent) {
|
||||
// determine current player, update game with outcome
|
||||
const gameId = message.gameId;
|
||||
if (!gameId) {
|
||||
console.error("Game not found");
|
||||
return;
|
||||
}
|
||||
|
||||
const game = await Game.load(gameId as ID<Game>, {
|
||||
loadAs: worker,
|
||||
resolve: {
|
||||
player1: true,
|
||||
player2: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!game) {
|
||||
throw new Error("Game not found");
|
||||
}
|
||||
|
||||
const currentPlayer = game[message.player as "player1" | "player2"];
|
||||
|
||||
if (!currentPlayer) {
|
||||
throw new Error("Player not found");
|
||||
}
|
||||
|
||||
if (currentPlayer.playSelection) {
|
||||
throw new Error("Player already made a selection");
|
||||
}
|
||||
|
||||
currentPlayer.playSelection = message.playSelection;
|
||||
|
||||
const player1Selection = game?.player1.playSelection;
|
||||
const player2Selection = game?.player2?.playSelection;
|
||||
|
||||
// once both players have a selection, determine the winner
|
||||
if (
|
||||
!!player1Selection &&
|
||||
player1Selection !== "" &&
|
||||
!!player2Selection &&
|
||||
player2Selection !== ""
|
||||
) {
|
||||
const outcome = determineWinner(player1Selection, player2Selection);
|
||||
game.outcome = outcome;
|
||||
if (outcome === "player1") {
|
||||
game.player1Score += 1;
|
||||
} else if (outcome === "player2") {
|
||||
game.player2Score += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
examples/jazz-paper-scissors/tsconfig.json
Normal file
28
examples/jazz-paper-scissors/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"include": ["**/*.ts", "**/*.tsx"],
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"jsx": "react-jsx",
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"types": ["vite/client"],
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
18
examples/jazz-paper-scissors/vite.config.ts
Normal file
18
examples/jazz-paper-scissors/vite.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { resolve } from "node:path";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
|
||||
import viteReact from "@vitejs/plugin-react";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
TanStackRouterVite({ autoCodeSplitting: true }),
|
||||
viteReact(),
|
||||
tailwindcss(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,20 @@
|
||||
# multi-cursors
|
||||
|
||||
## 0.0.71
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.70
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.69
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multi-cursors",
|
||||
"private": true,
|
||||
"version": "0.0.69",
|
||||
"version": "0.0.71",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# multiauth
|
||||
|
||||
## 0.0.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-react-auth-clerk@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
- jazz-react-auth-clerk@0.13.9
|
||||
|
||||
## 0.0.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "multiauth",
|
||||
"private": true,
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.19",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-example-musicplayer
|
||||
|
||||
## 0.0.100
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.10
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.99
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-inspector@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.98
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-music-player",
|
||||
"private": true,
|
||||
"version": "0.0.98",
|
||||
"version": "0.0.100",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# organization
|
||||
|
||||
## 0.0.71
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.70
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.69
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "organization",
|
||||
"private": true,
|
||||
"version": "0.0.69",
|
||||
"version": "0.0.71",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# passkey-svelte
|
||||
|
||||
## 0.0.65
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-svelte@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.64
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-svelte@0.13.9
|
||||
|
||||
## 0.0.63
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "passkey-svelte",
|
||||
"version": "0.0.63",
|
||||
"version": "0.0.65",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -32,6 +32,7 @@
|
||||
"vite": "6.0.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"jazz-svelte": "workspace:*"
|
||||
"jazz-svelte": "workspace:*",
|
||||
"jazz-tools": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# minimal-auth-passkey
|
||||
|
||||
## 0.0.76
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.75
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.74
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passkey",
|
||||
"private": true,
|
||||
"version": "0.0.74",
|
||||
"version": "0.0.76",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# passphrase
|
||||
|
||||
## 0.0.73
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.72
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.71
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "passphrase",
|
||||
"private": true,
|
||||
"version": "0.0.71",
|
||||
"version": "0.0.73",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-password-manager
|
||||
|
||||
## 0.0.97
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.96
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.95
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-password-manager",
|
||||
"private": true,
|
||||
"version": "0.0.95",
|
||||
"version": "0.0.97",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-example-pets
|
||||
|
||||
## 0.0.195
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.194
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.193
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-pets",
|
||||
"private": true,
|
||||
"version": "0.0.193",
|
||||
"version": "0.0.195",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# reactions
|
||||
|
||||
## 0.0.75
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.74
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.73
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "reactions",
|
||||
"private": true,
|
||||
"version": "0.0.73",
|
||||
"version": "0.0.75",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# todo-vue
|
||||
|
||||
## 0.0.79
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
- jazz-vue@0.13.10
|
||||
|
||||
## 0.0.78
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-browser@0.13.9
|
||||
- jazz-vue@0.13.9
|
||||
|
||||
## 0.0.77
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "todo-vue",
|
||||
"version": "0.0.77",
|
||||
"version": "0.0.79",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-example-todo
|
||||
|
||||
## 0.0.194
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.193
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.192
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jazz-example-todo",
|
||||
"private": true,
|
||||
"version": "0.0.192",
|
||||
"version": "0.0.194",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# version-history
|
||||
|
||||
## 0.0.73
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-inspector@0.13.10
|
||||
- jazz-react@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.0.72
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-inspector@0.13.9
|
||||
- jazz-react@0.13.9
|
||||
|
||||
## 0.0.71
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "version-history",
|
||||
"private": true,
|
||||
"version": "0.0.71",
|
||||
"version": "0.0.73",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# cojson-storage-indexeddb
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
- cojson-storage@0.13.10
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cojson-storage-indexeddb",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.10",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# cojson-storage-sqlite
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
- cojson-storage@0.13.10
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "cojson-storage-sqlite",
|
||||
"type": "module",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.10",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^11.7.0",
|
||||
"cojson": "workspace:0.13.7",
|
||||
"cojson": "workspace:0.13.10",
|
||||
"cojson-storage": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# cojson-storage
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cojson-storage",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.10",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# cojson-transport-nodejs-ws
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cojson-transport-ws",
|
||||
"type": "module",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.10",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# cojson
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f837cfe: Fix fatal errors happening when loading a CoValueCore without having the dependencies
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.10",
|
||||
"devDependencies": {
|
||||
"@opentelemetry/sdk-metrics": "^2.0.0",
|
||||
"typescript": "catalog:"
|
||||
|
||||
@@ -121,14 +121,35 @@ export class CoValueCore {
|
||||
this.header = header;
|
||||
this._sessionLogs = internalInitSessions;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
groupInvalidationSubscription?: () => void;
|
||||
|
||||
subscribeToGroupInvalidation() {
|
||||
if (this.groupInvalidationSubscription) {
|
||||
return;
|
||||
}
|
||||
|
||||
const header = this.header;
|
||||
|
||||
if (header.ruleset.type == "ownedByGroup") {
|
||||
this.node
|
||||
.expectCoValueLoaded(header.ruleset.group)
|
||||
.subscribe((_groupUpdate) => {
|
||||
this._cachedContent = undefined;
|
||||
this.notifyUpdate("immediate");
|
||||
const groupId = header.ruleset.group;
|
||||
const entry = this.node.coValuesStore.get(groupId);
|
||||
|
||||
if (entry.state.type === "available") {
|
||||
this.groupInvalidationSubscription = entry.state.coValue.subscribe(
|
||||
(_groupUpdate) => {
|
||||
this._cachedContent = undefined;
|
||||
this.notifyUpdate("immediate");
|
||||
},
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
logger.error("CoValueCore: Owner group not available", {
|
||||
id: this.id,
|
||||
groupId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,9 +389,15 @@ export class CoValueCore {
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(listener: (content?: RawCoValue) => void): () => void {
|
||||
subscribe(
|
||||
listener: (content?: RawCoValue) => void,
|
||||
immediateInvoke = true,
|
||||
): () => void {
|
||||
this.listeners.add(listener);
|
||||
listener(this.getCurrentContent());
|
||||
|
||||
if (immediateInvoke) {
|
||||
listener(this.getCurrentContent());
|
||||
}
|
||||
|
||||
return () => {
|
||||
this.listeners.delete(listener);
|
||||
@@ -474,6 +501,8 @@ export class CoValueCore {
|
||||
return this._cachedContent;
|
||||
}
|
||||
|
||||
this.subscribeToGroupInvalidation();
|
||||
|
||||
const newContent = coreToCoValue(this, options);
|
||||
|
||||
if (!options?.ignorePrivateTransactions) {
|
||||
|
||||
@@ -287,12 +287,30 @@ test("creating a coValue with a group should't trigger automatically a content c
|
||||
});
|
||||
|
||||
// It's called once for the group and never for the coValue
|
||||
expect(getCurrentContentSpy).toHaveBeenCalledTimes(1);
|
||||
expect(groupSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getCurrentContentSpy).toHaveBeenCalledTimes(0);
|
||||
expect(groupSpy).toHaveBeenCalledTimes(0);
|
||||
|
||||
getCurrentContentSpy.mockRestore();
|
||||
});
|
||||
|
||||
test("loading a coValue core without having the owner group available doesn't crash", () => {
|
||||
const [account, sessionID] = randomAnonymousAccountAndSessionID();
|
||||
const node = new LocalNode(account, sessionID, Crypto);
|
||||
|
||||
const otherNode = createTestNode();
|
||||
|
||||
const group = otherNode.createGroup();
|
||||
|
||||
const coValue = node.createCoValue({
|
||||
type: "costream",
|
||||
ruleset: { type: "ownedByGroup", group: group.id },
|
||||
meta: null,
|
||||
...Crypto.createdNowUnique(),
|
||||
});
|
||||
|
||||
expect(coValue.id).toBeDefined();
|
||||
});
|
||||
|
||||
test("listeners are notified even if the previous listener threw an error", async () => {
|
||||
const { node1, node2 } = await createTwoConnectedNodes("server", "server");
|
||||
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-auth-clerk
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
- jazz-browser@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.13.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-browser@0.13.9
|
||||
|
||||
## 0.13.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "jazz-auth-clerk",
|
||||
"version": "0.13.8",
|
||||
"version": "0.13.10",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cojson": "workspace:0.13.7",
|
||||
"jazz-browser": "workspace:0.13.7",
|
||||
"jazz-tools": "workspace:0.13.7"
|
||||
"cojson": "workspace:0.13.10",
|
||||
"jazz-browser": "workspace:0.13.10",
|
||||
"jazz-tools": "workspace:0.13.10"
|
||||
},
|
||||
"scripts": {
|
||||
"format-and-lint": "biome check .",
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# jazz-browser-media-images
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- jazz-browser@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.13.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-browser@0.13.9
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser-media-images",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.10",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@@ -8,8 +8,8 @@
|
||||
"dependencies": {
|
||||
"@types/image-blob-reduce": "^4.1.1",
|
||||
"image-blob-reduce": "^4.1.0",
|
||||
"jazz-browser": "workspace:0.13.7",
|
||||
"jazz-tools": "workspace:0.13.7",
|
||||
"jazz-browser": "workspace:0.13.10",
|
||||
"jazz-tools": "workspace:0.13.10",
|
||||
"pica": "^9.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
- cojson-storage-indexeddb@0.13.10
|
||||
- cojson-transport-ws@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.13.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
|
||||
## 0.13.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jazz-browser",
|
||||
"version": "0.13.7",
|
||||
"version": "0.13.10",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
# jazz-browser
|
||||
|
||||
## 0.13.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [f837cfe]
|
||||
- cojson@0.13.10
|
||||
- cojson-transport-ws@0.13.10
|
||||
- jazz-auth-clerk@0.13.10
|
||||
- jazz-react-core@0.13.10
|
||||
- jazz-react-native-core@0.13.10
|
||||
- jazz-tools@0.13.10
|
||||
|
||||
## 0.13.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [a6cf01f]
|
||||
- jazz-tools@0.13.9
|
||||
- jazz-auth-clerk@0.13.9
|
||||
- jazz-react-core@0.13.9
|
||||
- jazz-react-native-core@0.13.9
|
||||
|
||||
## 0.13.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user