Compare commits

..

3 Commits

Author SHA1 Message Date
Anselm Eickhoff
1baf60d660 Tighter slogan supported by kicker 2025-01-08 17:33:05 +00:00
Anselm
cad1b0ea43 Add connection between CoValues and local-first state 2025-01-08 16:02:42 +00:00
Anselm
473da86cca hermo improvements and start adding git comparison to narrative 2025-01-08 11:37:19 +00:00
984 changed files with 16752 additions and 78639 deletions

View File

@@ -9,15 +9,12 @@
"cojson-storage", "cojson-storage",
"cojson-storage-indexeddb", "cojson-storage-indexeddb",
"cojson-storage-sqlite", "cojson-storage-sqlite",
"cojson-storage-rn-sqlite",
"cojson-transport-ws", "cojson-transport-ws",
"jazz-browser", "jazz-browser",
"jazz-auth-clerk", "jazz-browser-auth-clerk",
"jazz-browser-media-images", "jazz-browser-media-images",
"jazz-inspector",
"jazz-nodejs", "jazz-nodejs",
"jazz-react", "jazz-react",
"jazz-react-core",
"jazz-react-auth-clerk", "jazz-react-auth-clerk",
"jazz-react-native", "jazz-react-native",
"jazz-react-native-auth-clerk", "jazz-react-native-auth-clerk",

View File

@@ -1,5 +0,0 @@
---
"multiauth": patch
---
Use the new Resolve API

View File

@@ -0,0 +1,7 @@
---
"jazz-react-native": patch
---
Fix username key hashing in DemoAuth
Improve error handling when loading an existing account fails
Fix the double context creation in Reacc development mode

View File

@@ -0,0 +1,5 @@
---
"cojson": patch
---
Add the assign method to RawCoMap to create bulk transactions and optimize RawCoMap init

View File

@@ -1,39 +0,0 @@
name: Setup Android Emulator
inputs:
api-level:
description: 'API level to use for the emulator'
required: true
default: '29'
runs:
using: "composite"
steps:
- name: Enable KVM
shell: bash
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Gradle cache
uses: gradle/actions/setup-gradle@v4
- name: AVD cache
uses: useblacksmith/cache@v5
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ inputs.api-level }}
- name: Create AVD and Generate Snapshot for Caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ inputs.api-level }}
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -no-metrics
disable-animations: false
script: echo "Generated AVD snapshot for caching."

View File

@@ -1,36 +0,0 @@
name: Get and Build Source Code
runs:
using: "composite"
steps:
- name: Enable latestcorepack
shell: bash
run: |
echo "Before: corepack version => $(corepack --version || echo 'not installed')"
npm install -g corepack@latest
echo "After : corepack version => $(corepack --version)"
corepack enable
pnpm --version
- name: Install Node.js
uses: useblacksmith/setup-node@v5
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: useblacksmith/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
shell: bash
run: pnpm install --frozen-lockfile

View File

@@ -6,7 +6,7 @@ on:
jobs: jobs:
build-examples: build-examples:
runs-on: blacksmith-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
example: [ example: [
@@ -19,16 +19,40 @@ jobs:
"pets", "pets",
"reactions", "reactions",
"todo", "todo",
"onboarding",
] ]
steps: steps:
- name: Checkout - uses: actions/checkout@v3
uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Setup Source Code - name: Enable corepack
uses: ./.github/actions/source-code/ run: corepack enable
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Pnpm Build - name: Pnpm Build
run: | run: |

View File

@@ -2,25 +2,51 @@ name: Build Starters
on: on:
push: push:
branches: ["main"] branches: [ "main" ]
jobs: jobs:
build-starters: build-starters:
runs-on: blacksmith-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
starter: ["react-passkey-auth"] starter: [
"react-demo-auth-tailwind",
]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- name: Setup Source Code - name: Enable corepack
uses: ./.github/actions/source-code/ run: corepack enable
- name: Pnpm Build - name: Install Node.js
run: | uses: actions/setup-node@v3
pnpm install with:
pnpm turbo build; node-version-file: '.node-version'
working-directory: ./starters/${{ matrix.starter }} cache: 'pnpm'
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Pnpm Build
run: |
pnpm install
pnpm turbo build;
working-directory: ./starters/${{ matrix.starter }}

View File

@@ -6,7 +6,7 @@ on:
jobs: jobs:
quality: quality:
runs-on: blacksmith-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@@ -1,85 +0,0 @@
name: End-to-End Tests for React Native
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- ".github/actions/android-emulator/**"
- ".github/actions/source-code/**"
- ".github/workflows/e2e-rn-test.yml"
- "examples/chat-rn/**"
- "examples/chat-rn-clerk/**"
- "packages/**"
jobs:
e2e-tests:
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Source Code
uses: ./.github/actions/source-code/
- name: Create Output Directory
run: |
mkdir -p ~/output
- name: Setup JDK
uses: actions/setup-java@v4
with:
distribution: corretto
java-version: 22
cache: gradle
- name: Pnpm Build
run: pnpm turbo build --filter="./packages/*"
- name: chat-rn App Pre Build
working-directory: ./examples/chat-rn
run: |
pnpm build
pnpm expo prebuild --clean
- name: Install Maestro
run: |
curl -fsSL "https://get.maestro.mobile.dev" | bash
- name: Setup Android Emulator
id: android-emulator
uses: ./.github/actions/android-emulator/
with:
api-level: 29
- name: Test App
uses: reactivecircus/android-emulator-runner@v2
id: e2e_test
continue-on-error: true
with:
api-level: 29
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -no-metrics
disable-animations: true
working-directory: ./examples/chat-rn/
script: ./test/e2e/run.sh
- name: Copy Maestro Output
if: steps.e2e_test.outcome != 'success'
run: |
cp -r ~/.maestro/tests/* ~/output
- name: Upload Output Files
if: steps.e2e_test.outcome != 'success'
uses: actions/upload-artifact@v4
with:
name: e2e-test-output
path: ~/output/*
retention-days: 5
- name: Exit with Test Result
if: always()
run: |
if [ "${{ steps.e2e_test.outcome }}" != "success" ]; then
exit 1
fi

View File

@@ -8,16 +8,38 @@ on:
jobs: jobs:
test: test:
runs-on: blacksmith-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
timeout-minutes: 5 timeout-minutes: 5
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- name: Setup Source Code - name: Enable corepack
uses: ./.github/actions/source-code/ run: corepack enable
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build jazz-run - name: Build jazz-run
run: pnpm exec turbo build && chmod +x dist/index.js; run: pnpm exec turbo build && chmod +x dist/index.js;
@@ -26,3 +48,4 @@ jobs:
- name: Run create account - name: Run create account
run: ./dist/index.js account create --name "Jazz Run CI test" run: ./dist/index.js account create --name "Jazz Run CI test"
working-directory: ./packages/jazz-run working-directory: ./packages/jazz-run

View File

@@ -9,19 +9,41 @@ on:
jobs: jobs:
test: test:
timeout-minutes: 60 timeout-minutes: 60
runs-on: blacksmith-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
continue-on-error: true continue-on-error: true
strategy: strategy:
matrix: matrix:
project: ["tests/e2e", "examples/chat", "examples/file-share-svelte", "examples/form", "examples/music-player", "examples/pets", "starters/react-passkey-auth"] project: ["tests/e2e", "examples/chat", "examples/file-share-svelte", "examples/form", "examples/music-player", "examples/pets", "examples/onboarding"]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- name: Setup Source Code - name: Enable corepack
uses: ./.github/actions/source-code/ run: corepack enable
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Pnpm Build - name: Pnpm Build
run: pnpm turbo build run: pnpm turbo build

View File

@@ -1,102 +0,0 @@
name: Pre-Publish tagged Pull Requests
on:
pull_request:
types: [opened, synchronize, reopened, labeled]
jobs:
pre-release:
if: contains(github.event.pull_request.labels.*.name, 'pre-release')
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Source Code
uses: ./.github/actions/source-code/
- name: Pnpm Build
run: pnpm turbo build --filter="./packages/*"
- name: Pre publish
run: pnpm exec pkg-pr-new publish --json output.json --comment=off "./packages/*"
- name: Post or update comment
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const output = JSON.parse(fs.readFileSync('output.json', 'utf8'));
const packages = output.packages
.map((p) => `- ${p.name}: ${p.url}`)
.join('\n');
const sha =
context.event_name === 'pull_request'
? context.payload.pull_request.head.sha
: context.payload.after;
const resolutions = Object.fromEntries(
output.packages.map((p) => [p.name, p.url])
);
const commitUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${sha}`;
const body = `## Jazz pre-release
### Packages:
\`\`\`json
${JSON.stringify(resolutions, null, 4)}
\`\`\`
[View Commit](${commitUrl})`;
async function logPublishInfo() {
console.log('\n' + '='.repeat(50));
console.log('Publish Information');
console.log('='.repeat(50));
console.log('\nPublished Packages:');
console.log(output.packages);
console.log('\nTemplates:');
console.log(templates);
console.log(`\nCommit URL: ${commitUrl}`);
console.log('\n' + '='.repeat(50));
}
if (context.eventName === 'pull_request') {
if (context.issue.number) {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body,
});
}
} else if (context.eventName === 'push') {
const pullRequests = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${context.repo.owner}:${context.ref.replace(
'refs/heads/',
''
)}`,
});
if (pullRequests.data.length > 0) {
await github.rest.issues.createComment({
issue_number: pullRequests.data[0].number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body,
});
} else {
console.log(
'No open pull request found for this push. Logging publish information to console:'
);
await logPublishInfo();
}
}

View File

@@ -17,16 +17,35 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs: jobs:
release: release:
name: Release name: Release
runs-on: blacksmith-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Setup Source Code - name: Enable corepack
uses: ./.github/actions/source-code/ run: corepack enable
- name: Build packages - name: Install Node.js
run: pnpm exec turbo run build --filter='./packages/*' uses: actions/setup-node@v3
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish to npm - name: Create Release Pull Request or Publish to npm
id: changesets id: changesets

View File

@@ -9,20 +9,39 @@ on:
jobs: jobs:
unit-tests: unit-tests:
runs-on: blacksmith-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Source Code - name: Enable corepack
uses: ./.github/actions/source-code/ run: corepack enable
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Pnpm Build - name: Pnpm Build
run: pnpm turbo build --filter="./packages/*" run: pnpm turbo build --filter="./packages/*"
- name: Install Playwright Browsers
run: pnpm exec playwright install
- name: Unit Tests - name: Unit Tests
run: pnpm test:ci run: pnpm test:ci

6
.gitignore vendored
View File

@@ -7,15 +7,11 @@ docsTmp
coverage coverage
.direnv .direnv
# Typescript
**/*.tsbuildinfo
# Next.js # Next.js
**/.next **/.next
# Vite output # Vite output
**/dist **/dist
__screenshots__
# Playwright # Playwright
test-results test-results
@@ -23,5 +19,3 @@ test-results
.husky .husky
.vscode/settings.json .vscode/settings.json
.svelte-kit

8
.idea/.gitignore generated vendored
View File

@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

8
.idea/jazz.iml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/jazz.iml" filepath="$PROJECT_DIR$/.idea/jazz.iml" />
</modules>
</component>
</project>

19
.idea/php.xml generated
View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

6
.idea/prettier.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myConfigurationMode" value="AUTOMATIC" />
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -36,7 +36,7 @@ We welcome all ideas! If you have suggestions, feel free to open an issue marked
### 5. Local Setup ### 5. Local Setup
You'll need Node.js 22.x installed (we're working on support for 23.x), and pnpm 9.x installed. If you're using nix, run `nix develop` to get a shell with the correct versions of everything installed. You'll need Node.js 20.x or 22.x installed (we're working on support for 23.x), and pnpm 9.x installed. If you're using nix, run `nix develop` to get a shell with the correct versions of everything installed.
1. **Clone the repository**: 1. **Clone the repository**:
```bash ```bash
@@ -48,25 +48,7 @@ You'll need Node.js 22.x installed (we're working on support for 23.x), and pnpm
pnpm install pnpm install
``` ```
3. **Install homepage dependencies**: 3. **Run tests** to verify everything is working:
```bash
cd homepage && pnpm install
```
4. **Go back to the project root**:
```bash
cd ..
```
4. **Build the packages**:
```bash
pnpm build
```
5. **Run tests** to verify everything is working:
```bash ```bash
pnpm test pnpm test
``` ```

View File

@@ -1,4 +1,4 @@
Copyright 2025, Garden Computing, Inc. Copyright 2024, Garden Computing, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

View File

@@ -17,4 +17,4 @@ For community and support, please join our [Discord](https://discord.gg/utDMjHYg
- Community & support: [Discord](https://discord.gg/utDMjHYg42) - Community & support: [Discord](https://discord.gg/utDMjHYg42)
- Updates: [X](https://x.com/jazz_tools) & [Email](https://garden.co/news) - Updates: [X](https://x.com/jazz_tools) & [Email](https://garden.co/news)
Copyright 2025 &mdash; Garden Computing, Inc. Copyright 2024 &mdash; Garden Computing, Inc.

View File

@@ -12,9 +12,7 @@
"**/ios/**", "**/ios/**",
"**/android/**", "**/android/**",
"packages/jazz-svelte/**", "packages/jazz-svelte/**",
"examples/*svelte*/**", "examples/*svelte*/**"
"homepage/homepage/**",
"**/package.json"
] ]
}, },
"formatter": { "formatter": {
@@ -54,24 +52,21 @@
} }
}, },
{ {
"include": ["packages/cojson-storage*/**", "cojson-transport-ws/**"], "include": ["packages/**/src/tests/**", "packages/**/src/test/**"],
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
}
},
{
"include": ["packages/**/src/tests/**"],
"linter": { "linter": {
"rules": { "rules": {
"correctness": { "correctness": {
"useImportExtensions": "off" "useImportExtensions": "off"
}, }
"style": { }
"noNonNullAssertion": "off" }
}, },
{
"include": ["packages/cojson-storage-indexeddb/**"],
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": { "suspicious": {
"noExplicitAny": "info" "noExplicitAny": "info"
} }

View File

@@ -1,490 +1,5 @@
# chat-rn-clerk # chat-rn-clerk
## 1.0.91
### Patch Changes
- jazz-react-native@0.12.1
- jazz-react-native-auth-clerk@0.12.1
- jazz-tools@0.12.1
- jazz-react-native-media-images@0.12.1
## 1.0.90
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- jazz-tools@0.12.0
- jazz-react-native@0.12.0
- jazz-react-native-auth-clerk@0.12.0
- jazz-react-native-media-images@0.12.0
## 1.0.89
### Patch Changes
- jazz-react-native@0.11.8
- jazz-react-native-auth-clerk@0.11.8
- jazz-tools@0.11.8
- jazz-react-native-media-images@0.11.8
## 1.0.88
### Patch Changes
- Updated dependencies [a140f55]
- Updated dependencies [2b0d1b0]
- jazz-tools@0.11.7
- jazz-react-native@0.11.7
- jazz-react-native-auth-clerk@0.11.7
- jazz-react-native-media-images@0.11.7
## 1.0.87
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react-native@0.11.6
- jazz-tools@0.11.6
- jazz-react-native-auth-clerk@0.11.6
- jazz-react-native-media-images@0.11.6
## 1.0.86
### Patch Changes
- jazz-react-native@0.11.5
- jazz-react-native-auth-clerk@0.11.5
- jazz-tools@0.11.5
- jazz-react-native-media-images@0.11.5
## 1.0.85
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react-native@0.11.4
- jazz-react-native-auth-clerk@0.11.4
- jazz-react-native-media-images@0.11.4
## 1.0.84
### Patch Changes
- jazz-react-native@0.11.3
- jazz-react-native-auth-clerk@0.11.3
- jazz-tools@0.11.3
- jazz-react-native-media-images@0.11.3
## 1.0.83
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react-native@0.11.2
- jazz-react-native-auth-clerk@0.11.2
- jazz-react-native-media-images@0.11.2
## 1.0.82
### Patch Changes
- jazz-react-native@0.11.1
- jazz-react-native-auth-clerk@0.11.1
## 1.0.81
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react-native-media-images@0.11.0
- jazz-react-native-auth-clerk@0.11.0
- jazz-react-native@0.11.0
## 1.0.80
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react-native@0.10.15
- jazz-react-native-auth-clerk@0.10.15
- jazz-react-native-media-images@0.10.15
## 1.0.79
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react-native@0.10.14
- jazz-react-native-auth-clerk@0.10.14
- jazz-react-native-media-images@0.10.14
## 1.0.78
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-react-native@0.10.13
- jazz-react-native-auth-clerk@0.10.13
- jazz-react-native-media-images@0.10.13
## 1.0.77
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-react-native@0.10.12
- jazz-react-native-auth-clerk@0.10.12
- jazz-react-native-media-images@0.10.12
## 1.0.76
### Patch Changes
- Updated dependencies [5a54e4a]
- jazz-react-native@0.10.11
- jazz-react-native-auth-clerk@0.10.11
## 1.0.75
### Patch Changes
- Updated dependencies [3405d8f]
- jazz-react-native@0.10.10
- jazz-react-native-auth-clerk@0.10.10
## 1.0.74
### Patch Changes
- jazz-react-native-auth-clerk@0.10.9
## 1.0.73
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-react-native@0.10.8
- jazz-react-native-auth-clerk@0.10.8
- jazz-react-native-media-images@0.10.8
## 1.0.72
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-react-native@0.10.7
- jazz-tools@0.10.7
- jazz-react-native-auth-clerk@0.10.7
- jazz-react-native-media-images@0.10.7
## 1.0.71
### Patch Changes
- Updated dependencies [ada802b]
- jazz-tools@0.10.6
- jazz-react-native@0.10.6
- jazz-react-native-auth-clerk@0.10.6
- jazz-react-native-media-images@0.10.6
## 1.0.70
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-react-native@0.10.5
- jazz-react-native-auth-clerk@0.10.5
- jazz-react-native-media-images@0.10.5
## 1.0.69
### Patch Changes
- jazz-react-native@0.10.4
- jazz-react-native-auth-clerk@0.10.4
- jazz-tools@0.10.4
- jazz-react-native-media-images@0.10.4
## 1.0.68
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-react-native@0.10.3
- jazz-react-native-auth-clerk@0.10.3
- jazz-react-native-media-images@0.10.3
## 1.0.67
### Patch Changes
- jazz-react-native@0.10.2
- jazz-react-native-auth-clerk@0.10.2
- jazz-tools@0.10.2
- jazz-react-native-media-images@0.10.2
## 1.0.66
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-react-native@0.10.1
- jazz-react-native-auth-clerk@0.10.1
- jazz-react-native-media-images@0.10.1
## 1.0.65
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-react-native-auth-clerk@0.10.0
- jazz-react-native@0.10.0
- jazz-tools@0.10.0
- jazz-react-native-media-images@0.10.0
## 1.0.64
### Patch Changes
- jazz-react-native@0.9.23
- jazz-react-native-auth-clerk@0.9.23
- jazz-tools@0.9.23
- jazz-react-native-media-images@0.9.23
## 1.0.63
### Patch Changes
- jazz-react-native@0.9.22
- jazz-react-native-auth-clerk@0.9.22
## 1.0.62
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-react-native@0.9.21
- jazz-react-native-auth-clerk@0.9.21
- jazz-react-native-media-images@0.9.21
## 1.0.61
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-react-native@0.9.20
- jazz-react-native-auth-clerk@0.9.20
- jazz-react-native-media-images@0.9.20
## 1.0.60
### Patch Changes
- jazz-react-native@0.9.19
- jazz-react-native-auth-clerk@0.9.19
- jazz-tools@0.9.19
- jazz-react-native-media-images@0.9.19
## 1.0.59
### Patch Changes
- jazz-react-native@0.9.18
- jazz-react-native-auth-clerk@0.9.18
- jazz-tools@0.9.18
- jazz-react-native-media-images@0.9.18
## 1.0.58
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-react-native@0.9.17
- jazz-react-native-auth-clerk@0.9.17
- jazz-react-native-media-images@0.9.17
## 1.0.57
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-react-native-auth-clerk@0.9.16
- jazz-tools@0.9.16
- jazz-react-native@0.9.16
- jazz-react-native-media-images@0.9.16
## 1.0.56
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-react-native@0.9.15
- jazz-react-native-auth-clerk@0.9.15
- jazz-react-native-media-images@0.9.15
## 1.0.55
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-react-native@0.9.14
- jazz-react-native-auth-clerk@0.9.14
- jazz-react-native-media-images@0.9.14
## 1.0.54
### Patch Changes
- jazz-react-native@0.9.13
- jazz-react-native-auth-clerk@0.9.13
- jazz-tools@0.9.13
- jazz-react-native-media-images@0.9.13
## 1.0.53
### Patch Changes
- jazz-react-native@0.9.12
- jazz-react-native-auth-clerk@0.9.12
- jazz-tools@0.9.12
- jazz-react-native-media-images@0.9.12
## 1.0.52
### Patch Changes
- jazz-react-native@0.9.11
- jazz-react-native-auth-clerk@0.9.11
- jazz-tools@0.9.11
- jazz-react-native-media-images@0.9.11
## 1.0.51
### Patch Changes
- f76274c: Fix image handling in react-native
- Updated dependencies [f76274c]
- Updated dependencies [5e83864]
- jazz-react-native@0.9.10
- jazz-tools@0.9.10
- jazz-react-native-auth-clerk@0.9.10
- jazz-react-native-media-images@0.9.10
## 1.0.50
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-react-native@0.9.9
- jazz-react-native-auth-clerk@0.9.9
- jazz-react-native-media-images@0.9.9
## 1.0.49
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react-native@0.9.8
- jazz-react-native-auth-clerk@0.9.8
- jazz-react-native-media-images@0.9.8
## 1.0.48
### Patch Changes
- Updated dependencies [8a390d2]
- jazz-react-native@0.9.6
- jazz-react-native-auth-clerk@0.9.6
## 1.0.47
### Patch Changes
- Updated dependencies [c871912]
- jazz-react-native@0.9.5
- jazz-react-native-auth-clerk@0.9.5
## 1.0.46
### Patch Changes
- jazz-react-native@0.9.4
- jazz-react-native-auth-clerk@0.9.4
## 1.0.45
### Patch Changes
- Updated dependencies [7cd691f]
- jazz-react-native@0.9.3
- jazz-react-native-auth-clerk@0.9.3
## 1.0.44
### Patch Changes
- Updated dependencies [80fd3e9]
- jazz-react-native@0.9.2
- jazz-react-native-auth-clerk@0.9.2
## 1.0.43
### Patch Changes
- Updated dependencies [1b71969]
- jazz-tools@0.9.1
- jazz-react-native@0.9.1
- jazz-react-native-auth-clerk@0.9.1
- jazz-react-native-media-images@0.9.1
## 1.0.42
### Patch Changes
- Updated dependencies [1da4d55]
- Updated dependencies [8eda792]
- Updated dependencies [1e5e3a1]
- jazz-react-native@0.9.0
- jazz-tools@0.9.0
- jazz-react-native-auth-clerk@0.9.0
- jazz-react-native-media-images@0.9.0
## 1.0.41 ## 1.0.41
### Patch Changes ### Patch Changes

View File

@@ -37,13 +37,7 @@
], ],
"expo-secure-store", "expo-secure-store",
"expo-font", "expo-font",
"expo-router", "expo-router"
[
"expo-image-picker",
{
"photosPermission": "The app accesses your photos to let you share them with your friends."
}
]
], ],
"extra": { "extra": {
"eas": { "eas": {

View File

@@ -1,9 +1,9 @@
import { Redirect, Stack } from "expo-router"; import { Redirect, Stack } from "expo-router";
import { useIsAuthenticated } from "jazz-react-native";
import React from "react"; import React from "react";
import { useAuth } from "../../src/auth-context";
export default function HomeLayout() { export default function HomeLayout() {
const isAuthenticated = useIsAuthenticated(); const { isAuthenticated } = useAuth();
if (isAuthenticated) { if (isAuthenticated) {
return <Redirect href={"/chat"} />; return <Redirect href={"/chat"} />;

View File

@@ -1,8 +1,8 @@
import { Redirect, Stack } from "expo-router"; import { Redirect, Stack } from "expo-router";
import { useIsAuthenticated } from "jazz-react-native"; import { useAuth } from "../../src/auth-context";
export default function UnAuthenticatedLayout() { export default function UnAuthenticatedLayout() {
const isAuthenticated = useIsAuthenticated(); const { isAuthenticated } = useAuth();
if (isAuthenticated) { if (isAuthenticated) {
return <Redirect href={"/chat"} />; return <Redirect href={"/chat"} />;

View File

@@ -1,6 +1,5 @@
import "../global.css"; import "../global.css";
import { ClerkLoaded, ClerkProvider } from "@clerk/clerk-expo"; import { ClerkLoaded, ClerkProvider } from "@clerk/clerk-expo";
import { secureStore } from "@clerk/clerk-expo/secure-store";
import { useFonts } from "expo-font"; import { useFonts } from "expo-font";
import { Slot } from "expo-router"; import { Slot } from "expo-router";
import * as SplashScreen from "expo-splash-screen"; import * as SplashScreen from "expo-splash-screen";
@@ -34,11 +33,7 @@ export default function RootLayout() {
} }
return ( return (
<ClerkProvider <ClerkProvider tokenCache={tokenCache} publishableKey={publishableKey}>
tokenCache={tokenCache}
publishableKey={publishableKey}
__experimental_resourceCache={secureStore}
>
<ClerkLoaded> <ClerkLoaded>
<JazzAndAuth> <JazzAndAuth>
<Slot /> <Slot />

View File

@@ -1,12 +1,9 @@
import { useAccount, useCoState } from "@/src/jazz";
import { Chat, Message } from "@/src/schema"; import { Chat, Message } from "@/src/schema";
import { useNavigation } from "@react-navigation/native"; import { useFocusEffect, useNavigation } from "@react-navigation/native";
import clsx from "clsx"; import clsx from "clsx";
import * as Clipboard from "expo-clipboard"; import * as Clipboard from "expo-clipboard";
import * as ImagePicker from "expo-image-picker";
import { useLocalSearchParams } from "expo-router"; import { useLocalSearchParams } from "expo-router";
import { useAccount, useCoState } from "jazz-react-native";
import { ProgressiveImg } from "jazz-react-native";
import { createImage } from "jazz-react-native-media-images";
import { Group, ID } from "jazz-tools"; import { Group, ID } from "jazz-tools";
import { useEffect, useLayoutEffect, useState } from "react"; import { useEffect, useLayoutEffect, useState } from "react";
import React, { import React, {
@@ -19,8 +16,6 @@ import React, {
KeyboardAvoidingView, KeyboardAvoidingView,
TextInput, TextInput,
Button, Button,
Image,
ActivityIndicator,
} from "react-native"; } from "react-native";
export default function Conversation() { export default function Conversation() {
@@ -28,9 +23,8 @@ export default function Conversation() {
const { me } = useAccount(); const { me } = useAccount();
const [chat, setChat] = useState<Chat>(); const [chat, setChat] = useState<Chat>();
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
const loadedChat = useCoState(Chat, chat?.id, { resolve: { $each: true } }); const loadedChat = useCoState(Chat, chat?.id, [{}]);
const navigation = useNavigation(); const navigation = useNavigation();
const [isUploading, setIsUploading] = useState(false);
useEffect(() => { useEffect(() => {
if (chat) return; if (chat) return;
@@ -71,7 +65,7 @@ export default function Conversation() {
const loadChat = async (chatId: ID<Chat>) => { const loadChat = async (chatId: ID<Chat>) => {
try { try {
const chat = await Chat.load(chatId, me); const chat = await Chat.load(chatId, me, []);
setChat(chat); setChat(chat);
} catch (error) { } catch (error) {
console.log("Error loading chat", error); console.log("Error loading chat", error);
@@ -87,32 +81,6 @@ export default function Conversation() {
} }
}; };
const handleImageUpload = async () => {
try {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
base64: true,
quality: 0.7,
});
if (!result.canceled && result.assets[0].base64 && chat) {
setIsUploading(true);
const base64Uri = `data:image/jpeg;base64,${result.assets[0].base64}`;
const image = await createImage(base64Uri, {
owner: chat._owner,
maxSize: 2048,
});
chat.push(Message.create({ text: "", image }, { owner: chat._owner }));
}
} catch (error) {
Alert.alert("Error", "Failed to upload image");
} finally {
setIsUploading(false);
}
};
const renderMessageItem = ({ item }: { item: Message }) => { const renderMessageItem = ({ item }: { item: Message }) => {
const isMe = item._edits.text.by?.isMe; const isMe = item._edits.text.by?.isMe;
return ( return (
@@ -138,27 +106,14 @@ export default function Conversation() {
isMe ? "flex-row" : "flex-row", isMe ? "flex-row" : "flex-row",
)} )}
> >
{item.image && ( <Text
<ProgressiveImg image={item.image} maxWidth={1024}> className={clsx(
{({ src, res, originalSize }) => ( !isMe ? "text-black" : "text-gray-200",
<Image `text-md max-w-[85%]`,
source={{ uri: src }} )}
className="w-48 h-48 rounded-lg mb-2" >
resizeMode="cover" {item.text}
/> </Text>
)}
</ProgressiveImg>
)}
{item.text && (
<Text
className={clsx(
!isMe ? "text-black" : "text-gray-200",
`text-md max-w-[85%]`,
)}
>
{item.text}
</Text>
)}
<Text <Text
className={clsx( className={clsx(
"text-[10px] text-right ml-2", "text-[10px] text-right ml-2",
@@ -192,17 +147,6 @@ export default function Conversation() {
className="p-3 bg-white border-t border-gray-300" className="p-3 bg-white border-t border-gray-300"
> >
<SafeAreaView className="flex-row items-center gap-2"> <SafeAreaView className="flex-row items-center gap-2">
<TouchableOpacity
onPress={handleImageUpload}
disabled={isUploading}
className="h-10 w-10 items-center justify-center"
>
{isUploading ? (
<ActivityIndicator size="small" color="#0000ff" />
) : (
<Text className="text-2xl">🖼</Text>
)}
</TouchableOpacity>
<TextInput <TextInput
className="flex-1 rounded-full h-10 px-4 bg-gray-100 border border-gray-300 focus:border-blue-500 focus:bg-white" className="flex-1 rounded-full h-10 px-4 bg-gray-100 border border-gray-300 focus:border-blue-500 focus:bg-white"
value={message} value={message}

View File

@@ -11,7 +11,7 @@ import React, {
} from "react-native"; } from "react-native";
import { useUser } from "@clerk/clerk-expo"; import { useUser } from "@clerk/clerk-expo";
import { useAccount } from "jazz-react-native"; import { useAccount } from "../../src/jazz";
import { Chat } from "../../src/schema"; import { Chat } from "../../src/schema";
export default function ChatScreen() { export default function ChatScreen() {
@@ -20,15 +20,10 @@ export default function ChatScreen() {
const navigation = useNavigation(); const navigation = useNavigation();
const { user } = useUser(); const { user } = useUser();
function handleLogOut() {
logOut();
router.navigate("/");
}
useLayoutEffect(() => { useLayoutEffect(() => {
navigation.setOptions({ navigation.setOptions({
headerTitle: "Chat", headerTitle: "Chat",
headerRight: () => <Button onPress={handleLogOut} title="Logout" />, headerRight: () => <Button onPress={logOut} title="Logout" />,
}); });
}, [navigation]); }, [navigation]);

View File

@@ -19,6 +19,7 @@ config.resolver.nodeModulesPaths = [
path.resolve(workspaceRoot, "node_modules"), path.resolve(workspaceRoot, "node_modules"),
]; ];
config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"]; config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"];
config.resolver.unstable_enablePackageExports = true;
config.resolver.requireCycleIgnorePatterns = [ config.resolver.requireCycleIgnorePatterns = [
/(^|\/|\\)node_modules($|\/|\\)/, /(^|\/|\\)node_modules($|\/|\\)/,
/(^|\/|\\)packages($|\/|\\)/, /(^|\/|\\)packages($|\/|\\)/,

View File

@@ -1,7 +1,7 @@
{ {
"name": "chat-rn-clerk", "name": "chat-rn-clerk",
"main": "index.js", "main": "index.js",
"version": "1.0.91", "version": "1.0.41",
"scripts": { "scripts": {
"build": "expo export -p ios", "build": "expo export -p ios",
"start": "expo start", "start": "expo start",
@@ -9,22 +9,22 @@
"format-and-lint:fix": "biome check . --write", "format-and-lint:fix": "biome check . --write",
"android": "expo run:android", "android": "expo run:android",
"ios": "expo run:ios", "ios": "expo run:ios",
"web": "expo start --web" "web": "expo start --web",
"test": "jest --watchAll"
}, },
"jest": { "jest": {
"preset": "jest-expo" "preset": "jest-expo"
}, },
"dependencies": { "dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2", "@azure/core-asynciterator-polyfill": "^1.0.2",
"@bacons/text-decoder": "0.0.0",
"@bam.tech/react-native-image-resizer": "^3.0.11", "@bam.tech/react-native-image-resizer": "^3.0.11",
"@craftzdog/react-native-buffer": "6.0.5",
"@clerk/clerk-expo": "^2.2.21", "@clerk/clerk-expo": "^2.2.21",
"@expo/vector-icons": "^14.0.2", "@expo/vector-icons": "^14.0.2",
"@op-engineering/op-sqlite": "^11.2.12",
"@react-native-community/netinfo": "^11.4.1", "@react-native-community/netinfo": "^11.4.1",
"@react-navigation/native": "^7.0.13", "@react-navigation/native": "^7.0.13",
"@react-navigation/native-stack": "^7.1.14", "@react-navigation/native-stack": "^7.1.14",
"base-64": "^1.0.0",
"buffer": "^6.0.3",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"expo": "^52.0.0", "expo": "^52.0.0",
"expo-build-properties": "~0.13.1", "expo-build-properties": "~0.13.1",
@@ -34,7 +34,6 @@
"expo-dev-client": "~5.0.5", "expo-dev-client": "~5.0.5",
"expo-file-system": "^18.0.4", "expo-file-system": "^18.0.4",
"expo-font": "~13.0.1", "expo-font": "~13.0.1",
"expo-image-picker": "~16.0.4",
"expo-linking": "~7.0.3", "expo-linking": "~7.0.3",
"expo-router": "~4.0.11", "expo-router": "~4.0.11",
"expo-secure-store": "~14.0.0", "expo-secure-store": "~14.0.0",
@@ -50,14 +49,18 @@
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-native": "~0.76.3", "react-native": "~0.76.3",
"react-native-fetch-api": "^3.0.0",
"react-native-gesture-handler": "~2.20.2", "react-native-gesture-handler": "~2.20.2",
"react-native-get-random-values": "^1.11.0", "react-native-get-random-values": "^1.11.0",
"react-native-polyfill-globals": "^3.1.0",
"react-native-quick-base64": "^2.1.2",
"react-native-reanimated": "~3.16.3", "react-native-reanimated": "~3.16.3",
"react-native-safe-area-context": "4.12.0", "react-native-safe-area-context": "4.12.0",
"react-native-screens": "4.1.0", "react-native-screens": "4.1.0",
"react-native-url-polyfill": "^2.0.0", "react-native-url-polyfill": "^2.0.0",
"react-native-web": "~0.19.13", "react-native-web": "~0.19.13",
"readable-stream": "4.7.0" "text-encoding": "^0.7.0",
"web-streams-polyfill": "^3.2.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.0", "@babel/core": "^7.20.0",
@@ -67,7 +70,7 @@
"jest": "^29.2.1", "jest": "^29.2.1",
"jest-expo": "~52.0.2", "jest-expo": "~52.0.2",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.15",
"typescript": "~5.6.2" "typescript": "~5.6.2"
}, },
"private": true "private": true

View File

@@ -1,17 +1,8 @@
/* eslint-disable import/order */ import "react-native-polyfill-globals/auto";
// @ts-expect-error - @types/react-native doesn't cover this file
import { polyfillGlobal } from "react-native/Libraries/Utilities/PolyfillFunctions";
import { Buffer } from "@craftzdog/react-native-buffer";
polyfillGlobal("Buffer", () => Buffer);
// @ts-expect-error - @types/readable-stream doesn't have ReadableStream type
import { ReadableStream } from "readable-stream";
polyfillGlobal("ReadableStream", () => ReadableStream);
import "@azure/core-asynciterator-polyfill"; import "@azure/core-asynciterator-polyfill";
import { Buffer } from "buffer";
import { polyfillGlobal } from "react-native/Libraries/Utilities/PolyfillFunctions";
import { ReadableStream } from "web-streams-polyfill/ponyfill/es6";
import "@bacons/text-decoder/install"; polyfillGlobal("Buffer", () => Buffer);
polyfillGlobal("ReadableStream", () => ReadableStream);
import "react-native-get-random-values";

View File

@@ -1 +0,0 @@
export const apiKey = "chat-rn-clerk-example-jazz@garden.co";

View File

@@ -1,20 +1,62 @@
import { useClerk } from "@clerk/clerk-expo"; import { useClerk, useUser } from "@clerk/clerk-expo";
import { JazzProviderWithClerk } from "jazz-react-native-auth-clerk"; import { useJazzClerkAuth } from "jazz-react-native-auth-clerk";
import React, { PropsWithChildren } from "react"; import React, {
import { apiKey } from "./apiKey"; createContext,
PropsWithChildren,
useContext,
useEffect,
useState,
} from "react";
import { Text, View } from "react-native";
import { Jazz, kvStore } from "./jazz";
const AuthContext = createContext<{
isAuthenticated: boolean;
isLoading: boolean;
}>({
isAuthenticated: false,
isLoading: true,
});
export function useAuth() {
return useContext(AuthContext);
}
export function JazzAndAuth({ children }: PropsWithChildren) { export function JazzAndAuth({ children }: PropsWithChildren) {
const { isSignedIn, isLoaded: isClerkLoaded } = useUser();
const clerk = useClerk(); const clerk = useClerk();
const [auth, state] = useJazzClerkAuth(clerk, kvStore);
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
if (isSignedIn && isClerkLoaded && auth) {
setIsAuthenticated(true);
} else {
setIsAuthenticated(false);
}
}, [isSignedIn, isClerkLoaded, auth]);
return ( return (
<JazzProviderWithClerk <AuthContext.Provider
clerk={clerk} value={{ isAuthenticated, isLoading: !isClerkLoaded || !auth }}
storage="sqlite"
sync={{
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
}}
> >
{children} {state?.errors?.length > 0 &&
</JazzProviderWithClerk> state.errors.map((error) => (
<View key={error}>
<Text style={{ color: "red" }}>{error}</Text>
</View>
))}
{auth && clerk.user ? (
<Jazz.Provider
auth={auth}
peer="wss://cloud.jazz.tools/?key=chat-rn-clerk-example-jazz@garden.co"
storage={undefined}
>
{children}
</Jazz.Provider>
) : (
children
)}
</AuthContext.Provider>
); );
} }

View File

@@ -0,0 +1,4 @@
import { createJazzRNApp } from "jazz-react-native";
export const Jazz = createJazzRNApp();
export const { useAccount, useCoState, useAcceptInvite, kvStore } = Jazz;

View File

@@ -1,8 +1,7 @@
import { CoList, CoMap, ImageDefinition, co } from "jazz-tools"; import { CoList, CoMap, co } from "jazz-tools";
export class Message extends CoMap { export class Message extends CoMap {
text = co.string; text = co.string;
image = co.optional.ref(ImageDefinition);
} }
export class Chat extends CoList.Of(co.ref(Message)) {} export class Chat extends CoList.Of(co.ref(Message)) {}

View File

@@ -1,393 +1,5 @@
# chat-rn # chat-rn
## 1.0.87
### Patch Changes
- jazz-react-native@0.12.1
- jazz-tools@0.12.1
## 1.0.86
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- jazz-tools@0.12.0
- jazz-react-native@0.12.0
## 1.0.85
### Patch Changes
- jazz-react-native@0.11.8
- jazz-tools@0.11.8
## 1.0.84
### Patch Changes
- Updated dependencies [a140f55]
- Updated dependencies [2b0d1b0]
- jazz-tools@0.11.7
- jazz-react-native@0.11.7
## 1.0.83
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-react-native@0.11.6
- jazz-tools@0.11.6
## 1.0.82
### Patch Changes
- jazz-react-native@0.11.5
- jazz-tools@0.11.5
## 1.0.81
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react-native@0.11.4
## 1.0.80
### Patch Changes
- jazz-react-native@0.11.3
- jazz-tools@0.11.3
## 1.0.79
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react-native@0.11.2
## 1.0.78
### Patch Changes
- jazz-react-native@0.11.1
## 1.0.77
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react-native@0.11.0
## 1.0.76
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react-native@0.10.15
## 1.0.75
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react-native@0.10.14
## 1.0.74
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-react-native@0.10.13
## 1.0.73
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-react-native@0.10.12
## 1.0.72
### Patch Changes
- Updated dependencies [5a54e4a]
- jazz-react-native@0.10.11
## 1.0.71
### Patch Changes
- Updated dependencies [3405d8f]
- jazz-react-native@0.10.10
## 1.0.70
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-react-native@0.10.8
## 1.0.69
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-react-native@0.10.7
- jazz-tools@0.10.7
## 1.0.68
### Patch Changes
- Updated dependencies [ada802b]
- jazz-tools@0.10.6
- jazz-react-native@0.10.6
## 1.0.67
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-react-native@0.10.5
## 1.0.66
### Patch Changes
- jazz-react-native@0.10.4
- jazz-tools@0.10.4
## 1.0.65
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-react-native@0.10.3
## 1.0.64
### Patch Changes
- jazz-react-native@0.10.2
- jazz-tools@0.10.2
## 1.0.63
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-react-native@0.10.1
## 1.0.62
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-react-native@0.10.0
- jazz-tools@0.10.0
## 1.0.61
### Patch Changes
- jazz-react-native@0.9.23
- jazz-tools@0.9.23
## 1.0.60
### Patch Changes
- jazz-react-native@0.9.22
## 1.0.59
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-react-native@0.9.21
## 1.0.58
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-react-native@0.9.20
## 1.0.57
### Patch Changes
- jazz-react-native@0.9.19
- jazz-tools@0.9.19
## 1.0.56
### Patch Changes
- jazz-react-native@0.9.18
- jazz-tools@0.9.18
## 1.0.55
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-react-native@0.9.17
## 1.0.54
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-tools@0.9.16
- jazz-react-native@0.9.16
## 1.0.53
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-react-native@0.9.15
## 1.0.52
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-react-native@0.9.14
## 1.0.51
### Patch Changes
- jazz-react-native@0.9.13
- jazz-tools@0.9.13
## 1.0.50
### Patch Changes
- jazz-react-native@0.9.12
- jazz-tools@0.9.12
## 1.0.49
### Patch Changes
- jazz-react-native@0.9.11
- jazz-tools@0.9.11
## 1.0.48
### Patch Changes
- Updated dependencies [f76274c]
- Updated dependencies [5e83864]
- jazz-react-native@0.9.10
- jazz-tools@0.9.10
## 1.0.47
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-react-native@0.9.9
## 1.0.46
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react-native@0.9.8
## 1.0.45
### Patch Changes
- Updated dependencies [8a390d2]
- jazz-react-native@0.9.6
## 1.0.44
### Patch Changes
- Updated dependencies [c871912]
- jazz-react-native@0.9.5
## 1.0.43
### Patch Changes
- jazz-react-native@0.9.4
## 1.0.42
### Patch Changes
- Updated dependencies [7cd691f]
- jazz-react-native@0.9.3
## 1.0.41
### Patch Changes
- Updated dependencies [80fd3e9]
- jazz-react-native@0.9.2
## 1.0.40
### Patch Changes
- Updated dependencies [1b71969]
- jazz-tools@0.9.1
- jazz-react-native@0.9.1
## 1.0.39
### Patch Changes
- Updated dependencies [1da4d55]
- Updated dependencies [8eda792]
- Updated dependencies [1e5e3a1]
- jazz-react-native@0.9.0
- jazz-tools@0.9.0
## 1.0.38 ## 1.0.38
### Patch Changes ### Patch Changes

View File

@@ -19,6 +19,7 @@ config.resolver.nodeModulesPaths = [
path.resolve(workspaceRoot, "node_modules"), path.resolve(workspaceRoot, "node_modules"),
]; ];
config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"]; config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"];
config.resolver.unstable_enablePackageExports = true;
config.resolver.requireCycleIgnorePatterns = [ config.resolver.requireCycleIgnorePatterns = [
/(^|\/|\\)node_modules($|\/|\\)/, /(^|\/|\\)node_modules($|\/|\\)/,
/(^|\/|\\)packages($|\/|\\)/, /(^|\/|\\)packages($|\/|\\)/,

View File

@@ -1,6 +1,6 @@
{ {
"name": "chat-rn", "name": "chat-rn",
"version": "1.0.87", "version": "1.0.38",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "expo export -p ios", "build": "expo export -p ios",
@@ -13,17 +13,16 @@
}, },
"dependencies": { "dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2", "@azure/core-asynciterator-polyfill": "^1.0.2",
"@bacons/text-decoder": "0.0.0",
"@craftzdog/react-native-buffer": "6.0.5",
"@op-engineering/op-sqlite": "^11.2.12",
"@react-native-community/netinfo": "^11.4.1", "@react-native-community/netinfo": "^11.4.1",
"@react-navigation/native": "^7.0.13", "@react-navigation/native": "^7.0.13",
"@react-navigation/native-stack": "^7.1.14", "@react-navigation/native-stack": "^7.1.14",
"base-64": "^1.0.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
"expo": "^52.0.0", "expo": "^52.0.0",
"expo-build-properties": "~0.13.1", "expo-build-properties": "~0.13.1",
"expo-clipboard": "~7.0.0", "expo-clipboard": "~7.0.0",
"expo-constants": "~17.0.3", "expo-constants": "~17.0.3",
"expo-crypto": "~14.0.1",
"expo-dev-client": "~5.0.5", "expo-dev-client": "~5.0.5",
"expo-linking": "~7.0.3", "expo-linking": "~7.0.3",
"expo-secure-store": "~14.0.0", "expo-secure-store": "~14.0.0",
@@ -34,16 +33,19 @@
"nativewind": "^4.1.21", "nativewind": "^4.1.21",
"react": "^18.3.1", "react": "^18.3.1",
"react-native": "~0.76.3", "react-native": "~0.76.3",
"react-native-fetch-api": "^3.0.0",
"react-native-get-random-values": "^1.11.0", "react-native-get-random-values": "^1.11.0",
"react-native-polyfill-globals": "^3.1.0",
"react-native-safe-area-context": "4.12.0", "react-native-safe-area-context": "4.12.0",
"react-native-screens": "4.1.0", "react-native-screens": "4.1.0",
"react-native-url-polyfill": "^2.0.0", "react-native-url-polyfill": "^2.0.0",
"readable-stream": "4.7.0" "text-encoding": "^0.7.0",
"web-streams-polyfill": "^3.2.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.0", "@babel/core": "^7.20.0",
"@types/react": "^18.3.12", "@types/react": "^18.3.12",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.15",
"typescript": "~5.6.2" "typescript": "~5.6.2"
}, },
"private": true "private": true

View File

@@ -1,17 +1,6 @@
/* eslint-disable import/order */ import "react-native-polyfill-globals/auto";
// @ts-expect-error - @types/react-native doesn't cover this file
import { polyfillGlobal } from "react-native/Libraries/Utilities/PolyfillFunctions";
import { Buffer } from "@craftzdog/react-native-buffer";
polyfillGlobal("Buffer", () => Buffer);
// @ts-expect-error - @types/readable-stream doesn't have ReadableStream type
import { ReadableStream } from "readable-stream";
polyfillGlobal("ReadableStream", () => ReadableStream);
import "@azure/core-asynciterator-polyfill"; import "@azure/core-asynciterator-polyfill";
import { polyfillGlobal } from "react-native/Libraries/Utilities/PolyfillFunctions";
import { ReadableStream } from "web-streams-polyfill/ponyfill/es6";
import "@bacons/text-decoder/install"; polyfillGlobal("ReadableStream", () => ReadableStream);
import "react-native-get-random-values";

View File

@@ -9,9 +9,9 @@ import * as Linking from "expo-linking";
import React, { StrictMode, useEffect, useState } from "react"; import React, { StrictMode, useEffect, useState } from "react";
import HandleInviteScreen from "./invite"; import HandleInviteScreen from "./invite";
import { JazzProvider } from "jazz-react-native"; import { DemoAuthBasicUI, useDemoAuth } from "jazz-react-native";
import { apiKey } from "./apiKey";
import ChatScreen from "./chat"; import ChatScreen from "./chat";
import { Jazz } from "./jazz";
const Stack = createNativeStackNavigator(); const Stack = createNativeStackNavigator();
@@ -29,10 +29,12 @@ const linking = {
}; };
function App() { function App() {
const [auth, state] = useDemoAuth();
const [initialRoute, setInitialRoute] = useState< const [initialRoute, setInitialRoute] = useState<
"ChatScreen" | "HandleInviteScreen" "ChatScreen" | "HandleInviteScreen"
>("ChatScreen"); >("ChatScreen");
const navigationRef = useNavigationContainerRef(); const navigationRef = useNavigationContainerRef();
useEffect(() => { useEffect(() => {
Linking.getInitialURL().then((url) => { Linking.getInitialURL().then((url) => {
if (url) { if (url) {
@@ -43,13 +45,16 @@ function App() {
}); });
}, []); }, []);
if (!auth) {
return null;
}
return ( return (
<StrictMode> <StrictMode>
<JazzProvider <Jazz.Provider
storage="sqlite" auth={auth}
sync={{ peer="wss://cloud.jazz.tools/?key=chat-rn-example-jazz@garden.co"
peer: `wss://cloud.jazz.tools/?key=${apiKey}`, storage={undefined}
}}
> >
<NavigationContainer linking={linking} ref={navigationRef}> <NavigationContainer linking={linking} ref={navigationRef}>
<Stack.Navigator initialRouteName={initialRoute}> <Stack.Navigator initialRouteName={initialRoute}>
@@ -65,7 +70,10 @@ function App() {
/> />
</Stack.Navigator> </Stack.Navigator>
</NavigationContainer> </NavigationContainer>
</JazzProvider> </Jazz.Provider>
{state.state !== "signedIn" ? (
<DemoAuthBasicUI appName="Jazz Chat" state={state} />
) : null}
</StrictMode> </StrictMode>
); );
} }

View File

@@ -1 +0,0 @@
export const apiKey = "chat-rn-example-jazz@garden.co";

View File

@@ -1,6 +1,6 @@
import clsx from "clsx"; import clsx from "clsx";
import * as Clipboard from "expo-clipboard"; import * as Clipboard from "expo-clipboard";
import { Group, ID, Profile } from "jazz-tools"; import { Group, ID } from "jazz-tools";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import React, { import React, {
Button, Button,
@@ -14,24 +14,18 @@ import React, {
Alert, Alert,
} from "react-native"; } from "react-native";
import { useAccount, useCoState } from "jazz-react-native"; import { useAccount, useCoState } from "./jazz";
import { Chat, Message } from "./schema"; import { Chat, Message } from "./schema";
export default function ChatScreen({ navigation }: { navigation: any }) { export default function ChatScreen({ navigation }: { navigation: any }) {
const { me, logOut } = useAccount(); const { me, logOut } = useAccount();
const [chatId, setChatId] = useState<ID<Chat>>(); const [chatId, setChatId] = useState<ID<Chat>>();
const loadedChat = useCoState(Chat, chatId, { resolve: { $each: true } }); const loadedChat = useCoState(Chat, chatId, [{}]);
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
const profile = useCoState(Profile, me._refs.profile?.id, {});
function handleLogOut() {
setChatId(undefined);
logOut();
}
useEffect(() => { useEffect(() => {
navigation.setOptions({ navigation.setOptions({
headerRight: () => <Button onPress={handleLogOut} title="Logout" />, headerRight: () => <Button onPress={logOut} title="Logout" />,
headerLeft: () => headerLeft: () =>
loadedChat ? ( loadedChat ? (
<Button <Button
@@ -137,19 +131,6 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
<View className="flex flex-col h-full"> <View className="flex flex-col h-full">
{!loadedChat ? ( {!loadedChat ? (
<View className="flex flex-col h-full items-center justify-center"> <View className="flex flex-col h-full items-center justify-center">
<Text className="text-m font-bold mb-6">Username</Text>
<TextInput
className="rounded h-12 p-2 mb-12 w-40 border border-gray-200 block"
value={profile?.name ?? ""}
onChangeText={(value) => {
if (profile) {
profile.name = value;
}
}}
textAlignVertical="center"
onSubmitEditing={sendMessage}
testID="username-input"
/>
<TouchableOpacity <TouchableOpacity
onPress={createChat} onPress={createChat}
className="bg-blue-500 p-4 rounded-md" className="bg-blue-500 p-4 rounded-md"
@@ -191,12 +172,10 @@ export default function ChatScreen({ navigation }: { navigation: any }) {
placeholder="Type a message..." placeholder="Type a message..."
textAlignVertical="center" textAlignVertical="center"
onSubmitEditing={sendMessage} onSubmitEditing={sendMessage}
testID="message-input"
/> />
<TouchableOpacity <TouchableOpacity
onPress={sendMessage} onPress={sendMessage}
className="bg-gray-300 text-white rounded-full h-8 w-8 items-center justify-center" className="bg-gray-300 text-white rounded-full h-8 w-8 items-center justify-center"
testID="send-button"
> >
<Text></Text> <Text></Text>
</TouchableOpacity> </TouchableOpacity>

View File

@@ -1,7 +1,13 @@
import { useAcceptInvite } from "jazz-react-native";
import React, { Text } from "react-native"; import React, { Text } from "react-native";
import { useAcceptInvite } from "./jazz";
import { Chat } from "./schema"; import { Chat } from "./schema";
type ChatScreenParams = {
valueHint?: string;
valueID?: string;
inviteSecret?: string;
};
export default function HandleInviteScreen({ export default function HandleInviteScreen({
navigation, navigation,
}: { }: {

View File

@@ -0,0 +1,4 @@
import { createJazzRNApp } from "jazz-react-native";
export const Jazz = createJazzRNApp();
export const { useAccount, useCoState, useAcceptInvite } = Jazz;

View File

@@ -1,16 +0,0 @@
# this sub-flow exists to work around an ios issue where the text field is not
# fully erased. The tap into the input field hits the middle, and clears all
# text to the left. If there's more to the right, it slides left, and thus we
# repeat this step. https://maestro.mobile.dev/api-reference/commands/erasetext
appId: com.jazz.chatrn
---
- copyTextFrom:
id: ${id}
- repeat:
times: 4
commands:
- tapOn:
id: ${id}
- eraseText
- copyTextFrom:
id: ${id}

View File

@@ -1,50 +0,0 @@
appId: com.jazz.chatrn
---
- launchApp
# # handle Expo screens (for local dev)
# - assertVisible: "Continue"
# - tapOn: "Continue"
# - assertVisible: "Reload"
# - tapOn: "Reload"
# login
- assertVisible: "Anonymous user"
- runFlow:
label: "Erase existing username"
file: erase_text.yml
env:
id: "username-input"
- inputText: "boorad"
- assertVisible: "boorad"
# start new chat
- tapOn: "Start new chat"
- assertVisible: "Share"
- assertVisible: "Jazz Chat"
- assertVisible: "Logout"
# send a message
- tapOn:
id: "message-input"
- inputText: "bro, low key, it do be like that tho"
- tapOn:
id: "send-button"
- assertVisible: "bro, low key, it do be like that tho"
# get invite code
- tapOn: "Share"
- assertVisible: "Copied to clipboard"
- tapOn: "OK"
# this assert doesn't work. maestro.copiedText only populates from `copyTextFrom`
# - assertTrue: ${maestro.copiedText.startsWith("co_z")}
# logout
- tapOn: "Logout"
- assertVisible: "Anonymous user"
# This doesn't work on CI, maybe because Android has a different alert dialog
# - tapOn: "Join chat"
# - inputText: "co_zFs6KFyhxPw4xtw83tcEMzeHUNv" # Use a static id because maestro doesn't have access to the system clipboard
# - pressKey: "enter"
# - assertVisible: "boorad"
# - assertVisible: "bro, low key, it do be like that tho"

View File

@@ -1,20 +0,0 @@
#!/bin/bash
# This script is necessary, because unlike ios, the android emulator action
# accepts a script, runs it as your tests, then terminates.
set -e
# build and install the app
echo "Building and installing Android app."
echo "If it fails, its output will be in artifact: android-install.log..."
cd ./android/
./gradlew installRelease >> ~/output/android-install.log 2>&1
cd ..
# run the e2e tests
export PATH="$PATH":"$HOME/.maestro/bin"
export MAESTRO_DRIVER_STARTUP_TIMEOUT=300000 # setting to 5 mins 👀
export MAESTRO_CLI_NO_ANALYTICS=1
export MAESTRO_CLI_ANALYSIS_NOTIFICATION_DISABLED=true
maestro test test/e2e/flow.yml

View File

@@ -1,391 +1,5 @@
# chat-vue # chat-vue
## 0.0.72
### Patch Changes
- jazz-browser@0.12.1
- jazz-tools@0.12.1
- jazz-vue@0.12.1
## 0.0.71
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- Updated dependencies [4c01459]
- jazz-tools@0.12.0
- jazz-vue@0.12.0
- jazz-browser@0.12.0
## 0.0.70
### Patch Changes
- jazz-browser@0.11.8
- jazz-tools@0.11.8
- jazz-vue@0.11.8
## 0.0.69
### Patch Changes
- Updated dependencies [a140f55]
- Updated dependencies [2b0d1b0]
- jazz-tools@0.11.7
- jazz-browser@0.11.7
- jazz-vue@0.11.7
## 0.0.68
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-tools@0.11.6
- jazz-vue@0.11.6
- jazz-browser@0.11.6
## 0.0.67
### Patch Changes
- jazz-browser@0.11.5
- jazz-tools@0.11.5
- jazz-vue@0.11.5
## 0.0.66
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser@0.11.4
- jazz-vue@0.11.4
## 0.0.65
### Patch Changes
- jazz-browser@0.11.3
- jazz-tools@0.11.3
- jazz-vue@0.11.3
## 0.0.64
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-browser@0.11.2
- jazz-vue@0.11.2
## 0.0.63
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [18428ea]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser@0.11.0
- jazz-vue@0.11.0
## 0.0.62
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser@0.10.15
- jazz-vue@0.10.15
## 0.0.61
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-browser@0.10.14
- jazz-vue@0.10.14
## 0.0.60
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-browser@0.10.13
- jazz-vue@0.10.13
## 0.0.59
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-vue@0.10.12
- jazz-browser@0.10.12
## 0.0.58
### Patch Changes
- Updated dependencies [834203f]
- jazz-browser@0.10.9
- jazz-vue@0.10.9
## 0.0.57
### Patch Changes
- Updated dependencies [1e87fc7]
- Updated dependencies [2fb6428]
- jazz-browser@0.10.8
- jazz-tools@0.10.8
- jazz-vue@0.10.8
## 0.0.56
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [bf76d79]
- Updated dependencies [0eed228]
- jazz-browser@0.10.7
- jazz-tools@0.10.7
- jazz-vue@0.10.7
## 0.0.55
### Patch Changes
- Updated dependencies [ada802b]
- jazz-tools@0.10.6
- jazz-browser@0.10.6
- jazz-vue@0.10.6
## 0.0.54
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-browser@0.10.5
- jazz-vue@0.10.5
## 0.0.53
### Patch Changes
- jazz-browser@0.10.4
- jazz-tools@0.10.4
- jazz-vue@0.10.4
## 0.0.52
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-browser@0.10.3
- jazz-vue@0.10.3
## 0.0.51
### Patch Changes
- jazz-browser@0.10.2
- jazz-tools@0.10.2
- jazz-vue@0.10.2
## 0.0.50
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-browser@0.10.1
- jazz-vue@0.10.1
## 0.0.49
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-browser@0.10.0
- jazz-tools@0.10.0
- jazz-vue@0.10.0
## 0.0.48
### Patch Changes
- jazz-browser@0.9.23
- jazz-tools@0.9.23
- jazz-vue@0.9.23
## 0.0.47
### Patch Changes
- jazz-browser@0.9.22
- jazz-vue@0.9.22
## 0.0.46
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-browser@0.9.21
- jazz-vue@0.9.21
## 0.0.45
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-browser@0.9.20
- jazz-vue@0.9.20
## 0.0.44
### Patch Changes
- jazz-browser@0.9.19
- jazz-tools@0.9.19
- jazz-vue@0.9.19
## 0.0.43
### Patch Changes
- jazz-browser@0.9.18
- jazz-tools@0.9.18
- jazz-vue@0.9.18
## 0.0.42
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-browser@0.9.17
- jazz-vue@0.9.17
## 0.0.41
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-tools@0.9.16
- jazz-browser@0.9.16
- jazz-vue@0.9.16
## 0.0.40
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-browser@0.9.15
- jazz-vue@0.9.15
## 0.0.39
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-browser@0.9.14
- jazz-vue@0.9.14
## 0.0.38
### Patch Changes
- jazz-browser@0.9.13
- jazz-tools@0.9.13
- jazz-vue@0.9.13
## 0.0.37
### Patch Changes
- jazz-browser@0.9.12
- jazz-tools@0.9.12
- jazz-vue@0.9.12
## 0.0.36
### Patch Changes
- jazz-browser@0.9.11
- jazz-tools@0.9.11
- jazz-vue@0.9.11
## 0.0.35
### Patch Changes
- Updated dependencies [5e83864]
- jazz-tools@0.9.10
- jazz-browser@0.9.10
- jazz-vue@0.9.10
## 0.0.34
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-browser@0.9.9
- jazz-vue@0.9.9
## 0.0.33
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-browser@0.9.8
- jazz-vue@0.9.8
## 0.0.32
### Patch Changes
- Updated dependencies [1b71969]
- Updated dependencies [5d98189]
- jazz-browser@0.9.1
- jazz-tools@0.9.1
- jazz-vue@0.9.1
## 0.0.31
### Patch Changes
- Updated dependencies [9dd8d95]
- Updated dependencies [8eda792]
- jazz-vue@0.9.0
- jazz-tools@0.9.0
- jazz-browser@0.9.0
## 0.0.30 ## 0.0.30
### Patch Changes ### Patch Changes

View File

@@ -1,55 +1,29 @@
# Chat example with Jazz and Vue # Chat example with Jazz and Vue
## Getting started ## Installing & running the example locally
You can either (This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation))
1. Clone the jazz repository, and run the app within the monorepo.
2. Or create a new Jazz project using this example as a template.
Start by downloading the [jazz repository](https://github.com/garden-co/jazz):
### Using the example as a template
Create a new Jazz project, and use this example as a template.
```bash ```bash
npx create-jazz-app@latest chat-vue-app --example chat-vue npx degit gardencmp/jazz jazz
``` ```
Go to the new project directory. Go to the todo-vue example directory:
```bash ```bash
cd chat-vue-app cd jazz/examples/chat-vue
``` ```
Run the dev server. Install and build dependencies:
```bash
npm run dev
```
### Using the monorepo
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
Clone the jazz repository.
```bash
git clone https://github.com/garden-co/jazz.git
```
Install and build dependencies.
```bash ```bash
pnpm i && npx turbo build pnpm i && npx turbo build
``` ```
Go to the example directory. Start the dev server:
```bash
cd jazz/examples/chat-vue/
```
Start the dev server.
```bash ```bash
pnpm dev pnpm dev
``` ```
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
## Questions / problems / feedback ## Questions / problems / feedback
If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong. If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong.

View File

@@ -1,6 +1,6 @@
{ {
"name": "chat-vue", "name": "chat-vue",
"version": "0.0.72", "version": "0.0.30",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
@@ -30,9 +30,9 @@
"eslint-plugin-vue": "^9.28.0", "eslint-plugin-vue": "^9.28.0",
"npm-run-all2": "^6.2.3", "npm-run-all2": "^6.2.3",
"postcss": "^8.4.27", "postcss": "^8.4.27",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.15",
"typescript": "~5.6.2", "typescript": "~5.6.2",
"vite": "^6.0.11", "vite": "^5.4.10",
"vite-plugin-vue-devtools": "^7.4.6", "vite-plugin-vue-devtools": "^7.4.6",
"vue-tsc": "^2.1.6" "vue-tsc": "^2.1.6"
} }

View File

@@ -9,9 +9,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useAccount } from "jazz-vue";
import AppContainer from "./components/AppContainer.vue"; import AppContainer from "./components/AppContainer.vue";
import TopBar from "./components/TopBar.vue"; import TopBar from "./components/TopBar.vue";
import { useAccount } from "./main";
const { me, logOut } = useAccount(); const { me, logOut } = useAccount();
</script> </script>

View File

@@ -1 +0,0 @@
export const apiKey = "chat-example-jazz@garden.co";

View File

@@ -1,31 +1,36 @@
import { DemoAuthBasicUI, JazzProvider } from "jazz-vue"; import { DemoAuthBasicUI, createJazzVueApp, useDemoAuth } from "jazz-vue";
import { createApp, defineComponent, h } from "vue"; import { createApp, defineComponent, h } from "vue";
import App from "./App.vue"; import App from "./App.vue";
import "./index.css"; import "./index.css";
import { apiKey } from "@/apiKey";
import router from "./router"; import router from "./router";
const Jazz = createJazzVueApp();
export const { useAccount, useCoState } = Jazz;
const { JazzProvider } = Jazz;
const RootComponent = defineComponent({ const RootComponent = defineComponent({
name: "RootComponent", name: "RootComponent",
setup() { setup() {
return () => const { authMethod, state } = useDemoAuth();
return () => [
h( h(
JazzProvider, JazzProvider,
{ {
sync: { auth: authMethod.value,
peer: `wss://cloud.jazz.tools/?key=${apiKey}`, peer: "wss://cloud.jazz.tools/?key=chat-example-jazz@garden.co",
},
}, },
h( {
DemoAuthBasicUI, default: () => h(App),
{ },
appName: "Jazz Vue Chat", ),
},
{ state.state !== "signedIn" &&
default: () => h(App), h(DemoAuthBasicUI, {
}, appName: "Jazz Chat",
), state,
); }),
];
}, },
}); });

View File

@@ -26,12 +26,12 @@
<script lang="ts"> <script lang="ts">
import type { ID } from "jazz-tools"; import type { ID } from "jazz-tools";
import { useCoState } from "jazz-vue";
import { type PropType, computed, defineComponent, ref } from "vue"; import { type PropType, computed, defineComponent, ref } from "vue";
import ChatBody from "../components/ChatBody.vue"; import ChatBody from "../components/ChatBody.vue";
import ChatBubble from "../components/ChatBubble.vue"; import ChatBubble from "../components/ChatBubble.vue";
import ChatInput from "../components/ChatInput.vue"; import ChatInput from "../components/ChatInput.vue";
import EmptyChatMessage from "../components/EmptyChatMessage.vue"; import EmptyChatMessage from "../components/EmptyChatMessage.vue";
import { useCoState } from "../main";
import { Chat, Message } from "../schema"; import { Chat, Message } from "../schema";
export default defineComponent({ export default defineComponent({
@@ -49,7 +49,7 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const chat = useCoState(Chat, props.chatId, { resolve: { $each: true } }); const chat = useCoState(Chat, props.chatId, [{}]);
const showNLastMessages = ref(30); const showNLastMessages = ref(30);
const displayedMessages = computed(() => { const displayedMessages = computed(() => {

View File

@@ -4,8 +4,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { Group } from "jazz-tools"; import { Group } from "jazz-tools";
import { useAccount } from "jazz-vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useAccount } from "../main";
import { Chat } from "../schema"; import { Chat } from "../schema";
const router = useRouter(); const router = useRouter();

View File

@@ -1,409 +1,5 @@
# jazz-example-chat # jazz-example-chat
## 0.0.169
### Patch Changes
- jazz-inspector@0.12.1
- jazz-react@0.12.1
- jazz-tools@0.12.1
## 0.0.168
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- Updated dependencies [9a56bb3]
- jazz-tools@0.12.0
- jazz-inspector@0.12.0
- jazz-react@0.12.0
## 0.0.167
### Patch Changes
- Updated dependencies [71b9390]
- jazz-inspector@0.11.8
- jazz-react@0.11.8
- jazz-tools@0.11.8
## 0.0.166
### Patch Changes
- Updated dependencies [2c3761c]
- Updated dependencies [a140f55]
- Updated dependencies [4019918]
- Updated dependencies [2b0d1b0]
- jazz-inspector@0.11.7
- jazz-tools@0.11.7
- jazz-react@0.11.7
## 0.0.165
### Patch Changes
- Updated dependencies [e7c85b7]
- Updated dependencies [09f0a98]
- Updated dependencies [11da4d1]
- Updated dependencies [8ed144e]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-inspector@0.11.6
- jazz-browser-media-images@0.11.6
## 0.0.164
### Patch Changes
- jazz-react@0.11.5
- jazz-tools@0.11.5
- jazz-browser-media-images@0.11.5
## 0.0.163
### Patch Changes
- 2074e45: In the chat app example, show a "Message not readable" placeholder, if messages from a chat list are not readable by the user.
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser-media-images@0.11.4
- jazz-react@0.11.4
## 0.0.162
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
- jazz-browser-media-images@0.11.3
## 0.0.161
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-browser-media-images@0.11.2
## 0.0.160
### Patch Changes
- jazz-react@0.11.1
## 0.0.159
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser-media-images@0.11.0
- jazz-react@0.11.0
## 0.0.158
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser-media-images@0.10.15
- jazz-react@0.10.15
## 0.0.157
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-browser-media-images@0.10.14
## 0.0.156
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-browser-media-images@0.10.13
- jazz-react@0.10.13
## 0.0.155
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-react@0.10.12
- jazz-browser-media-images@0.10.12
## 0.0.154
### Patch Changes
- jazz-browser-media-images@0.10.9
- jazz-react@0.10.9
## 0.0.153
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-react@0.10.8
- jazz-browser-media-images@0.10.8
## 0.0.152
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-react@0.10.7
- jazz-tools@0.10.7
- jazz-browser-media-images@0.10.7
## 0.0.151
### Patch Changes
- Updated dependencies [1d71ca1]
- Updated dependencies [ada802b]
- hash-slash@0.2.2
- jazz-react@0.10.6
- jazz-tools@0.10.6
- jazz-browser-media-images@0.10.6
## 0.0.150
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-browser-media-images@0.10.5
- jazz-react@0.10.5
## 0.0.149
### Patch Changes
- jazz-react@0.10.4
- jazz-tools@0.10.4
- jazz-browser-media-images@0.10.4
## 0.0.148
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-browser-media-images@0.10.3
- jazz-react@0.10.3
## 0.0.147
### Patch Changes
- jazz-react@0.10.2
- jazz-tools@0.10.2
- jazz-browser-media-images@0.10.2
## 0.0.146
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-browser-media-images@0.10.1
- jazz-react@0.10.1
## 0.0.145
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-react@0.10.0
- jazz-tools@0.10.0
- jazz-browser-media-images@0.10.0
## 0.0.144
### Patch Changes
- jazz-react@0.9.23
- jazz-tools@0.9.23
- jazz-browser-media-images@0.9.23
## 0.0.143
### Patch Changes
- jazz-browser-media-images@0.9.22
- jazz-react@0.9.22
## 0.0.142
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-browser-media-images@0.9.21
- jazz-react@0.9.21
## 0.0.141
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-browser-media-images@0.9.20
- jazz-react@0.9.20
## 0.0.140
### Patch Changes
- jazz-react@0.9.19
- jazz-tools@0.9.19
- jazz-browser-media-images@0.9.19
## 0.0.139
### Patch Changes
- jazz-react@0.9.18
- jazz-tools@0.9.18
- jazz-browser-media-images@0.9.18
## 0.0.138
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-browser-media-images@0.9.17
- jazz-react@0.9.17
## 0.0.137
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-tools@0.9.16
- jazz-browser-media-images@0.9.16
- jazz-react@0.9.16
## 0.0.136
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-browser-media-images@0.9.15
- jazz-react@0.9.15
## 0.0.135
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-browser-media-images@0.9.14
- jazz-react@0.9.14
## 0.0.134
### Patch Changes
- jazz-react@0.9.13
- jazz-tools@0.9.13
- jazz-browser-media-images@0.9.13
## 0.0.133
### Patch Changes
- jazz-react@0.9.12
- jazz-tools@0.9.12
- jazz-browser-media-images@0.9.12
## 0.0.132
### Patch Changes
- jazz-react@0.9.11
- jazz-tools@0.9.11
- jazz-browser-media-images@0.9.11
## 0.0.131
### Patch Changes
- f76274c: Fix image handling in react-native
- Updated dependencies [5e83864]
- jazz-react@0.9.10
- jazz-tools@0.9.10
- jazz-browser-media-images@0.9.10
## 0.0.130
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-browser-media-images@0.9.9
- jazz-react@0.9.9
## 0.0.129
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.128
### Patch Changes
- jazz-react@0.9.4
## 0.0.127
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.126
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.125 ## 0.0.125
### Patch Changes ### Patch Changes

View File

@@ -2,56 +2,30 @@
Live version: [https://chat.jazz.tools](https://chat.jazz.tools) Live version: [https://chat.jazz.tools](https://chat.jazz.tools)
## Getting started ## Installing & running the example locally
You can either (This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation))
1. Clone the jazz repository, and run the app within the monorepo.
2. Or create a new Jazz project using this example as a template.
Start by downloading the [jazz repository](https://github.com/garden-co/jazz):
### Using the example as a template
Create a new Jazz project, and use this example as a template.
```bash ```bash
npx create-jazz-app@latest chat-app --example chat npx degit gardencmp/jazz jazz
``` ```
Go to the new project directory. Go to the chat example directory:
```bash ```bash
cd chat-app cd jazz/examples/chat
``` ```
Run the dev server. Install and build dependencies:
```bash
npm run dev
```
### Using the monorepo
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
Clone the jazz repository.
```bash
git clone https://github.com/garden-co/jazz.git
```
Install and build dependencies.
```bash ```bash
pnpm i && npx turbo build pnpm i && npx turbo build
``` ```
Go to the example directory. Start the dev server:
```bash
cd jazz/examples/chat/
```
Start the dev server.
```bash ```bash
pnpm dev pnpm dev
``` ```
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
## Questions / problems / feedback ## Questions / problems / feedback
If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong. If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong.
@@ -60,4 +34,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work. By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/main.tsx](./src/main.tsx). You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).

View File

@@ -1,7 +1,7 @@
{ {
"name": "jazz-example-chat", "name": "jazz-example-chat",
"private": true, "private": true,
"version": "0.0.169", "version": "0.0.125",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -9,13 +9,13 @@
"format-and-lint": "biome check .", "format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write", "format-and-lint:fix": "biome check . --write",
"preview": "vite preview", "preview": "vite preview",
"test:e2e": "playwright test", "test": "playwright test",
"test:e2e:ui": "playwright test --ui" "test:ui": "playwright test --ui"
}, },
"dependencies": { "dependencies": {
"clsx": "^2.0.0", "clsx": "^2.0.0",
"hash-slash": "workspace:*", "hash-slash": "workspace:*",
"jazz-inspector": "workspace:*", "jazz-browser-media-images": "workspace:*",
"jazz-react": "workspace:*", "jazz-react": "workspace:*",
"jazz-tools": "workspace:*", "jazz-tools": "workspace:*",
"lucide-react": "^0.274.0", "lucide-react": "^0.274.0",
@@ -23,15 +23,15 @@
"react-dom": "^18.3.1" "react-dom": "^18.3.1"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.50.1", "@playwright/test": "^1.46.1",
"@types/react": "^18.3.12", "@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1", "@types/react-dom": "^18.3.1",
"@vitejs/plugin-react-swc": "^3.3.2", "@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"is-ci": "^3.0.1", "is-ci": "^3.0.1",
"postcss": "^8.4.27", "postcss": "^8.4.27",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.15",
"typescript": "~5.6.2", "typescript": "~5.6.2",
"vite": "^6.0.11" "vite": "^5.4.10"
} }
} }

View File

@@ -1 +0,0 @@
export const apiKey = "chat-example-jazz@garden.co";

View File

@@ -1,14 +1,9 @@
import { apiKey } from "@/apiKey.ts"; import { inIframe, onChatLoad } from "@/util.ts";
import { getRandomUsername, inIframe, onChatLoad } from "@/util.ts";
import { useIframeHashRouter } from "hash-slash"; import { useIframeHashRouter } from "hash-slash";
import { JazzInspector } from "jazz-inspector";
import { JazzProvider, useAccount } from "jazz-react";
import { Group, ID } from "jazz-tools"; import { Group, ID } from "jazz-tools";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { ChatScreen } from "./chatScreen.tsx"; import { ChatScreen } from "./chatScreen.tsx";
import { useAccount } from "./main.tsx";
import { Chat } from "./schema.ts"; import { Chat } from "./schema.ts";
import { ThemeProvider } from "./themeProvider.tsx";
import { AppContainer, TopBar } from "./ui.tsx"; import { AppContainer, TopBar } from "./ui.tsx";
export function App() { export function App() {
@@ -17,9 +12,9 @@ export function App() {
const createChat = () => { const createChat = () => {
if (!me) return; if (!me) return;
const group = Group.create(); const group = Group.create({ owner: me });
group.addMember("everyone", "writer"); group.addMember("everyone", "writer");
const chat = Chat.create([], group); const chat = Chat.create([], { owner: group });
router.navigate("/#/chat/" + chat.id); router.navigate("/#/chat/" + chat.id);
// for https://jazz.tools marketing site demo only // for https://jazz.tools marketing site demo only
@@ -29,16 +24,7 @@ export function App() {
return ( return (
<AppContainer> <AppContainer>
<TopBar> <TopBar>
<input <p>{me?.profile?.name}</p>
type="text"
value={me?.profile?.name ?? ""}
className="bg-transparent"
onChange={(e) => {
if (!me?.profile) return;
me.profile.name = e.target.value;
}}
placeholder="Set username"
/>
{!inIframe && <button onClick={logOut}>Log out</button>} {!inIframe && <button onClick={logOut}>Log out</button>}
</TopBar> </TopBar>
{router.route({ {router.route({
@@ -48,22 +34,3 @@ export function App() {
</AppContainer> </AppContainer>
); );
} }
const url = new URL(window.location.href);
const defaultProfileName = url.searchParams.get("user") ?? getRandomUsername();
createRoot(document.getElementById("root")!).render(
<ThemeProvider>
<StrictMode>
<JazzProvider
sync={{
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
}}
defaultProfileName={defaultProfileName}
>
<App />
<JazzInspector />
</JazzProvider>
</StrictMode>
</ThemeProvider>,
);

View File

@@ -1,6 +1,7 @@
import { createImage, useAccount, useCoState } from "jazz-react"; import { createImage } from "jazz-browser-media-images";
import { Account, ID } from "jazz-tools"; import { ID } from "jazz-tools";
import { useState } from "react"; import { useState } from "react";
import { useAccount, useCoState } from "./main.tsx";
import { Chat, Message } from "./schema.ts"; import { Chat, Message } from "./schema.ts";
import { import {
BubbleBody, BubbleBody,
@@ -16,8 +17,8 @@ import {
} from "./ui.tsx"; } from "./ui.tsx";
export function ChatScreen(props: { chatID: ID<Chat> }) { export function ChatScreen(props: { chatID: ID<Chat> }) {
const chat = useCoState(Chat, props.chatID, { resolve: { $each: true } }); const chat = useCoState(Chat, props.chatID, [{}]);
const account = useAccount(); const { me } = useAccount();
const [showNLastMessages, setShowNLastMessages] = useState(30); const [showNLastMessages, setShowNLastMessages] = useState(30);
if (!chat) if (!chat)
@@ -26,6 +27,8 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
); );
const sendImage = (event: React.ChangeEvent<HTMLInputElement>) => { const sendImage = (event: React.ChangeEvent<HTMLInputElement>) => {
if (!me?.profile) return;
const file = event.currentTarget.files?.[0]; const file = event.currentTarget.files?.[0];
if (!file) return; if (!file) return;
@@ -36,7 +39,12 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
} }
createImage(file, { owner: chat._owner }).then((image) => { createImage(file, { owner: chat._owner }).then((image) => {
chat.push(Message.create({ text: file.name, image: image }, chat._owner)); chat.push(
Message.create(
{ text: file.name, image: image },
{ owner: chat._owner },
),
);
}); });
}; };
@@ -47,7 +55,7 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
chat chat
.slice(-showNLastMessages) .slice(-showNLastMessages)
.reverse() // this plus flex-col-reverse on ChatBody gives us scroll-to-bottom behavior .reverse() // this plus flex-col-reverse on ChatBody gives us scroll-to-bottom behavior
.map((msg) => <ChatBubble me={account.me} msg={msg} key={msg.id} />) .map((msg) => <ChatBubble msg={msg} key={msg.id} />)
) : ( ) : (
<EmptyChatMessage /> <EmptyChatMessage />
)} )}
@@ -74,20 +82,7 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
); );
} }
function ChatBubble(props: { me: Account; msg: Message }) { function ChatBubble(props: { msg: Message }) {
if (!props.me.canRead(props.msg)) {
return (
<BubbleContainer fromMe={false}>
<BubbleBody fromMe={false}>
<BubbleText
text="Message not readable"
className="text-gray-500 italic"
/>
</BubbleBody>
</BubbleContainer>
);
}
const lastEdit = props.msg._edits.text; const lastEdit = props.msg._edits.text;
const fromMe = lastEdit.by?.isMe; const fromMe = lastEdit.by?.isMe;
const { text, image } = props.msg; const { text, image } = props.msg;

View File

@@ -0,0 +1,36 @@
import { ThemeProvider } from "@/themeProvider.tsx";
import { DemoAuthBasicUI, createJazzReactApp, useDemoAuth } from "jazz-react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { App } from "./app.tsx";
const Jazz = createJazzReactApp();
export const { useAccount, useCoState } = Jazz;
function JazzAndAuth({ children }: { children: React.ReactNode }) {
const [auth, state] = useDemoAuth();
return (
<>
<Jazz.Provider
auth={auth}
peer="wss://cloud.jazz.tools/?key=chat-example-jazz@garden.co"
>
{children}
</Jazz.Provider>
{state.state !== "signedIn" && (
<DemoAuthBasicUI appName="Jazz Chat" state={state} />
)}
</>
);
}
createRoot(document.getElementById("root")!).render(
<ThemeProvider>
<StrictMode>
<JazzAndAuth>
<App />
</JazzAndAuth>
</StrictMode>
</ThemeProvider>,
);

View File

@@ -6,7 +6,7 @@ import { useId, useRef } from "react";
export function AppContainer(props: { children: React.ReactNode }) { export function AppContainer(props: { children: React.ReactNode }) {
return ( return (
<div className="flex flex-col justify-between w-screen h-screen bg-stone-50 dark:bg-stone-925 dark:text-white"> <div className="flex flex-col justify-between w-screen h-screen bg-stone-50 dark:bg-black dark:text-white">
{props.children} {props.children}
</div> </div>
); );
@@ -14,7 +14,7 @@ export function AppContainer(props: { children: React.ReactNode }) {
export function TopBar(props: { children: React.ReactNode }) { export function TopBar(props: { children: React.ReactNode }) {
return ( return (
<div className="p-3 bg-white w-full flex justify-between gap-2 border-b dark:bg-transparent dark:border-stone-900"> <div className="p-3 bg-white w-full flex justify-between gap-2 border-b dark:bg-transparent dark:border-stone-800">
{props.children} {props.children}
</div> </div>
); );
@@ -33,7 +33,7 @@ export function ChatBody(props: { children: React.ReactNode }) {
export function EmptyChatMessage() { export function EmptyChatMessage() {
return ( return (
<div className="h-full text-base text-stone-500 flex items-center justify-center px-3 md:text-2xl"> <div className="h-full text-base text-stone-500 flex items-center justify-center px-3 text-lg md:text-2xl">
Start a conversation below. Start a conversation below.
</div> </div>
); );
@@ -61,7 +61,7 @@ export function BubbleBody(props: {
"line-clamp-10 text-ellipsis whitespace-pre-wrap", "line-clamp-10 text-ellipsis whitespace-pre-wrap",
"rounded-2xl overflow-hidden max-w-[calc(100%-5rem)] shadow-sm p-1", "rounded-2xl overflow-hidden max-w-[calc(100%-5rem)] shadow-sm p-1",
props.fromMe props.fromMe
? "bg-white dark:bg-stone-900 dark:text-white" ? "bg-white dark:bg-stone-700 dark:text-white"
: "bg-blue text-white", : "bg-blue text-white",
)} )}
> >
@@ -70,12 +70,8 @@ export function BubbleBody(props: {
); );
} }
export function BubbleText(props: { text: string; className?: string }) { export function BubbleText(props: { text: string }) {
return ( return <p className="px-2 leading-relaxed">{props.text}</p>;
<p className={clsx("px-2 leading-relaxed", props.className)}>
{props.text}
</p>
);
} }
export function BubbleImage(props: { image: ImageDefinition }) { export function BubbleImage(props: { image: ImageDefinition }) {
@@ -101,7 +97,7 @@ export function BubbleInfo(props: { by: string | undefined; madeAt: Date }) {
export function InputBar(props: { children: React.ReactNode }) { export function InputBar(props: { children: React.ReactNode }) {
return ( return (
<div className="p-3 bg-white border-t shadow-2xl mt-auto flex gap-1 dark:bg-transparent dark:border-stone-900"> <div className="p-3 bg-white border-t shadow-2xl mt-auto flex gap-1 dark:bg-transparent dark:border-stone-800">
{props.children} {props.children}
</div> </div>
); );
@@ -151,7 +147,7 @@ export function TextInput(props: { onSubmit: (text: string) => void }) {
</label> </label>
<input <input
id={inputId} id={inputId}
className="rounded-full py-1 px-3 border block w-full placeholder:text-stone-500 dark:bg-stone-925 dark:text-white dark:border-stone-900" className="rounded-full py-1 px-3 border block w-full placeholder:text-stone-500 dark:bg-black dark:text-white dark:border-stone-700"
placeholder="Type a message and press Enter" placeholder="Type a message and press Enter"
maxLength={2048} maxLength={2048}
onKeyDown={({ key, currentTarget: input }) => { onKeyDown={({ key, currentTarget: input }) => {

View File

@@ -15,20 +15,3 @@ export function onChatLoad(chat: Chat) {
} }
export const inIframe = window.self !== window.top; export const inIframe = window.self !== window.top;
const animals = [
"elephant",
"penguin",
"giraffe",
"octopus",
"kangaroo",
"dolphin",
"cheetah",
"koala",
"platypus",
"pangolin",
];
export function getRandomUsername() {
return `Anonymous ${animals[Math.floor(Math.random() * animals.length)]}`;
}

View File

@@ -1,35 +1,48 @@
import { test } from "@playwright/test"; import { test } from "@playwright/test";
import { ChatPage } from "./pages/ChatPage"; import { ChatPage } from "./pages/ChatPage";
import { LoginPage } from "./pages/LoginPage";
test("chat between two users", async ({ page: marioPage, browser }) => { test("chat between two users", async ({ page }) => {
const context = await browser.newContext(); const loginPage = new LoginPage(page);
const luigiPage = await context.newPage();
await marioPage.goto("/"); const mario = "S. Mario";
const luigi = "Luigi";
const marioChat = new ChatPage(marioPage); await loginPage.goto();
const luigiChat = new ChatPage(luigiPage); await loginPage.fillUsername(mario);
await loginPage.signup();
await marioChat.setUsername("Mario"); const chatPage = new ChatPage(page);
const message1ByMario = "Hello Luigi, are you ready to save the princess?"; const message1ByMario = "Hello Luigi, are you ready to save the princess?";
await marioChat.sendMessage(message1ByMario); await chatPage.sendMessage(message1ByMario);
await marioChat.expectMessageRow(message1ByMario); await chatPage.expectMessageRow(message1ByMario);
const roomURL = marioPage.url(); const roomURL = page.url();
await luigiPage.goto(roomURL);
await luigiChat.setUsername("Luigi"); await chatPage.logout();
await luigiChat.expectMessageRow(message1ByMario); await loginPage.expectLoaded();
await loginPage.fillUsername(luigi);
await loginPage.signup();
await page.goto(roomURL);
await chatPage.expectMessageRow(message1ByMario);
const message2ByLuigi = const message2ByLuigi =
"No, I'm not ready yet. I'm still trying to find the key to the castle."; "No, I'm not ready yet. I'm still trying to find the key to the castle.";
await luigiChat.sendMessage(message2ByLuigi); await chatPage.sendMessage(message2ByLuigi);
await luigiChat.expectMessageRow(message2ByLuigi); await chatPage.expectMessageRow(message2ByLuigi);
await marioChat.expectMessageRow(message1ByMario); await chatPage.logout();
await luigiChat.expectMessageRow(message2ByLuigi); await loginPage.loginAs(mario);
await page.goto(roomURL);
await chatPage.expectMessageRow(message1ByMario);
await chatPage.expectMessageRow(message2ByLuigi);
}); });

View File

@@ -4,7 +4,7 @@ export class ChatPage {
readonly page: Page; readonly page: Page;
readonly messageInput: Locator; readonly messageInput: Locator;
readonly logoutButton: Locator; readonly logoutButton: Locator;
readonly usernameInput: Locator;
constructor(page: Page) { constructor(page: Page) {
this.page = page; this.page = page;
this.messageInput = page.getByRole("textbox", { this.messageInput = page.getByRole("textbox", {
@@ -13,11 +13,6 @@ export class ChatPage {
this.logoutButton = page.getByRole("button", { this.logoutButton = page.getByRole("button", {
name: "Log out", name: "Log out",
}); });
this.usernameInput = page.getByPlaceholder("Set username");
}
async setUsername(username: string) {
await this.usernameInput.fill(username);
} }
async sendMessage(message: string) { async sendMessage(message: string) {

View File

@@ -0,0 +1,40 @@
import { Locator, Page, expect } from "@playwright/test";
export class LoginPage {
readonly page: Page;
readonly usernameInput: Locator;
readonly signupButton: Locator;
constructor(page: Page) {
this.page = page;
this.usernameInput = page.getByRole("textbox");
this.signupButton = page.getByRole("button", {
name: "Sign up",
});
}
async goto() {
this.page.goto("/");
}
async fillUsername(value: string) {
await this.usernameInput.clear();
await this.usernameInput.fill(value);
}
async loginAs(value: string) {
await this.page
.getByRole("button", {
name: value,
})
.click();
}
async signup() {
await this.signupButton.click();
}
async expectLoaded() {
await expect(this.signupButton).toBeVisible();
}
}

View File

@@ -1,402 +1,5 @@
# minimal-auth-clerk # minimal-auth-clerk
## 0.0.68
### Patch Changes
- jazz-react@0.12.1
- jazz-react-auth-clerk@0.12.1
- jazz-tools@0.12.1
## 0.0.67
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- jazz-tools@0.12.0
- jazz-react@0.12.0
- jazz-react-auth-clerk@0.12.0
## 0.0.66
### Patch Changes
- jazz-react@0.11.8
- jazz-react-auth-clerk@0.11.8
- jazz-tools@0.11.8
## 0.0.65
### Patch Changes
- Updated dependencies [a140f55]
- Updated dependencies [4019918]
- Updated dependencies [2b0d1b0]
- jazz-tools@0.11.7
- jazz-react@0.11.7
- jazz-react-auth-clerk@0.11.7
## 0.0.64
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-react-auth-clerk@0.11.6
## 0.0.63
### Patch Changes
- jazz-react@0.11.5
- jazz-react-auth-clerk@0.11.5
- jazz-tools@0.11.5
## 0.0.62
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
- jazz-react-auth-clerk@0.11.4
## 0.0.61
### Patch Changes
- jazz-react@0.11.3
- jazz-react-auth-clerk@0.11.3
- jazz-tools@0.11.3
## 0.0.60
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-react-auth-clerk@0.11.2
## 0.0.59
### Patch Changes
- jazz-react@0.11.1
- jazz-react-auth-clerk@0.11.1
## 0.0.58
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-react-auth-clerk@0.11.0
- jazz-react@0.11.0
## 0.0.57
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
- jazz-react-auth-clerk@0.10.15
## 0.0.56
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-react-auth-clerk@0.10.14
## 0.0.55
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-react@0.10.13
- jazz-react-auth-clerk@0.10.13
## 0.0.54
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-react@0.10.12
- jazz-react-auth-clerk@0.10.12
## 0.0.53
### Patch Changes
- jazz-react@0.10.9
- jazz-react-auth-clerk@0.10.9
## 0.0.52
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-react@0.10.8
- jazz-react-auth-clerk@0.10.8
## 0.0.51
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-react-auth-clerk@0.10.7
- jazz-react@0.10.7
- jazz-tools@0.10.7
## 0.0.50
### Patch Changes
- Updated dependencies [1d71ca1]
- Updated dependencies [ada802b]
- jazz-react-auth-clerk@0.10.6
- jazz-react@0.10.6
- jazz-tools@0.10.6
## 0.0.49
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-react@0.10.5
- jazz-react-auth-clerk@0.10.5
## 0.0.48
### Patch Changes
- jazz-react@0.10.4
- jazz-react-auth-clerk@0.10.4
- jazz-tools@0.10.4
## 0.0.47
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-react@0.10.3
- jazz-react-auth-clerk@0.10.3
## 0.0.46
### Patch Changes
- jazz-react@0.10.2
- jazz-react-auth-clerk@0.10.2
- jazz-tools@0.10.2
## 0.0.45
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-react@0.10.1
- jazz-react-auth-clerk@0.10.1
## 0.0.44
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-react-auth-clerk@0.10.0
- jazz-react@0.10.0
- jazz-tools@0.10.0
## 0.0.43
### Patch Changes
- jazz-react@0.9.23
- jazz-react-auth-clerk@0.9.23
- jazz-tools@0.9.23
## 0.0.42
### Patch Changes
- jazz-react@0.9.22
- jazz-react-auth-clerk@0.9.22
## 0.0.41
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-react@0.9.21
- jazz-react-auth-clerk@0.9.21
## 0.0.40
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-react@0.9.20
- jazz-react-auth-clerk@0.9.20
## 0.0.39
### Patch Changes
- jazz-react@0.9.19
- jazz-react-auth-clerk@0.9.19
- jazz-tools@0.9.19
## 0.0.38
### Patch Changes
- jazz-react@0.9.18
- jazz-react-auth-clerk@0.9.18
- jazz-tools@0.9.18
## 0.0.37
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-react@0.9.17
- jazz-react-auth-clerk@0.9.17
## 0.0.36
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-react-auth-clerk@0.9.16
- jazz-tools@0.9.16
- jazz-react@0.9.16
## 0.0.35
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-react@0.9.15
- jazz-react-auth-clerk@0.9.15
## 0.0.34
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-react@0.9.14
- jazz-react-auth-clerk@0.9.14
## 0.0.33
### Patch Changes
- jazz-react@0.9.13
- jazz-react-auth-clerk@0.9.13
- jazz-tools@0.9.13
## 0.0.32
### Patch Changes
- jazz-react@0.9.12
- jazz-react-auth-clerk@0.9.12
- jazz-tools@0.9.12
## 0.0.31
### Patch Changes
- jazz-react@0.9.11
- jazz-react-auth-clerk@0.9.11
- jazz-tools@0.9.11
## 0.0.30
### Patch Changes
- Updated dependencies [5e83864]
- jazz-react@0.9.10
- jazz-tools@0.9.10
- jazz-react-auth-clerk@0.9.10
## 0.0.29
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-react@0.9.9
- jazz-react-auth-clerk@0.9.9
## 0.0.28
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-react-auth-clerk@0.9.8
## 0.0.27
### Patch Changes
- jazz-react@0.9.4
- jazz-react-auth-clerk@0.9.4
## 0.0.26
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-react-auth-clerk@0.9.1
## 0.0.25
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-react-auth-clerk@0.9.0
## 0.0.24 ## 0.0.24
### Patch Changes ### Patch Changes

View File

@@ -4,56 +4,30 @@ This is an example of how to use clerk authentication with Jazz.
Live version: https://clerk-demo.jazz.tools Live version: https://clerk-demo.jazz.tools
## Getting started ## Installing & running the example locally
You can either (This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation))
1. Clone the jazz repository, and run the app within the monorepo.
2. Or create a new Jazz project using this example as a template.
Start by downloading the [jazz repository](https://github.com/garden-co/jazz):
### Using the example as a template
Create a new Jazz project, and use this example as a template.
```bash ```bash
npx create-jazz-app@latest clerk-app --example clerk npx degit gardencmp/jazz jazz
``` ```
Go to the new project directory. Go to the clerk example directory:
```bash ```bash
cd clerk-app cd jazz/examples/clerk
``` ```
Run the dev server. Install and build dependencies:
```bash
npm run dev
```
### Using the monorepo
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
Clone the jazz repository.
```bash
git clone https://github.com/garden-co/jazz.git
```
Install and build dependencies.
```bash ```bash
pnpm i && npx turbo build pnpm i && npx turbo build
``` ```
Go to the example directory. Start the dev server:
```bash
cd jazz/examples/clerk/
```
Start the dev server.
```bash ```bash
pnpm dev pnpm dev
``` ```
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
## Questions / problems / feedback ## Questions / problems / feedback
If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong. If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong.

View File

@@ -1,7 +1,7 @@
{ {
"name": "clerk", "name": "clerk",
"private": true, "private": true,
"version": "0.0.68", "version": "0.0.24",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -13,7 +13,7 @@
"dependencies": { "dependencies": {
"@clerk/clerk-react": "^5.4.1", "@clerk/clerk-react": "^5.4.1",
"jazz-react": "workspace:*", "jazz-react": "workspace:*",
"jazz-react-auth-clerk": "workspace:0.12.1", "jazz-react-auth-clerk": "workspace:0.8.51",
"jazz-tools": "workspace:*", "jazz-tools": "workspace:*",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1" "react-dom": "^18.3.1"
@@ -25,6 +25,6 @@
"@vitejs/plugin-react": "^4.3.3", "@vitejs/plugin-react": "^4.3.3",
"globals": "^15.11.0", "globals": "^15.11.0",
"typescript": "~5.6.2", "typescript": "~5.6.2",
"vite": "^6.0.11" "vite": "^5.4.10"
} }
} }

View File

@@ -1,25 +1,13 @@
import { SignInButton } from "@clerk/clerk-react"; import { useAccount } from "./main";
import { useAccount, useIsAuthenticated } from "jazz-react";
function App() { function App() {
const { me, logOut } = useAccount(); const { me, logOut } = useAccount();
const isAuthenticated = useIsAuthenticated();
if (isAuthenticated) {
return (
<div className="container">
<h1>You're logged in</h1>
<p>Welcome back, {me?.profile?.name}</p>
<button onClick={() => logOut()}>Logout</button>
</div>
);
}
return ( return (
<div className="container"> <div className="container">
<h1>You're not logged in</h1> <h1>You're logged in</h1>
<SignInButton /> <p>Welcome back, {me?.profile?.name}</p>
<button onClick={() => logOut()}>Logout</button>
</div> </div>
); );
} }

View File

@@ -1 +0,0 @@
export const apiKey = "minimal-auth-clerk-example@garden.co";

View File

@@ -62,7 +62,7 @@ button {
} }
.container { .container {
max-width: 400px; max-width: 200px;
margin: 0 auto; margin: 0 auto;
padding: 0 1rem; padding: 0 1rem;
display: flex; display: flex;

View File

@@ -1,10 +1,10 @@
import { ClerkProvider, useClerk } from "@clerk/clerk-react"; import { ClerkProvider, SignInButton, useClerk } from "@clerk/clerk-react";
import { createJazzReactApp } from "jazz-react";
import { useJazzClerkAuth } from "jazz-react-auth-clerk";
import { StrictMode } from "react"; import { StrictMode } from "react";
import { createRoot } from "react-dom/client"; import { createRoot } from "react-dom/client";
import App from "./App.tsx"; import App from "./App.tsx";
import "./index.css"; import "./index.css";
import { JazzProviderWithClerk } from "jazz-react-auth-clerk";
import { apiKey } from "./apiKey";
// Import your publishable key // Import your publishable key
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY; const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;
@@ -13,27 +13,38 @@ if (!PUBLISHABLE_KEY) {
throw new Error("Add your Clerk publishable key to the .env.local file"); throw new Error("Add your Clerk publishable key to the .env.local file");
} }
function JazzProvider({ children }: { children: React.ReactNode }) { const Jazz = createJazzReactApp();
export const { useAccount, useCoState } = Jazz;
function JazzAndAuth({ children }: { children: React.ReactNode }) {
const clerk = useClerk(); const clerk = useClerk();
const [auth, state] = useJazzClerkAuth(clerk);
return ( return (
<JazzProviderWithClerk <main className="container">
clerk={clerk} {state?.errors?.map((error) => (
sync={{ <div key={error}>{error}</div>
peer: `wss://cloud.jazz.tools/?key=${apiKey}`, ))}
}} {clerk.user && auth ? (
> <Jazz.Provider
{children} auth={auth}
</JazzProviderWithClerk> peer="wss://cloud.jazz.tools/?key=minimal-auth-clerk-example@garden.co"
>
{children}
</Jazz.Provider>
) : (
<SignInButton />
)}
</main>
); );
} }
createRoot(document.getElementById("root")!).render( createRoot(document.getElementById("root")!).render(
<StrictMode> <StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY} afterSignOutUrl="/"> <ClerkProvider publishableKey={PUBLISHABLE_KEY} afterSignOutUrl="/">
<JazzProvider> <JazzAndAuth>
<App /> <App />
</JazzProvider> </JazzAndAuth>
</ClerkProvider> </ClerkProvider>
</StrictMode>, </StrictMode>,
); );

View File

@@ -1,344 +1,5 @@
# file-share-svelte # file-share-svelte
## 0.0.52
### Patch Changes
- jazz-svelte@0.12.1
- jazz-tools@0.12.1
## 0.0.51
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- jazz-tools@0.12.0
- jazz-svelte@0.12.0
## 0.0.50
### Patch Changes
- jazz-svelte@0.11.8
- jazz-tools@0.11.8
## 0.0.49
### Patch Changes
- Updated dependencies [a140f55]
- Updated dependencies [2b0d1b0]
- jazz-tools@0.11.7
- jazz-svelte@0.11.7
## 0.0.48
### Patch Changes
- 1bfa9bb: Removed when="singedUp" from examples apps' Jazz providers. This is a really niche use-case option and can lead to broken-feeling experiences when anonymous users try to load something.
- Updated dependencies [e7c85b7]
- jazz-tools@0.11.6
- jazz-svelte@0.11.6
## 0.0.47
### Patch Changes
- jazz-svelte@0.11.5
- jazz-tools@0.11.5
## 0.0.46
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-svelte@0.11.4
## 0.0.45
### Patch Changes
- jazz-svelte@0.11.3
- jazz-tools@0.11.3
## 0.0.44
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-svelte@0.11.2
## 0.0.43
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-svelte@0.11.0
## 0.0.42
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-svelte@0.10.15
## 0.0.41
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-svelte@0.10.14
## 0.0.40
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-svelte@0.10.13
## 0.0.39
### Patch Changes
- Updated dependencies [4612e05]
- jazz-svelte@0.10.12
- jazz-tools@0.10.12
## 0.0.38
### Patch Changes
- jazz-svelte@0.10.9
## 0.0.37
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-svelte@0.10.8
## 0.0.36
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-svelte@0.10.7
- jazz-tools@0.10.7
## 0.0.35
### Patch Changes
- Updated dependencies [ada802b]
- jazz-tools@0.10.6
- jazz-svelte@0.10.6
## 0.0.34
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-svelte@0.10.5
## 0.0.33
### Patch Changes
- jazz-svelte@0.10.4
- jazz-tools@0.10.4
## 0.0.32
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-svelte@0.10.3
## 0.0.31
### Patch Changes
- jazz-svelte@0.10.2
- jazz-tools@0.10.2
## 0.0.30
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-svelte@0.10.1
## 0.0.29
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-tools@0.10.0
- jazz-svelte@0.10.0
## 0.0.28
### Patch Changes
- jazz-svelte@0.9.23
- jazz-tools@0.9.23
## 0.0.27
### Patch Changes
- jazz-svelte@0.9.22
## 0.0.26
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-svelte@0.9.21
## 0.0.25
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-svelte@0.9.20
## 0.0.24
### Patch Changes
- jazz-svelte@0.9.19
- jazz-tools@0.9.19
## 0.0.23
### Patch Changes
- jazz-svelte@0.9.18
- jazz-tools@0.9.18
## 0.0.22
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-svelte@0.9.17
## 0.0.21
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-tools@0.9.16
- jazz-svelte@0.9.16
## 0.0.20
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-svelte@0.9.15
## 0.0.19
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-svelte@0.9.14
## 0.0.18
### Patch Changes
- jazz-svelte@0.9.13
- jazz-tools@0.9.13
## 0.0.17
### Patch Changes
- jazz-svelte@0.9.12
- jazz-tools@0.9.12
## 0.0.16
### Patch Changes
- jazz-svelte@0.9.11
- jazz-tools@0.9.11
## 0.0.15
### Patch Changes
- Updated dependencies [5e83864]
- jazz-tools@0.9.10
- jazz-svelte@0.9.10
## 0.0.14
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-svelte@0.9.9
## 0.0.13
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-svelte@0.9.8
## 0.0.12
### Patch Changes
- Updated dependencies [1b71969]
- jazz-tools@0.9.1
- jazz-svelte@0.9.1
## 0.0.11
### Patch Changes
- Updated dependencies [9dd8d95]
- Updated dependencies [8eda792]
- jazz-svelte@0.9.0
- jazz-tools@0.9.0
## 0.0.10 ## 0.0.10
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "file-share-svelte", "name": "file-share-svelte",
"version": "0.0.52", "version": "0.0.10",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
@@ -13,13 +13,13 @@
"lint": "prettier --check . && eslint .", "lint": "prettier --check . && eslint .",
"format-and-lint": "pnpm run format && pnpm run lint", "format-and-lint": "pnpm run format && pnpm run lint",
"format-and-lint:fix": "pnpm run format --write && pnpm run lint --fix", "format-and-lint:fix": "pnpm run format --write && pnpm run lint --fix",
"test:e2e": "playwright test", "test": "playwright test",
"test:e2e:ui": "playwright test --ui" "test:ui": "playwright test --ui"
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-vercel": "^5.5.0", "@sveltejs/adapter-vercel": "^5.5.0",
"@sveltejs/kit": "^2.16.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0", "@sveltejs/vite-plugin-svelte": "^4.0.1",
"@types/is-ci": "^3.0.4", "@types/is-ci": "^3.0.4",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"eslint": "^9.7.0", "eslint": "^9.7.0",
@@ -32,10 +32,10 @@
"prettier-plugin-tailwindcss": "^0.6.5", "prettier-plugin-tailwindcss": "^0.6.5",
"svelte": "^5.0.0", "svelte": "^5.0.0",
"svelte-check": "^4.0.0", "svelte-check": "^4.0.0",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.15",
"typescript": "~5.6.2", "typescript": "~5.6.2",
"typescript-eslint": "^8.0.0", "typescript-eslint": "^8.0.0",
"vite": "^6.0.11" "vite": "^5.4.10"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/typography": "^0.5.15", "@tailwindcss/typography": "^0.5.15",

View File

@@ -1 +0,0 @@
export const apiKey = "file-share-svelte@garden.co"

View File

@@ -3,7 +3,7 @@
import { SharedFile } from '$lib/schema'; import { SharedFile } from '$lib/schema';
import { FileStream } from 'jazz-tools'; import { FileStream } from 'jazz-tools';
import { File, FileDown, Trash2, Link2 } from 'lucide-svelte'; import { File, FileDown, Trash2, Link2 } from 'lucide-svelte';
import { useAccount } from 'jazz-svelte'; import { useAccount } from '$lib/jazz';
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import { formatFileSize } from '$lib/utils'; import { formatFileSize } from '$lib/utils';

View File

@@ -0,0 +1,7 @@
import { createJazzApp } from 'jazz-svelte';
import { FileShareAccount } from './schema';
export const { useAccount, useCoState, useAcceptInvite, useAccountOrGuest, Provider } =
createJazzApp({
AccountSchema: FileShareAccount
});

View File

@@ -17,6 +17,6 @@ export function formatFileSize(bytes: number): string {
* @param createdAt The creation date * @param createdAt The creation date
* @returns A unique file ID string * @returns A unique file ID string
*/ */
export function generateTempFileId(fileName: string | undefined, createdAt: Date | undefined): string { export function generateTempFileId(fileName: string, createdAt: Date): string {
return `file-${fileName ?? 'unknown'}-${createdAt?.getTime() ?? 0}`; return `file-${fileName}-${createdAt.getTime()}`;
} }

View File

@@ -1,20 +1,13 @@
<script lang="ts" module>
declare module 'jazz-svelte' {
interface Register {
Account: FileShareAccount;
}
}
</script>
<script lang="ts"> <script lang="ts">
import { JazzProvider } from 'jazz-svelte'; import { Provider } from '$lib/jazz';
import { PasskeyAuthBasicUI, usePasskeyAuth } from 'jazz-svelte'; import { PasskeyAuthBasicUI, usePasskeyAuth } from 'jazz-svelte';
import { Toaster } from 'svelte-sonner'; import { Toaster } from 'svelte-sonner';
import '../app.css'; import '../app.css';
import { FileShareAccount } from '$lib/schema';
import {apiKey} from '../apiKey';
let { children } = $props(); let { children } = $props();
const auth = usePasskeyAuth({
appName: 'File Share'
});
</script> </script>
<svelte:head> <svelte:head>
@@ -23,15 +16,17 @@
<Toaster richColors /> <Toaster richColors />
<JazzProvider {#if auth.state.state === 'ready'}
AccountSchema={FileShareAccount} <div class="fixed inset-0 flex items-center justify-center bg-gray-50/80">
sync={{ <div class="rounded-lg bg-white p-8 shadow-lg">
peer: `wss://cloud.jazz.tools/?key=${apiKey}`, <PasskeyAuthBasicUI state={auth.state} />
}} </div>
> </div>
<PasskeyAuthBasicUI appName="File Share"> {/if}
{#if auth.current}
<Provider auth={auth.current} peer="wss://cloud.jazz.tools/?key=file-share-svelte@garden.co">
<div class="min-h-screen bg-gray-100"> <div class="min-h-screen bg-gray-100">
{@render children()} {@render children()}
</div> </div>
</PasskeyAuthBasicUI> </Provider>
</JazzProvider> {/if}

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { useAccount, useCoState } from 'jazz-svelte'; import { useAccount, useCoState } from '$lib/jazz';
import { SharedFile, ListOfSharedFiles } from '$lib/schema'; import { SharedFile, ListOfSharedFiles } from '$lib/schema';
import { createInviteLink } from 'jazz-svelte'; import { createInviteLink } from 'jazz-svelte';
import { FileStream } from 'jazz-tools'; import { FileStream } from 'jazz-tools';
@@ -28,7 +28,7 @@
const input = event.target as HTMLInputElement; const input = event.target as HTMLInputElement;
const files = input.files; const files = input.files;
if (!files || !files.length || !me.root?.sharedFiles || !me.root.publicGroup) return; if (!files || !files.length || !me?.root?.sharedFiles || !me.root.publicGroup) return;
const file = files[0]; const file = files[0];
const fileName = file.name; const fileName = file.name;
@@ -129,14 +129,12 @@
{#if sharedFiles.current} {#if sharedFiles.current}
{#if !(sharedFiles.current.length === 0 && uploadingFiles.size === 0)} {#if !(sharedFiles.current.length === 0 && uploadingFiles.size === 0)}
{#each [...sharedFiles.current, ...uploadingFiles.values()] as file (generateTempFileId(file?.name, file?.createdAt))} {#each [...sharedFiles.current, ...uploadingFiles.values()] as file (generateTempFileId(file?.name, file?.createdAt))}
{#if file} <FileItem
<FileItem {file}
{file} loading={uploadingFiles.has(generateTempFileId(file?.name, file?.createdAt))}
loading={uploadingFiles.has(generateTempFileId(file?.name, file?.createdAt))} onShare={shareFile}
onShare={shareFile} onDelete={deleteFile}
onDelete={deleteFile} />
/>
{/if}
{/each} {/each}
{:else} {:else}
<p class="text-center text-gray-500">No files yet</p> <p class="text-center text-gray-500">No files yet</p>

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { useAccount, useCoState } from 'jazz-svelte'; import { useAccount, useCoState } from '$lib/jazz';
import { SharedFile } from '$lib/schema'; import { SharedFile } from '$lib/schema';
import { File, FileDown, Link2 } from 'lucide-svelte'; import { File, FileDown, Link2 } from 'lucide-svelte';
import type { ID } from 'jazz-tools'; import type { ID } from 'jazz-tools';

View File

@@ -1,28 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
/test-results/
/playwright-report/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
playwright-report

View File

@@ -1,327 +0,0 @@
# jazz-tailwind-demo-auth-starter
## 0.0.8
### Patch Changes
- jazz-react@0.12.1
- jazz-tools@0.12.1
## 0.0.7
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- jazz-tools@0.12.0
- jazz-react@0.12.0
## 0.0.6
### Patch Changes
- jazz-react@0.11.8
- jazz-tools@0.11.8
## 0.0.5
### Patch Changes
- Updated dependencies [a140f55]
- Updated dependencies [4019918]
- Updated dependencies [2b0d1b0]
- jazz-tools@0.11.7
- jazz-react@0.11.7
## 0.0.4
### Patch Changes
- Updated dependencies [e7c85b7]
- jazz-react@0.11.6
- jazz-tools@0.11.6
## 0.0.3
### Patch Changes
- jazz-react@0.11.5
- jazz-tools@0.11.5
## 0.0.2
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-react@0.11.4
## 0.0.52
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-react@0.10.15
## 0.0.51
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
## 0.0.50
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-react@0.10.13
## 0.0.49
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-react@0.10.12
## 0.0.48
### Patch Changes
- jazz-react@0.10.9
## 0.0.47
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-react@0.10.8
## 0.0.46
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-react@0.10.7
- jazz-tools@0.10.7
## 0.0.45
### Patch Changes
- Updated dependencies [1d71ca1]
- Updated dependencies [ada802b]
- jazz-react@0.10.6
- jazz-tools@0.10.6
## 0.0.44
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-react@0.10.5
## 0.0.43
### Patch Changes
- jazz-react@0.10.4
- jazz-tools@0.10.4
## 0.0.42
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-react@0.10.3
## 0.0.41
### Patch Changes
- jazz-react@0.10.2
- jazz-tools@0.10.2
## 0.0.40
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-react@0.10.1
## 0.0.39
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-react@0.10.0
- jazz-tools@0.10.0
## 0.0.38
### Patch Changes
- jazz-react@0.9.23
- jazz-tools@0.9.23
## 0.0.37
### Patch Changes
- jazz-react@0.9.22
## 0.0.36
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-react@0.9.21
## 0.0.35
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-react@0.9.20
## 0.0.34
### Patch Changes
- jazz-react@0.9.19
- jazz-tools@0.9.19
## 0.0.33
### Patch Changes
- jazz-react@0.9.18
- jazz-tools@0.9.18
## 0.0.32
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-react@0.9.17
## 0.0.31
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-tools@0.9.16
- jazz-react@0.9.16
## 0.0.30
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-react@0.9.15
## 0.0.29
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-react@0.9.14
## 0.0.28
### Patch Changes
- jazz-react@0.9.13
- jazz-tools@0.9.13
## 0.0.27
### Patch Changes
- jazz-react@0.9.12
- jazz-tools@0.9.12
## 0.0.26
### Patch Changes
- jazz-react@0.9.11
- jazz-tools@0.9.11
## 0.0.25
### Patch Changes
- Updated dependencies [5e83864]
- jazz-react@0.9.10
- jazz-tools@0.9.10
## 0.0.24
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-react@0.9.9
## 0.0.23
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
## 0.0.22
### Patch Changes
- jazz-react@0.9.4
## 0.0.21
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
## 0.0.20
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
## 0.0.19
### Patch Changes
- Updated dependencies [dc62b95]
- Updated dependencies [1de26f8]
- jazz-tools@0.8.51
- jazz-react@0.8.51

View File

@@ -1,66 +0,0 @@
# File upload example with Jazz and React
This is an example of how to upload and render images with Jazz.
Live version: https://file-upload-demo.jazz.tools
## Getting started
You can either
1. Clone the jazz repository, and run the app within the monorepo.
2. Or create a new Jazz project using this example as a template.
### Using the example as a template
Create a new Jazz project, and use this example as a template.
```bash
npx create-jazz-app@latest --example file-upload --project-name file-upload
```
Go to the new project directory.
```bash
cd file-upload
```
Run the dev server.
```bash
npm run dev
```
### Using the monorepo
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
Clone the jazz repository.
```bash
git clone https://github.com/garden-co/jazz.git
```
Install and build dependencies.
```bash
pnpm i && npx turbo build
```
Go to the example directory.
```bash
cd jazz/examples/file-upload/
```
Start the dev server.
```bash
pnpm dev
```
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
## Questions / problems / feedback
If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong.
## Configuration: sync server
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of `JazzProvider` component in [./src/main.tsx](./src/main.tsx).

View File

@@ -1,37 +0,0 @@
import { FileWidget } from "./FileWidget.js";
import { Logo } from "./Logo.tsx";
function App() {
return (
<>
<main className="container mt-16 flex flex-col gap-8">
<Logo />
<FileWidget />
<p className="text-center">
Edit the form above,{" "}
<button
type="button"
onClick={() => window.location.reload()}
className="font-semibold underline"
>
refresh
</button>{" "}
this page, and see your changes persist.
</p>
<p className="text-center my-16">
Go to{" "}
<a
className="font-semibold underline"
href="https://jazz.tools/docs/react/guide"
>
jazz.tools/docs/react/guide
</a>{" "}
for a full tutorial.
</p>
</main>
</>
);
}
export default App;

View File

@@ -1,269 +0,0 @@
"use client";
import { useAccount } from "jazz-react";
import { FileStream } from "jazz-tools";
import { useRef, useState } from "react";
export function FileWidget() {
const inputRef = useRef<HTMLInputElement>(null);
const dragAndDropElementRef = useRef<HTMLDivElement>(null);
const [isUploading, setIsUploading] = useState(false);
const [progress, setProgress] = useState(0);
const [error, setError] = useState<string | null>(null);
const { me } = useAccount();
async function handleUpload(event: React.FormEvent) {
event.preventDefault();
setError(null);
if (!me?.profile) {
setError("User profile not found");
return;
}
setProgress(0);
const file = inputRef.current?.files?.[0];
if (!file) {
setError("Please select a file");
return;
}
try {
setIsUploading(true);
me.profile.file = await FileStream.createFromBlob(file, {
onProgress: (p) => setProgress(Math.round(p * 100)),
});
} catch (error) {
setError(
error instanceof Error ? error.message : "Failed to upload file",
);
console.error("Error uploading file:", error);
} finally {
setIsUploading(false);
}
}
function handleDelete() {
if (!me?.profile) return;
delete me.profile?.file;
}
async function handleDownload() {
if (!me?.profile) return;
const file = me.profile.file;
if (!file) return;
try {
const blob = file.toBlob();
const url = URL.createObjectURL(blob || new Blob());
const a = document.createElement("a");
a.href = url;
a.download = file.id || "download";
a.click();
URL.revokeObjectURL(url);
} catch (error) {
console.error("Error downloading file:", error);
}
}
function formatFileSize(bytes?: number): string {
if (!bytes) return "0 Bytes";
const k = 1024;
const sizes = ["Bytes", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
}
const onDragEnter = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-stone-400",
"border-blue-700",
);
};
const onDragOver = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-stone-400",
"border-blue-700",
);
};
const onDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-blue-700",
"border-stone-400",
);
};
const onDrop = async (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
dragAndDropElementRef?.current?.classList.replace(
"border-blue-700",
"border-stone-400",
);
if (!me?.profile) {
setError("User profile not found");
return;
}
const droppedFiles = e.dataTransfer.files;
if (!droppedFiles || droppedFiles.length === 0) {
return;
}
const file = droppedFiles[0];
setProgress(0);
try {
setIsUploading(true);
me.profile.file = await FileStream.createFromBlob(file, {
onProgress: (p) => setProgress(Math.round(p * 100)),
});
} catch (error) {
setError(
error instanceof Error ? error.message : "Failed to upload file",
);
console.error("Error uploading file:", error);
} finally {
setIsUploading(false);
}
};
if (me?.profile?.file == null) {
return (
<div className="flex flex-col gap-4">
<div
className="flex flex-col border-2 border-dashed border-stone-400 h-48 items-center justify-center bg-stone-100 m-5 rounded-md"
ref={dragAndDropElementRef}
onDragEnter={onDragEnter}
onDragOver={onDragOver}
onDragLeave={onDragLeave}
onDrop={onDrop}
>
<p>Drag & drop your file here</p>
</div>
<form onSubmit={handleUpload} className="flex gap-2">
<input
className="bg-stone-100 py-1.5 px-2 text-sm rounded-md w-4/5"
ref={inputRef}
type="file"
accept="file"
onChange={() => setError(null)}
disabled={isUploading}
/>
<button
type="submit"
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md disabled:opacity-50"
disabled={isUploading}
>
{isUploading ? `Uploading...` : "Upload file"}
</button>
</form>
{error && (
<div className="text-red-800 text-sm pl-4" role="alert">
{error}
</div>
)}
{isUploading && (
<div className="flex gap-2 items-center">
<div className="py-1.5 px-3 text-sm">Progress: {progress}%</div>
<div className="h-2 bg-stone-200 rounded-full flex-1">
<div
className="h-full bg-blue-500 rounded-full transition-all duration-300"
style={{ width: `${progress}%` }}
/>
</div>
</div>
)}
</div>
);
}
const fileData = me?.profile?.file?.getChunks();
const mimeType = fileData?.mimeType || "unknown";
return (
<div className="gap-2">
<div className="p-4">
<div className="space-y-2">
<div className="flex justify-between">
<span className="font-bold">File name</span>
<span>{fileData?.fileName}</span>
</div>
<div className="flex justify-between">
<span className="font-bold">Type</span>
<span>{mimeType}</span>
</div>
<div className="flex justify-between">
<span className="font-bold">Size</span>
<span>{formatFileSize(fileData?.totalSizeBytes)}</span>
</div>
</div>
</div>
<div className="flex gap-2 justify-end">
<button
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md"
onClick={handleDelete}
>
Delete file
</button>
<button
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md"
onClick={handleDownload}
>
Download file
</button>
</div>
<div className="w-full justify-center pt-8">
{fileData?.mimeType?.startsWith("image/") && (
<div className="flex justify-center">
<img
src={URL.createObjectURL(
me?.profile?.file?.toBlob() || new Blob(),
)}
alt="File preview"
className="max-w-xs mb-4"
/>
</div>
)}
{fileData?.mimeType?.startsWith("audio/") && (
<div className="flex justify-center">
<audio
src={URL.createObjectURL(
me?.profile?.file?.toBlob() || new Blob(),
)}
controls
className="w-full mb-4"
/>
</div>
)}
{fileData?.mimeType?.startsWith("video/") && (
<div className="flex justify-center">
<video
src={URL.createObjectURL(
me?.profile?.file?.toBlob() || new Blob(),
)}
controls
className="w-full mb-4"
/>
</div>
)}
</div>
</div>
);
}

View File

@@ -1 +0,0 @@
export const apiKey = "filestream-example-jazz@garden.co";

View File

@@ -1,29 +0,0 @@
import { JazzProvider } from "jazz-react";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import { apiKey } from "./apiKey.ts";
import "./index.css";
import { JazzAccount } from "./schema.ts";
// We use this to identify the app in the passkey auth
export const APPLICATION_NAME = "Jazz File Stream Example";
declare module "jazz-react" {
export interface Register {
Account: JazzAccount;
}
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<JazzProvider
sync={{
peer: `wss://cloud.jazz.tools/?key=${apiKey}`,
}}
AccountSchema={JazzAccount}
>
<App />
</JazzProvider>
</StrictMode>,
);

View File

@@ -1,14 +0,0 @@
import { Account, FileStream, Profile, co } from "jazz-tools";
export class JazzProfile extends Profile {
file = co.ref(FileStream, { optional: true });
}
export class JazzAccount extends Account {
profile = co.ref(JazzProfile);
/** The account migration is run on account creation and on every log-in.
* You can use it to set up the account root and any other initial CoValues you need.
*/
migrate(this: JazzAccount) {}
}

View File

@@ -1,9 +0,0 @@
import { expect, test } from "@playwright/test";
test("home page loads", async ({ page }) => {
await page.goto("/");
await expect(page.getByText("Welcome!")).toBeVisible();
await page.getByLabel("Name").fill("Bob");
await expect(page.getByText("Welcome, Bob!")).toBeVisible();
});

View File

@@ -1,401 +1,5 @@
# form # form
## 0.1.10
### Patch Changes
- jazz-react@0.12.1
- jazz-tools@0.12.1
## 0.1.9
### Patch Changes
- Updated dependencies [01523dc]
- Updated dependencies [4ea87dc]
- Updated dependencies [1e6da19]
- Updated dependencies [b6c6a0a]
- jazz-tools@0.12.0
- jazz-react@0.12.0
## 0.1.8
### Patch Changes
- jazz-react@0.11.8
- jazz-tools@0.11.8
## 0.1.7
### Patch Changes
- Updated dependencies [a140f55]
- Updated dependencies [4019918]
- Updated dependencies [2b0d1b0]
- jazz-tools@0.11.7
- jazz-react@0.11.7
## 0.1.6
### Patch Changes
- Updated dependencies [e7c85b7]
- Updated dependencies [8ed144e]
- jazz-react@0.11.6
- jazz-tools@0.11.6
- jazz-browser-media-images@0.11.6
## 0.1.5
### Patch Changes
- jazz-react@0.11.5
- jazz-tools@0.11.5
- jazz-browser-media-images@0.11.5
## 0.1.4
### Patch Changes
- Updated dependencies [57a3dbe]
- Updated dependencies [a717754]
- Updated dependencies [a91f343]
- jazz-tools@0.11.4
- jazz-browser-media-images@0.11.4
- jazz-react@0.11.4
## 0.1.3
### Patch Changes
- jazz-react@0.11.3
- jazz-tools@0.11.3
- jazz-browser-media-images@0.11.3
## 0.1.2
### Patch Changes
- Updated dependencies [6892dc6]
- jazz-tools@0.11.2
- jazz-react@0.11.2
- jazz-browser-media-images@0.11.2
## 0.1.1
### Patch Changes
- jazz-react@0.11.1
## 0.1.0
### Minor Changes
- 18428ea: PasskeyAuth: Sets `profile.name` only if a non-empty username is passed to `signUp`
### Patch Changes
- Updated dependencies [6a96d8b]
- Updated dependencies [a35249a]
- Updated dependencies [b9d194a]
- Updated dependencies [a4713df]
- Updated dependencies [34cbdc3]
- Updated dependencies [f039e8f]
- Updated dependencies [e22de9f]
- jazz-tools@0.11.0
- jazz-browser-media-images@0.11.0
- jazz-react@0.11.0
## 0.0.53
### Patch Changes
- Updated dependencies [2f99de0]
- jazz-tools@0.10.15
- jazz-browser-media-images@0.10.15
- jazz-react@0.10.15
## 0.0.52
### Patch Changes
- Updated dependencies [75211e3]
- jazz-tools@0.10.14
- jazz-react@0.10.14
- jazz-browser-media-images@0.10.14
## 0.0.51
### Patch Changes
- Updated dependencies [07feedd]
- jazz-tools@0.10.13
- jazz-browser-media-images@0.10.13
- jazz-react@0.10.13
## 0.0.50
### Patch Changes
- Updated dependencies [4612e05]
- jazz-tools@0.10.12
- jazz-react@0.10.12
- jazz-browser-media-images@0.10.12
## 0.0.49
### Patch Changes
- jazz-browser-media-images@0.10.9
- jazz-react@0.10.9
## 0.0.48
### Patch Changes
- Updated dependencies [2fb6428]
- jazz-tools@0.10.8
- jazz-react@0.10.8
- jazz-browser-media-images@0.10.8
## 0.0.47
### Patch Changes
- Updated dependencies [1136d9b]
- Updated dependencies [0eed228]
- jazz-react@0.10.7
- jazz-tools@0.10.7
- jazz-browser-media-images@0.10.7
## 0.0.46
### Patch Changes
- Updated dependencies [1d71ca1]
- Updated dependencies [ada802b]
- hash-slash@0.2.2
- jazz-react@0.10.6
- jazz-tools@0.10.6
- jazz-browser-media-images@0.10.6
## 0.0.45
### Patch Changes
- Updated dependencies [59ff77e]
- jazz-tools@0.10.5
- jazz-browser-media-images@0.10.5
- jazz-react@0.10.5
## 0.0.44
### Patch Changes
- jazz-react@0.10.4
- jazz-tools@0.10.4
- jazz-browser-media-images@0.10.4
## 0.0.43
### Patch Changes
- Updated dependencies [d8582fc]
- jazz-tools@0.10.3
- jazz-browser-media-images@0.10.3
- jazz-react@0.10.3
## 0.0.42
### Patch Changes
- jazz-react@0.10.2
- jazz-tools@0.10.2
- jazz-browser-media-images@0.10.2
## 0.0.41
### Patch Changes
- Updated dependencies [5a63cba]
- jazz-tools@0.10.1
- jazz-browser-media-images@0.10.1
- jazz-react@0.10.1
## 0.0.40
### Patch Changes
- Updated dependencies [498954f]
- Updated dependencies [d42c2aa]
- Updated dependencies [dd03464]
- Updated dependencies [b426342]
- jazz-react@0.10.0
- jazz-tools@0.10.0
- jazz-browser-media-images@0.10.0
## 0.0.39
### Patch Changes
- jazz-react@0.9.23
- jazz-tools@0.9.23
- jazz-browser-media-images@0.9.23
## 0.0.38
### Patch Changes
- jazz-browser-media-images@0.9.22
- jazz-react@0.9.22
## 0.0.37
### Patch Changes
- Updated dependencies [1be017d]
- jazz-tools@0.9.21
- jazz-browser-media-images@0.9.21
- jazz-react@0.9.21
## 0.0.36
### Patch Changes
- Updated dependencies [b01cc1f]
- jazz-tools@0.9.20
- jazz-browser-media-images@0.9.20
- jazz-react@0.9.20
## 0.0.35
### Patch Changes
- jazz-react@0.9.19
- jazz-tools@0.9.19
- jazz-browser-media-images@0.9.19
## 0.0.34
### Patch Changes
- jazz-react@0.9.18
- jazz-tools@0.9.18
- jazz-browser-media-images@0.9.18
## 0.0.33
### Patch Changes
- Updated dependencies [c2ca1fe]
- Updated dependencies [1227047]
- jazz-tools@0.9.17
- jazz-browser-media-images@0.9.17
- jazz-react@0.9.17
## 0.0.32
### Patch Changes
- Updated dependencies [24b3b6a]
- jazz-tools@0.9.16
- jazz-browser-media-images@0.9.16
- jazz-react@0.9.16
## 0.0.31
### Patch Changes
- Updated dependencies [7491711]
- jazz-tools@0.9.15
- jazz-browser-media-images@0.9.15
- jazz-react@0.9.15
## 0.0.30
### Patch Changes
- Updated dependencies [3df93cc]
- jazz-tools@0.9.14
- jazz-browser-media-images@0.9.14
- jazz-react@0.9.14
## 0.0.29
### Patch Changes
- jazz-react@0.9.13
- jazz-tools@0.9.13
- jazz-browser-media-images@0.9.13
## 0.0.28
### Patch Changes
- jazz-react@0.9.12
- jazz-tools@0.9.12
- jazz-browser-media-images@0.9.12
## 0.0.27
### Patch Changes
- jazz-react@0.9.11
- jazz-tools@0.9.11
- jazz-browser-media-images@0.9.11
## 0.0.26
### Patch Changes
- Updated dependencies [5e83864]
- jazz-react@0.9.10
- jazz-tools@0.9.10
- jazz-browser-media-images@0.9.10
## 0.0.25
### Patch Changes
- Updated dependencies [8eb9247]
- jazz-tools@0.9.9
- jazz-browser-media-images@0.9.9
- jazz-react@0.9.9
## 0.0.24
### Patch Changes
- Updated dependencies [d1d773b]
- jazz-tools@0.9.8
- jazz-react@0.9.8
- jazz-browser-media-images@0.9.8
## 0.0.23
### Patch Changes
- jazz-react@0.9.4
## 0.0.22
### Patch Changes
- Updated dependencies [1b71969]
- jazz-react@0.9.1
- jazz-tools@0.9.1
- jazz-browser-media-images@0.9.1
## 0.0.21
### Patch Changes
- Updated dependencies [956a4d1]
- Updated dependencies [8eda792]
- jazz-react@0.9.0
- jazz-tools@0.9.0
- jazz-browser-media-images@0.9.0
## 0.0.20 ## 0.0.20
### Patch Changes ### Patch Changes

View File

@@ -17,56 +17,30 @@ converting it into a `BubbleTeaOrder`.
[See the full guide here.](https://jazz.tools/docs/react/design-patterns/form) [See the full guide here.](https://jazz.tools/docs/react/design-patterns/form)
## Getting started ## Installing & running the example locally
You can either (This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation))
1. Clone the jazz repository, and run the app within the monorepo.
2. Or create a new Jazz project using this example as a template.
Start by downloading the [jazz repository](https://github.com/garden-co/jazz):
### Using the example as a template
Create a new Jazz project, and use this example as a template.
```bash ```bash
npx create-jazz-app@latest form-app --example form npx degit gardencmp/jazz jazz
``` ```
Go to the new project directory. Go to the form example directory:
```bash ```bash
cd form-app cd jazz/examples/form
``` ```
Run the dev server. Install and build dependencies:
```bash
npm run dev
```
### Using the monorepo
This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation).
Clone the jazz repository.
```bash
git clone https://github.com/garden-co/jazz.git
```
Install and build dependencies.
```bash ```bash
pnpm i && npx turbo build pnpm i && npx turbo build
``` ```
Go to the example directory. Start the dev server:
```bash
cd jazz/examples/form/
```
Start the dev server.
```bash ```bash
pnpm dev pnpm dev
``` ```
Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
## Questions / problems / feedback ## Questions / problems / feedback
If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong. If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or open an issue or PR to fix something that seems wrong.
@@ -75,4 +49,4 @@ If you have feedback, let us know on [Discord](https://discord.gg/utDMjHYg42) or
By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work. By default, the example app uses [Jazz Cloud](https://jazz.tools/cloud) (`wss://cloud.jazz.tools`) - so cross-device use, invites and collaboration should just work.
You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<JazzProvider>` provider component in [./src/main.tsx](./src/main.tsx). You can also run a local sync server by running `npx jazz-run sync` and adding the query param `?sync=ws://localhost:4200` to the URL of the example app (for example: `http://localhost:5173/?peer=ws://localhost:4200`), or by setting the `sync` parameter of the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).

Some files were not shown because too many files have changed in this diff Show More