Compare commits

...

355 Commits

Author SHA1 Message Date
Guido D'Orsi
5d20c81ed5 feat: Add an API to disable the permission errors logs 2024-12-19 13:08:03 +01:00
pax-k
3accbc06e2 chore: add build step to release workflow (debug) 2024-12-18 21:58:25 +02:00
pax-k
39ae4fc8c1 chore: enable tmate debugging on gh workflow failure 2024-12-18 21:13:01 +02:00
Guido D'Orsi
ae60eb0d01 Merge pull request #1050 from garden-co/fix/remove-local-server-e2e
test(e2e): run tests against our cloud
2024-12-18 17:09:29 +01:00
Guido D'Orsi
05eb330173 Merge pull request #1019 from garden-co/form-example-test
Add test for form example
2024-12-18 16:36:03 +01:00
Guido D'Orsi
5d1e192245 test(e2e): run tests against our cloud 2024-12-18 16:34:59 +01:00
Anselm Eickhoff
c5e059b3a9 Merge pull request #1048 from garden-co/docs/org-design-pattern
Add organization design pattern to docs
2024-12-18 15:24:37 +00:00
Trisha Lim
d1785c0178 Address feedback 2024-12-18 15:14:12 +00:00
pax
9b95c32edb Merge pull request #1049 from garden-co/changeset-release/main
Version Packages
2024-12-18 17:08:52 +02:00
github-actions[bot]
d87781d33f Version Packages 2024-12-18 15:04:52 +00:00
pax
ad50ec2d9d Merge pull request #1047 from garden-co/create-jazz-app
create-jazz-app
2024-12-18 17:03:50 +02:00
Trisha Lim
fef055b9fb Add organization design pattern to docs 2024-12-18 14:20:10 +00:00
pax-k
cdc7f9f841 chore: changeset 2024-12-18 14:56:28 +02:00
pax-k
ff6940de56 chore: bumped jazz-react-native-auth-clerk 2024-12-18 14:52:44 +02:00
pax-k
cad54e4018 chore: upgraded nativewind to 4.x 2024-12-18 14:52:31 +02:00
pax-k
c657880a22 chore: small adjustments 2024-12-18 14:51:54 +02:00
pax-k
79b02dee3c chore: added readme for create-jazz-app 2024-12-18 14:51:35 +02:00
pax-k
ee29cb300c chore: changeset 2024-12-18 13:38:20 +02:00
pax-k
36f0ab7571 Merge branch 'main' into create-jazz-app 2024-12-18 13:00:53 +02:00
pax-k
829be3cafa chore: cleanup 2024-12-18 13:00:32 +02:00
Guido D'Orsi
7c322796aa fix: exclude tests from build 2024-12-18 12:00:18 +01:00
pax-k
36d50d96dd feat: create-jazz-app command 2024-12-18 12:59:58 +02:00
Guido D'Orsi
1fd26b9d05 Merge pull request #1038 from garden-co/changeset-release/main
Version Packages
2024-12-18 11:54:35 +01:00
github-actions[bot]
40f161d4d0 Version Packages 2024-12-18 10:52:20 +00:00
Anselm Eickhoff
655a601a8e Merge pull request #991 from garden-co/jazz-91-writer-only-permission-kind
feat: add writeOnly role on groups
2024-12-18 10:50:04 +00:00
Anselm Eickhoff
c7a28e5003 Merge pull request #1029 from garden-co/feat/icon-component
Create Icon component for consistent icons
2024-12-18 10:49:28 +00:00
Anselm Eickhoff
ae429d0a1c Merge pull request #1034 from garden-co/feat/incremental-transactions
perf: incremental computation on transactions
2024-12-18 10:46:51 +00:00
Guido D'Orsi
26c390be66 fix(rn-e2e): fix app name 2024-12-18 11:40:46 +01:00
pax
a0a0962f28 Merge pull request #1044 from garden-co/ignore-homepage-build
Skip unnecessary Vercel builds if only docs are changed
2024-12-17 16:14:38 +02:00
Guido D'Orsi
32834ef9e3 chore: improve doc comment
Co-authored-by: Anselm Eickhoff <anselm.eickhoff@gmail.com>
2024-12-17 12:06:04 +01:00
Trisha Lim
13be2a3235 Use Icon component in onboarding example thumbnail 2024-12-17 09:39:42 +00:00
Trisha Lim
7fa6e4333d Create Icon component for consistent icon sizes 2024-12-17 09:35:44 +00:00
pax-k
093f08b5e0 chore: renamed vercel build checking script 2024-12-16 22:00:50 +02:00
pax-k
f374545692 chore: rename script 2024-12-16 21:58:54 +02:00
pax-k
9a8f2747fe chore: added vercel.json for example apps 2024-12-16 21:49:30 +02:00
pax-k
84b7c9ab89 chore: test script 2024-12-16 21:10:59 +02:00
pax-k
3863d834ce fix: added vercel.json for homepage 2024-12-16 21:09:56 +02:00
pax-k
4c860075ee fix: tweaked ignore-build.js 2024-12-16 21:01:57 +02:00
pax-k
79480ddf0c chore: moved ignore-build.js to root 2024-12-16 20:47:14 +02:00
pax-k
8d447b8725 chore: test ignore build script 2024-12-16 20:18:02 +02:00
pax-k
238fd47089 fix: use ES modules instead of CommonJS 2024-12-16 20:13:36 +02:00
pax-k
29ac1fbe88 feat: ignore homepage build if "docs" not found in branch name 2024-12-16 20:11:26 +02:00
Anselm
95fd27d3e3 Fix doc typo 2024-12-16 17:22:07 +00:00
Anselm Eickhoff
533d7684c9 Merge pull request #1042 from garden-co/docs-getting-group-of-covalues
Document Getting the Group of an existing CoValue
2024-12-16 17:14:14 +00:00
Anselm
798403a57d Document Getting the Group of an existing CoValue 2024-12-16 17:07:48 +00:00
Anselm
ddf060e64c Improve docs: talk about casting to ID<Account> 2024-12-16 16:58:38 +00:00
Anselm Eickhoff
51515f629c Merge pull request #1041 from garden-co/docs-adding-group-members-by-id
Document how to add Group members by ID
2024-12-16 16:43:13 +00:00
Anselm
65e012f401 Document how to add Group members by ID 2024-12-16 16:38:43 +00:00
Trisha Lim
a1ba29fd47 Add onboarding to examples page 2024-12-16 15:34:19 +00:00
Trisha Lim
b6b76ab2b9 Fix: form does not submit on Enter key press 2024-12-16 15:34:19 +00:00
Guido D'Orsi
77dbd4e205 fix: keep the cachedContent if processNewTransactions is supported 2024-12-16 12:50:03 +01:00
Guido D'Orsi
baa8aff33f Merge pull request #1037 from garden-co/gio/chore/otel-peer-dep
chore(cojson): add @opentlementry/api as a dependency
2024-12-16 10:57:24 +01:00
Giordano Ricci
63703489ab chore(cojson): add @opentlementry/api as a dependency 2024-12-16 09:48:10 +00:00
Guido D'Orsi
325250272b chore: changeset 2024-12-16 10:09:10 +01:00
Guido D'Orsi
219ba975a5 pref(CoMap): lazy computation of the values when doing time travel 2024-12-14 22:52:24 +01:00
Guido D'Orsi
f5a3394d40 perf: improve incemental computation 2024-12-14 21:25:55 +01:00
Guido D'Orsi
4a5209237f perf(coStream): process transactions incrementally 2024-12-14 21:25:55 +01:00
Guido D'Orsi
d7eb50abc1 perf(coMap): process transactions incrementally 2024-12-14 21:25:55 +01:00
Anselm Eickhoff
4908d7cfd3 Merge pull request #1033 from garden-co/changeset-release/main
Version Packages
2024-12-14 17:26:15 +00:00
github-actions[bot]
38b19ab980 Version Packages 2024-12-14 17:22:26 +00:00
Anselm Eickhoff
9e2486c332 Merge pull request #1032 from garden-co/jazz-594-send-content-from-storage-peers-in-one-message-instead-of
Send content from storage peers in one message instead of streaming it
2024-12-14 17:20:46 +00:00
Anselm
e905c84a34 Send content from storage peers in one message instead of streaming it 2024-12-14 17:14:04 +00:00
Trisha Lim
b097c38617 Test draft indicator 2024-12-13 18:20:59 +00:00
Trisha Lim
385dfc89ff Add test to CI 2024-12-13 18:08:31 +00:00
Trisha Lim
d89e4c3412 Test order editing 2024-12-13 18:05:12 +00:00
Trisha Lim
bbeee086ce Test order creation 2024-12-13 17:59:05 +00:00
Trisha Lim
718e9418e2 Set up playwright on form example 2024-12-13 17:34:48 +00:00
Guido D'Orsi
507a00fe6a Merge pull request #1016 from garden-co/fix-depencencies
fix: run sherif to align all the packages/examples dependencies
2024-12-13 15:13:09 +01:00
Guido D'Orsi
8e940130d2 fix: run sherif to aling all the packages/examples dependencies 2024-12-13 15:05:23 +01:00
Guido D'Orsi
ac216b9f2e chore: changeset 2024-12-13 13:19:24 +01:00
Guido D'Orsi
93230df2cb test: add some tests for the writeOnly role and the inheritance 2024-12-13 13:19:24 +01:00
Guido D'Orsi
c13daa140b chore: add comments 2024-12-13 13:19:24 +01:00
Guido D'Orsi
3c9439d0cc chore: rename getCurrentKeyReadId into getCurrentReadKeyId 2024-12-13 13:19:24 +01:00
Guido D'Orsi
d38d4928c7 test: add e2e tests for the writeOnly role 2024-12-13 13:19:24 +01:00
Guido D'Orsi
596901cba6 fix: add writeOnly to createInvite types 2024-12-13 13:19:24 +01:00
Guido D'Orsi
2a1fda3758 feat: add writeOnly role on groups 2024-12-13 13:19:24 +01:00
Trisha Lim
f3581d1086 Fix form example build 2024-12-13 12:17:25 +00:00
Guido D'Orsi
4ac2b75194 Merge pull request #1014 from garden-co/migrate-taiwind-config
fix: migrate tailwind configs to typescript
2024-12-13 13:17:15 +01:00
Guido D'Orsi
cfa78ed628 fix(form): restore palette and add ts-ignore to the vite config 2024-12-13 13:12:49 +01:00
Guido D'Orsi
94095aff28 fix(ci): build only packages on the unit test workflow 2024-12-13 13:09:57 +01:00
Guido D'Orsi
a70f7a4c49 fix: migrate tailwind configs to typescript 2024-12-13 13:09:20 +01:00
Trisha Lim
2270ae113e Fix link typo 2024-12-13 11:54:32 +00:00
Benjamin S. Leveritt
92b64e05ca Add comment about public visibility on profile content 2024-12-13 11:54:32 +00:00
Benjamin S. Leveritt
cb6b9af57d Improve guide 2024-12-13 11:54:32 +00:00
Benjamin S. Leveritt
fc00369d87 Add initial project guide 2024-12-13 11:54:32 +00:00
Anselm Eickhoff
0b260f339d Merge pull request #993 from garden-co/jazz-549-add-forms-example
Add form example for creating and updating
2024-12-13 11:54:11 +00:00
Trisha Lim
8f50dd48f6 Show errors on page 2024-12-13 11:50:43 +00:00
Anselm Eickhoff
d3af4fecd1 Merge pull request #1012 from garden-co/jazz-582-officially-support-svelte
Officially support svelte
2024-12-13 11:32:07 +00:00
Guido D'Orsi
4ec13a9515 Merge pull request #999 from garden-co/changeset-release/main
Version Packages
2024-12-13 12:22:40 +01:00
Trisha Lim
79262351fa Icon stroke width 2024-12-13 11:05:43 +00:00
Trisha Lim
01292230e8 Add validation 2024-12-13 10:49:26 +00:00
github-actions[bot]
9b31d3241d Version Packages 2024-12-12 17:37:39 +00:00
Anselm Eickhoff
77dfd4f883 Merge pull request #1011 from garden-co/fix/import-extensions-linting
fix: enable linting for import extensions on packages
2024-12-12 17:36:16 +00:00
Trisha Lim
9150c238e4 Add feature tags to file share example 2024-12-12 17:33:35 +00:00
Trisha Lim
67bd5ab07f Update file share icon 2024-12-12 17:25:04 +00:00
Trisha Lim
2678c83a99 Add Svelte passkey example app to examples page 2024-12-12 17:22:03 +00:00
Trisha Lim
4c1364a5cb Add Svelte file share example app to examples page 2024-12-12 17:20:16 +00:00
Trisha Lim
f546811a23 Add Svelte under supported environments 2024-12-12 17:10:32 +00:00
Guido D'Orsi
eb9164633c fix: enable linting for import extensions on packages 2024-12-12 18:02:02 +01:00
Trisha Lim
db5e5d8392 Add form example to examples page 2024-12-12 16:26:56 +00:00
Trisha Lim
a18d870faa Update lock file 2024-12-12 15:16:02 +00:00
Trisha Lim
d434b23a34 Layout fix 2024-12-12 15:14:18 +00:00
Trisha Lim
dd363d613f Add readme description 2024-12-12 15:14:18 +00:00
Trisha Lim
9d41f7a16a Orders empty screen 2024-12-12 15:14:18 +00:00
Trisha Lim
dfddc3603a Set default values 2024-12-12 15:14:18 +00:00
Trisha Lim
5c09f0f41a Style strong tag 2024-12-12 15:12:59 +00:00
Trisha Lim
139fcbe172 Add draft indicator 2024-12-12 15:12:59 +00:00
Trisha Lim
507b3b890a Form styling 2024-12-12 15:11:08 +00:00
Trisha Lim
06ad39c418 Order thumbnail styling 2024-12-12 15:10:59 +00:00
Trisha Lim
7077a41c2d Make addons checkbox work 2024-12-12 15:10:59 +00:00
Trisha Lim
9572729cc9 Remove unused 2024-12-12 15:10:59 +00:00
Trisha Lim
9f08ca8cd8 Save draft as an order 2024-12-12 15:10:59 +00:00
Trisha Lim
8e0bf8a8d8 Replace drafts array with a single draft 2024-12-12 15:10:59 +00:00
Trisha Lim
5b72d1f89b Show drafts in home 2024-12-12 15:10:59 +00:00
Trisha Lim
e10d09e6ab Add order draft to schema 2024-12-12 15:10:59 +00:00
Trisha Lim
2007815745 Do not use react-hook-form 2024-12-12 15:10:59 +00:00
Trisha Lim
1f826734d4 Create Order form using react-form-hook 2024-12-12 15:10:59 +00:00
Trisha Lim
80383dac3b Create form example project 2024-12-12 15:09:20 +00:00
Guido D'Orsi
b9ed9e3f13 Merge pull request #994 from garden-co/jazz-493-wait-for-stuff-to-sync-in-ephemeral-contexts-before-quitting
fix(jazz-nodejs): wait for sync before closing and fix the reconnection
2024-12-12 14:52:19 +01:00
Guido D'Orsi
96f844af5e chore: changeset 2024-12-12 11:07:32 +01:00
Guido D'Orsi
994fbf3524 test: add tests on startWorker 2024-12-12 11:04:28 +01:00
Guido D'Orsi
6eba301599 fix: wait for all coValues in sync before closing the Workers node 2024-12-12 10:16:50 +01:00
Guido D'Orsi
322438f361 fix(jazz-nodejs): fix the reconnection system 2024-12-12 10:16:50 +01:00
Guido D'Orsi
f2f3481773 Merge pull request #935 from garden-co/jazz-550-match-account-load-depth-fallback
Add depth fallback
2024-12-12 10:15:12 +01:00
Guido D'Orsi
b96bab59d0 Merge pull request #955 from garden-co/jzi-29-track-the-amount-of-connected-peers-in-cojson-syncmanager
chore: add an up-down counter to track the amount of connected peers
2024-12-12 10:13:34 +01:00
Benjamin S. Leveritt
aa21072ceb Chore: Add changeset 2024-12-11 23:32:39 +00:00
Benjamin S. Leveritt
01442948d0 Exclude Svelte 5 from coverage instrumentation (not supported) 2024-12-11 23:23:43 +00:00
Benjamin S. Leveritt
6c26902a73 Fix coverage picking up wrong files in Jazz-Svelte 2024-12-11 22:53:24 +00:00
Benjamin S. Leveritt
b12f9dc675 Fix downgrade vitest syntax 2024-12-11 22:28:19 +00:00
Benjamin S. Leveritt
bb6d9791dc Lower vitest version 2024-12-11 22:28:19 +00:00
Benjamin S. Leveritt
024b24f5fa Add tests for jazz.svelte 2024-12-11 22:28:19 +00:00
Benjamin S. Leveritt
facfc51e84 Add tests for passkey auth 2024-12-11 22:28:19 +00:00
Benjamin S. Leveritt
6e4a7411dd Add config 2024-12-11 22:28:19 +00:00
Benjamin S. Leveritt
a02b53cbe3 Add vitest coverage 2024-12-11 22:28:19 +00:00
Benjamin S. Leveritt
a0548ecb25 Add vitest 2024-12-11 22:28:19 +00:00
Benjamin S. Leveritt
970414c8c3 Add depth fallback 2024-12-11 22:27:28 +00:00
Anselm Eickhoff
d62a5c74f9 Merge pull request #1004 from garden-co/jazz-579-external-links-to-expo-are-broken
Fix broken links in docs
2024-12-11 18:20:12 +00:00
Guido D'Orsi
5d35469b91 fix: fix jazz-browser-media-images dependency on chat example 2024-12-11 18:49:04 +01:00
Trisha Lim
6cd79a0631 Fix broken links in docs 2024-12-11 16:52:13 +00:00
Trisha Lim
5122cd027b Fix external links in docs 2024-12-11 16:50:06 +00:00
Giordano Ricci
9d9bb97da3 add tests 2024-12-11 11:59:24 +00:00
Giordano Ricci
9db3f2120b add test metric reader utilities 2024-12-11 11:58:50 +00:00
Giordano Ricci
cb4ccd5d33 chore: add .direnv to ignore file 2024-12-11 11:54:27 +00:00
Giordano Ricci
3121551e8a chore: add an up-down counter to track the amount of connected peers 2024-12-11 11:54:27 +00:00
Anselm Eickhoff
1a65ffd913 Merge pull request #950 from garden-co/jazz-188-add-method-to-wait-until-a-covalue-is-synced
feat: add the APIs to wait for a sync state
2024-12-11 10:42:59 +00:00
Guido D'Orsi
80301e51bb Merge pull request #979 from garden-co/jazz-530-send-images-in-chat-example
Send image in chat example
2024-12-11 11:18:54 +01:00
Guido D'Orsi
5686db9b89 Merge pull request #996 from garden-co/jazz-576-fix-homepage-build
Move to use turbo build
2024-12-11 11:18:26 +01:00
Guido D'Orsi
21a56fc96b Merge remote-tracking branch 'origin/main' into jazz-530-send-images-in-chat-example 2024-12-11 11:17:02 +01:00
Guido D'Orsi
eb22a24f17 Merge pull request #990 from garden-co/jazz-574-bump-repo-to-node-22
Chore: Bump node version to 22
2024-12-11 10:56:02 +01:00
Guido D'Orsi
4f3de09154 Merge remote-tracking branch 'origin/main' into jazz-574-bump-repo-to-node-22 2024-12-11 10:53:39 +01:00
Guido D'Orsi
f2f865da50 Merge pull request #920 from garden-co/add-file-share-example-app
Add file share example app
2024-12-11 10:52:30 +01:00
Guido D'Orsi
c0d12dba26 Merge remote-tracking branch 'origin/main' into add-file-share-example-app 2024-12-11 10:51:26 +01:00
Guido D'Orsi
cd0717f35d Merge pull request #983 from garden-co/jazz-571-bug-the-ws-connection-isnt-restored-when-dropped-by-the
fix(react-native): reconnect automatically when the WebSocket is closed by the server
2024-12-11 10:49:23 +01:00
Guido D'Orsi
4515395bb9 Merge pull request #980 from garden-co/jazz-558-set-up-cryptography-tests-for-react-native
feat(react-native): setup a basic environment to test the crypto
2024-12-11 10:49:05 +01:00
Guido D'Orsi
7cee49f2b2 chore: fix typo 2024-12-11 10:32:18 +01:00
Guido D'Orsi
9414fbfb23 fix: fix e2e tests and initial account migration 2024-12-11 10:25:11 +01:00
Guido D'Orsi
9c6ea58ef5 feat(file-share-svelter): add the e2e test to the CI 2024-12-11 09:44:50 +01:00
Guido D'Orsi
0685436b0c Merge pull request #842 from garden-co/JAZZ-238/very-quick-way-to-open-up-inspector-as-current-user-in-an-app
feat: pressing cmd+j in a jazz app exports the jazz account to inspector
2024-12-11 09:33:48 +01:00
Guido D'Orsi
daa11aa915 chore: remove console.log 2024-12-11 09:33:05 +01:00
Benjamin S. Leveritt
bbdb1ef429 Improve build instructions in readme 2024-12-10 23:37:07 +00:00
Benjamin S. Leveritt
508537928f Update cloud key 2024-12-10 23:30:59 +00:00
Benjamin S. Leveritt
eaeeedc3a4 Update readmes 2024-12-10 23:30:59 +00:00
Benjamin S. Leveritt
15cdfd406c Add svelte output to turbo for better caching 2024-12-10 23:30:59 +00:00
Benjamin S. Leveritt
76262c1a03 Replace svelte auto adapter with vercel 2024-12-10 23:30:59 +00:00
Benjamin S. Leveritt
fc43a2384b Remove the special example exception 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
d1698eed6f Add Readmes 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
6d68dc1bbf Rename file-share app 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
1fb49b266a Remove ownerId from url
As it's not used
2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
49f0ab1545 Exclude file-share from biome checking for now 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
641bbddd64 Add file name to page title 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
7e22f53718 Chore: fix formatting 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
4c44468129 Fix Ownership to be determined by admin role 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
b0c5ecd7b6 Add guest access to files 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
5bf9d69e9f Add loading check 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
3ecf11ded9 Replace messages with toasts 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
709d60b365 Add download error handler 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
f135babcb8 Add page title 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
36a85d4313 Add file detail page for sharing 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
7316379247 Add lucide icons 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
0cf59b6549 Tweak UI layout 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
bcaff2f24a Improve layout of uploader 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
d2a5087e65 Animate uploading files 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
8627d47afc Show uploading files 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
47f625cbd4 Add file size 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
34b65ef67a Add shared files page 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
51209d5314 Fix root re-initialising on reload 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
309dffcc67 Wrap auth and provider around app 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
716b87da0a Initialise Jazz app 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
3c58879a10 Add schema 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
ed16031f12 Add jazz deps 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
90d9e1ca91 Format files 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
95828596f8 Add sv created file share app 2024-12-10 23:28:56 +00:00
Benjamin S. Leveritt
d794a555dc Merge pull request #942 from garden-co/jazz-560-fix-linting-in-cojson-storage-indexeddb
Add linting to cojson-storage-indexeddb
2024-12-10 23:27:15 +00:00
Benjamin S. Leveritt
a6c143f33f Add build instructions 2024-12-10 23:02:06 +00:00
Benjamin S. Leveritt
1db615d1b1 Formatting 2024-12-10 21:28:44 +00:00
Benjamin S. Leveritt
9b45c44b29 Move to use turbo build 2024-12-10 21:27:42 +00:00
Benjamin S. Leveritt
ecc7c9672d Chore: Add changeset 2024-12-10 20:24:59 +00:00
Benjamin S. Leveritt
d645970cb0 Bump dockerfile node version 2024-12-10 20:24:59 +00:00
Benjamin S. Leveritt
e9864cda9d Chore: Bump better-sqlite3 version 2024-12-10 20:24:59 +00:00
Benjamin S. Leveritt
d4e9afc4e2 Chore: Bump node version to 22 2024-12-10 20:21:36 +00:00
pax
4fc4f029a2 Merge pull request #977 from garden-co/changeset-release/main
Version Packages
2024-12-10 20:39:58 +02:00
Guido D'Orsi
fb06319dae chore: simplify createAccount relying on waitForAllCoValuesSync 2024-12-10 18:29:54 +01:00
Guido D'Orsi
a4886fede8 test: fix test after merge 2024-12-10 18:16:30 +01:00
Trisha Lim
b2ca4ec52e Change owner of image 2024-12-10 16:59:56 +00:00
Trisha Lim
b2c8a1a27d Add hover styling to Upload Image button 2024-12-10 16:58:29 +00:00
github-actions[bot]
5469c1f347 Version Packages 2024-12-10 14:55:06 +00:00
Anselm Eickhoff
d36e7cd55a Merge pull request #987 from garden-co/jazz-573-improve-turbo-caching-on-homepage
Adds caching to homepage
2024-12-10 14:53:43 +00:00
Giordano Ricci
03ccdb93af Merge pull request #988 from garden-co/gio/add-queue-metrics-tests
chore: adds message queue size metrics tests
2024-12-10 13:36:00 +00:00
Giordano Ricci
eb8bd20931 teardown meter provider 2024-12-10 13:28:29 +00:00
Giordano Ricci
9819811c91 chore: adds message queue size metrics tests 2024-12-10 12:35:24 +00:00
Benjamin S. Leveritt
350e59b187 Adds caching to homepage 2024-12-10 11:42:57 +00:00
Guido D'Orsi
c2cad4b68c Merge remote-tracking branch 'origin/main' into jazz-188-add-method-to-wait-until-a-covalue-is-synced 2024-12-10 11:23:29 +01:00
Guido D'Orsi
0c6b0f37ed fix(react-native): reconnect automatically when the WebSocket is closed by the server 2024-12-10 11:17:56 +01:00
Anselm Eickhoff
a3541f24ee Merge pull request #975 from garden-co/jzi-28-track-the-message-queue-size-of-each-peerstate-on-cojson
chore: Add message queue size metric
2024-12-10 09:59:17 +00:00
Anselm Eickhoff
f8be4e8bc0 Merge pull request #978 from garden-co/fix/sqlite-scheduling
fix(sqlite): improve the work scheduling when under pressure
2024-12-10 09:52:40 +00:00
Guido D'Orsi
c8015ddee1 feat(react-native): setup a basic environment to test the crypto 2024-12-10 10:24:30 +01:00
Guido D'Orsi
44227bd6e8 Merge pull request #970 from garden-co/fix/sync-server-console
fix(jazz-run): fix console output to log the server address when running the local sync
2024-12-10 10:02:10 +01:00
Trisha Lim
d582429488 Set file size limit to 5MB 2024-12-09 18:45:00 +00:00
Trisha Lim
3db0639636 Update demo section copy 2024-12-09 18:29:10 +00:00
Trisha Lim
c75cd9da37 Send image in chat example 2024-12-09 16:12:05 +00:00
Guido D'Orsi
da13ecac5c fix(sqlite): improve the work scheduling when under pressure 2024-12-09 16:44:34 +01:00
Giordano Ricci
c4af72e1ca mark @opentelemetry/api as a peer dependency 2024-12-09 14:48:10 +00:00
Trisha Lim
e43ca2bc98 Fix broken links 2024-12-09 11:46:28 +00:00
Trisha Lim
bcdd8e9125 Change "updating" to "writing" 2024-12-09 11:46:28 +00:00
Trisha Lim
2d6352a2dc Match side nav links with content links 2024-12-09 11:46:28 +00:00
Trisha Lim
749350cb59 Docs: return coming soon page on routes with no content 2024-12-09 11:46:28 +00:00
Trisha Lim
07e9a73c52 Fix clerk example readme title 2024-12-09 11:28:47 +00:00
Anselm Eickhoff
1ef9998b23 Merge pull request #973 from garden-co/fix/parent-group-role-resolution
fix(role): apply time traveling when resolving role from parents
2024-12-09 11:12:12 +00:00
Guido D'Orsi
b00ee914c3 fix(role): apply time traveling when resolving role from parents 2024-12-09 12:03:18 +01:00
Giordano Ricci
f488c09545 add changeset 2024-12-09 10:17:31 +00:00
Giordano Ricci
0d6ea25e56 chore: Add message queue size metric 2024-12-09 10:09:20 +00:00
Guido D'Orsi
9ffe6d0c63 test(e2e): use waitForSync to improve the test stability 2024-12-08 12:53:23 +01:00
Guido D'Orsi
249eecb68f chore: changeset 2024-12-08 12:46:05 +01:00
Guido D'Orsi
cdbde2970d fix(PeerState): keep optimistic and knownState the same when the role is storage 2024-12-08 12:46:05 +01:00
Guido D'Orsi
24a1b045d3 test(e2e): move synced check up 2024-12-08 12:46:05 +01:00
Guido D'Orsi
a21c3068cd feat(waitForSync): add API docs and some more tests 2024-12-08 12:46:05 +01:00
Guido D'Orsi
55ab4844d6 feat: add the APIs to wait for a sync state 2024-12-08 12:46:05 +01:00
Guido D'Orsi
6e131eb0dc Merge pull request #971 from garden-co/fix/e2e-test-sharing
test(e2e): use the local server to reduce the flakyiness
2024-12-08 11:47:00 +01:00
Guido D'Orsi
8a0cb69c72 test(e2e): fix flakyiness on the Sharing test suit 2024-12-08 11:40:56 +01:00
Guido D'Orsi
d01286b723 test(e2e): use the local server to reduce the flakyiness 2024-12-08 11:32:49 +01:00
Guido D'Orsi
0b636d26f3 Merge pull request #968 from garden-co/playwright-cache
chore(ci): optimize playwright browsers install
2024-12-08 11:22:25 +01:00
Guido D'Orsi
f41a1b0d1d Merge pull request #969 from garden-co/upgrade-pnpm-changeset
chore: update pnpm and changeset to fix release
2024-12-08 11:18:03 +01:00
Guido D'Orsi
28930ee1d5 fix(jazz-run): fix console output 2024-12-08 11:09:53 +01:00
Guido D'Orsi
0a8753dfe0 chore: align pnpm-lock with main 2024-12-08 11:06:39 +01:00
Guido D'Orsi
3ca8b13f6c fix: fix type error on test file 2024-12-08 11:01:40 +01:00
Guido D'Orsi
e06c18150a chore(ci): remove --with-deps 2024-12-08 10:57:35 +01:00
Guido D'Orsi
4c4499ce86 Merge remote-tracking branch 'origin/main' into upgrade-pnpm-changeset 2024-12-08 10:56:11 +01:00
Guido D'Orsi
afa4c825ca chore: update pnpm and changeset to fix release 2024-12-08 10:53:04 +01:00
Guido D'Orsi
60e04cb193 chore(ci): cache playwright browsers 2024-12-08 10:51:30 +01:00
Guido D'Orsi
843a012f33 Merge pull request #967 from garden-co/update-changeset-config
fix(changeset): update config
2024-12-08 10:39:17 +01:00
Guido D'Orsi
bd510a13ce fix(changeset): update config 2024-12-08 10:38:36 +01:00
Benjamin S. Leveritt
0d6853bbdd Fix imports 2024-12-08 07:36:35 +00:00
Benjamin S. Leveritt
a238dde78a Fix test 2024-12-08 07:36:35 +00:00
Benjamin S. Leveritt
59997fbf71 Add linting 2024-12-08 07:36:35 +00:00
Anselm
b56d7e3e7c Make passkey-svelte example private on npm 2024-12-07 19:17:06 +00:00
Anselm Eickhoff
2f5bd74206 Merge pull request #966 from garden-co/changeset-release/main
Version Packages
2024-12-07 19:09:20 +00:00
github-actions[bot]
a4864d93d2 Version Packages 2024-12-07 19:04:33 +00:00
Anselm Eickhoff
19376e6abd Merge pull request #965 from garden-co/perf/coMapAtTime
perf(CoMap): optimize the atTime processing
2024-12-07 19:02:56 +00:00
Guido D'Orsi
22f6db8141 test: cover CoMap public methods with tests 2024-12-07 19:40:44 +01:00
Guido D'Orsi
3d9f12e9ea chore: changeset 2024-12-07 19:28:12 +01:00
Guido D'Orsi
68620a3df9 perf(CoMap): optimize the atTime processing 2024-12-07 19:07:52 +01:00
Anselm Eickhoff
1767f024d9 Merge pull request #964 from garden-co/jazz-567-speed-up-latency-map-rendering
Fix caching for latency map
2024-12-07 14:06:46 +00:00
Anselm
c55924a04a Fix caching 2024-12-07 13:56:48 +00:00
Anselm Eickhoff
31e00a96ae Merge pull request #963 from garden-co/jazz-567-speed-up-latency-map-rendering
Speed up latency map rendering
2024-12-07 12:59:44 +00:00
Anselm
7bb834f399 Lint & format 2024-12-07 12:54:37 +00:00
pax
667f36e1cf Merge pull request #957 from garden-co/rn-examples-new-arch
fix: upgraded RN examples to Expo SDK 52 with new arch
2024-12-07 14:50:50 +02:00
pax-k
07669923ad Merge branch 'main' into rn-examples-new-arch 2024-12-07 14:48:28 +02:00
Anselm
9082a099ee Merge branch 'main' into jazz-567-speed-up-latency-map-rendering 2024-12-07 12:31:58 +00:00
Anselm
aba059db28 Try strongarming vercel into using the right pnpm version 2024-12-07 12:23:15 +00:00
Anselm
ae6b9c8dd2 Speed up latency map rendering 2024-12-06 18:59:21 +00:00
pax-k
7b9f96bf1a chore: pnpm lock 2024-12-06 18:52:25 +02:00
pax-k
8df49546fe Merge branch 'main' into rn-examples-new-arch 2024-12-06 18:52:08 +02:00
pax-k
bb4460f422 fix: upgraded RN examples to Expo SDK 52 with new arch 2024-12-06 18:51:35 +02:00
Anselm Eickhoff
2099099afc Merge pull request #956 from nikitavoloboev/patch-1
fix 404 urls in docs
2024-12-06 16:47:19 +00:00
Nikita
06b0758d7c fix urls 2024-12-06 17:43:06 +01:00
Nikita
6135250e57 fix 404 url 2024-12-06 17:38:32 +01:00
Anselm Eickhoff
aacd03bbdd Merge pull request #945 from garden-co/changeset-release/main
Version Packages
2024-12-06 15:39:02 +00:00
github-actions[bot]
ca7f250d47 Version Packages 2024-12-06 14:46:52 +00:00
pax
83ad506b94 Merge pull request #954 from garden-co/jazz-react-native-auth-clerk
jazz-react-native-auth-clerk package
2024-12-06 16:45:42 +02:00
pax-k
e9751f5b69 Merge branch 'main' into jazz-react-native-auth-clerk 2024-12-06 16:36:14 +02:00
pax-k
c84764acd5 chore: changeset 2024-12-06 16:30:35 +02:00
pax-k
c2a805bffa chore: added expo-font 2024-12-06 16:27:27 +02:00
pax-k
8728dde42b feat: added package jazz-react-native-auth-clerk 2024-12-06 15:13:45 +02:00
Benjamin S. Leveritt
9dd9366734 Merge pull request #949 from garden-co/jazz-518-write-initial-defining-schemas-docs
Write initial defining schemas docs
2024-12-05 20:23:03 +00:00
Anselm Eickhoff
48dd00f453 Merge pull request #946 from garden-co/jazz-563-fix-github-url
Replaces github url with new one
2024-12-05 18:25:57 +00:00
Anselm Eickhoff
cc361aefe5 Merge pull request #919 from garden-co/jazz-544-refactor-sqlite-storage-the-same-way-as-the-idbs-done
Refactor SQLite storage
2024-12-05 17:12:54 +00:00
Anselm
9e4438cb54 Write initial defining schemas docs 2024-12-05 17:09:01 +00:00
Benjamin S. Leveritt
08706d557a Update general web urls 2024-12-05 16:55:44 +00:00
Benjamin S. Leveritt
02c1ec63cc Change cloud keys and peer addresses 2024-12-05 16:54:33 +00:00
Benjamin S. Leveritt
df797dedcd Change email addresses 2024-12-05 16:53:01 +00:00
Benjamin S. Leveritt
74cb08e7d4 Replaces github url with new one 2024-12-05 16:48:44 +00:00
Anselm Eickhoff
73720a8cc4 Merge pull request #907 from garden-co/latency-map
Add a latency map to cloud page
2024-12-05 16:36:39 +00:00
Anselm Eickhoff
50c77fa788 Merge pull request #916 from garden-co/docs/examples-demo
Show demo and code for minimal examples
2024-12-05 16:35:04 +00:00
Benjamin S. Leveritt
9977a4ee85 Use jsxEmit value rather than string 2024-12-05 16:06:46 +00:00
Guido D'Orsi
441fe27802 chore: changeset 2024-12-05 15:53:19 +01:00
Marina Orlova
1afbd2c7cc Add changeset 2024-12-05 15:43:12 +01:00
Marina Orlova
4955e39af5 Create cojson-storage 2024-12-05 15:43:12 +01:00
Marina Orlova
ace151696c Copy syncUtils code into sqlite package 2024-12-05 15:43:12 +01:00
Marina Orlova
db9560ebc5 Fix ERR_MODULE_NOT_FOUND 2024-12-05 15:43:12 +01:00
Marina Orlova
80b572710e Fix tests 2024-12-05 15:43:12 +01:00
Marina Orlova
bbb9d45969 Unify IDB and SQLite storage code 2024-12-05 15:43:12 +01:00
Marina Orlova
83e9a3eaa8 Normalise sqlite code against indexedb 2024-12-05 15:43:12 +01:00
Marina Orlova
9ff7e68f7d Split sqlite storage 2024-12-05 15:43:12 +01:00
Anselm Eickhoff
06740e840a Merge pull request #927 from garden-co/jazz-551-optimise-large-record-like-comaps-for-access-of-latest-value
Optimise large record-like CoMaps for access of latest value
2024-12-05 10:28:19 +00:00
Guido D'Orsi
b0e2c4fd4b fix: revert the incremental processing optimization as it doesn't take into account that older transactions might be synced after the new ones 2024-12-05 11:11:49 +01:00
Guido D'Orsi
4c1922c10e perf(coMap): process only the new transactions on update 2024-12-05 11:03:35 +01:00
Anselm Eickhoff
76bad9b5c3 Merge pull request #922 from garden-co/jazz-547-explicitly-reference-homepage-dependencies
Explicitly reference homepage dependencies
2024-12-05 09:46:55 +00:00
Trisha Lim
7f16f2705e Attempt fix build 2024-12-04 21:54:08 +00:00
Guido D'Orsi
d12594e521 fix: fix timing issues and invalidate on update 2024-12-04 21:13:43 +01:00
Guido D'Orsi
cf96350b01 Merge remote-tracking branch 'origin/main' into jazz-551-optimise-large-record-like-comaps-for-access-of-latest-value 2024-12-04 20:21:53 +01:00
Anselm
947030433f Merge branch 'main' into latency-map 2024-12-04 18:27:34 +00:00
Anselm
b4cebd732e Merge branch 'main' into docs/examples-demo 2024-12-04 18:26:40 +00:00
Anselm
d0d95e6d5d Merge branch 'main' into jazz-547-explicitly-reference-homepage-dependencies 2024-12-04 18:23:47 +00:00
Trisha Lim
a75383ac6a Fix build 2024-12-04 18:15:44 +00:00
Trisha Lim
de503b6120 Formatting fixes 2024-12-04 18:07:59 +00:00
Trisha Lim
f7ae41254f Merge branch 'main' into docs/examples-demo 2024-12-04 18:06:09 +00:00
Trisha Lim
8f348b28c6 Improve code example styling 2024-12-04 18:05:53 +00:00
Trisha Lim
3b185b4cd3 Merge branch 'main' into latency-map 2024-12-04 16:54:50 +00:00
Anselm
df5dc513bf Don't reverse iterate over valid transactions for now 2024-12-04 16:51:11 +00:00
Benjamin S. Leveritt
8e6783ad88 Link dependant jazz packages for api docs generation 2024-12-04 16:48:59 +00:00
Benjamin S. Leveritt
79bf6f478f Add Turbo build config to homepage workspace 2024-12-04 16:48:59 +00:00
Trisha Lim
7fd93a5a61 Move Examples page before API Ref nav link 2024-12-04 16:48:39 +00:00
Trisha Lim
8f9687323f Reorder examples 2024-12-04 16:48:39 +00:00
Trisha Lim
47ee25786f Spacing 2024-12-04 16:48:39 +00:00
Trisha Lim
0009aa19b2 Example demo header design 2024-12-04 16:48:39 +00:00
Trisha Lim
741b9cbada Move components out of page.tsx 2024-12-04 16:48:39 +00:00
Trisha Lim
259ade3099 Consistent layout and styling in demo apps 2024-12-04 16:48:39 +00:00
Trisha Lim
b6f2da2221 Move demos to separate section 2024-12-04 16:48:39 +00:00
Trisha Lim
44157945a0 Show code samples 2024-12-04 16:48:39 +00:00
Trisha Lim
4ff7bb500a Show iframe for examples 2024-12-04 16:48:39 +00:00
Anselm
db5ea54338 Fix jazz-tools use of _raw.ops 2024-12-04 16:26:19 +00:00
Anselm
7c7880a9b2 Optimise large record-like CoMaps for access of latest value 2024-12-04 16:21:01 +00:00
Trisha Lim
49082a5aad Merge branch 'main' into latency-map 2024-12-04 10:41:18 +00:00
pax-k
ab7c899a9e Merge branch 'main' into JAZZ-238/very-quick-way-to-open-up-inspector-as-current-user-in-an-app 2024-12-04 12:18:36 +02:00
Trisha Lim
b6653555f5 Fix build 2024-12-03 15:45:24 +00:00
Trisha Lim
c9fd16ce21 Desktop view 2024-12-03 14:46:14 +00:00
Trisha Lim
e60f34d9e6 Mobile view 2024-12-03 14:28:24 +00:00
Trisha Lim
a04c7dca7a Install next-themes 2024-12-03 12:37:00 +00:00
Trisha Lim
e067c29d81 Map positioning 2024-12-03 12:36:14 +00:00
pax-k
81c470e9fa fix: comment out createCoValueObservable.test.ts until cirular imports are fixed 2024-12-03 14:31:50 +02:00
pax-k
52d5a14fdf fix: comment out createCoValueObservable.test.ts until cirular imports are fixed 2024-12-03 14:24:49 +02:00
Trisha Lim
1357306d1b Switch latency map colors according to theme 2024-12-03 12:10:22 +00:00
pax-k
fca6be8da0 Merge branch 'main' into JAZZ-238/very-quick-way-to-open-up-inspector-as-current-user-in-an-app 2024-12-03 14:07:17 +02:00
Trisha Lim
3c6d9b20c1 Move theme controls to gcmp/jazz, and out of design system 2024-12-03 12:03:22 +00:00
pax-k
e386f2ba8d chore: changeset 2024-12-03 13:56:41 +02:00
pax-k
c2d292effc chore: moved export-account-inspector.ts to jazz-browser 2024-12-03 13:52:09 +02:00
Trisha Lim
f597316267 Remove console logs 2024-12-03 11:18:50 +00:00
Trisha Lim
17f8bc25c3 Update colors for dark mode 2024-12-02 20:21:29 +00:00
Trisha Lim
c1d652cf7f Update colors for light mode 2024-12-02 20:05:38 +00:00
Trisha Lim
10f3e4aabd Update colors for light mode 2024-12-02 17:24:42 +00:00
Anselm
63f5574003 Improve map 2024-12-02 16:26:38 +00:00
Anselm
9bb5c4ca5f Add a latency map to cloud page 2024-12-01 16:03:38 +00:00
pax-k
a107e17c44 fix: cmd+j now registered only if allowJazzInspector is found in window.location.href 2024-11-25 17:28:46 +02:00
pax
d2d2801537 Update packages/jazz-tools/src/utils/export-account-inspector.ts
Co-authored-by: Anselm Eickhoff <anselm.eickhoff@gmail.com>
2024-11-25 17:04:45 +02:00
pax-k
d5af8df158 feat: pressing cmd+j in a jazz app exports the jazz account to inspector 2024-11-21 17:30:50 +02:00
421 changed files with 38801 additions and 6531 deletions

View File

@@ -6,18 +6,23 @@
"linked": [
[
"cojson",
"jazz-tools",
"jazz-browser",
"jazz-browser-media-images",
"jazz-browser-auth-clerk",
"jazz-react-auth-clerk",
"jazz-react",
"jazz-react-native",
"jazz-nodejs",
"jazz-run",
"cojson-transport-ws",
"cojson-storage",
"cojson-storage-indexeddb",
"cojson-storage-sqlite"
"cojson-storage-sqlite",
"cojson-transport-ws",
"jazz-browser",
"jazz-browser-auth-clerk",
"jazz-browser-media-images",
"jazz-nodejs",
"jazz-react",
"jazz-react-auth-clerk",
"jazz-react-native",
"jazz-react-native-auth-clerk",
"jazz-react-native-media-images",
"jazz-run",
"jazz-svelte",
"jazz-tools",
"jazz-vue"
]
],
"access": "public",

View File

@@ -0,0 +1,5 @@
---
"cojson": patch
---
Add an internal API to disable the permission errors logs

View File

@@ -13,7 +13,7 @@ jobs:
continue-on-error: true
strategy:
matrix:
project: ["tests/e2e", "examples/chat", "examples/music-player", "examples/pets", "examples/onboarding"]
project: ["tests/e2e", "examples/chat", "examples/file-share-svelte", "examples/form", "examples/music-player", "examples/pets", "examples/onboarding"]
steps:
- uses: actions/checkout@v3
@@ -41,20 +41,16 @@ jobs:
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 turbo build
working-directory: ./${{ matrix.project }}
- name: Build jazz-run
run: pnpm exec turbo build && chmod +x dist/index.js;
working-directory: ./packages/jazz-run
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps
run: pnpm exec playwright install
working-directory: ./${{ matrix.project }}
- name: Run Playwright tests

View File

@@ -4,6 +4,13 @@ on:
push:
branches:
- main
workflow_dispatch:
inputs:
debug_enabled:
type: boolean
description: "Run tmate session for debugging"
required: false
default: false
concurrency: ${{ github.workflow }}-${{ github.ref }}
@@ -48,4 +55,11 @@ jobs:
publish: pnpm release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# Enable tmate debugging only if the workflow is manually triggered, debug_enabled is true, and the workflow failed
- name: Setup tmate session for debugging
if: ${{ failure() && github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
uses: mxschmitt/action-tmate@v3
with:
timeout-minutes: 15

View File

@@ -41,7 +41,7 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Pnpm Build
run: pnpm turbo build
run: pnpm turbo build --filter="./packages/*"
- name: Unit Tests
run: pnpm test:ci

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@ docsTmp
.DS_Store
.turbo
coverage
.direnv
# Next.js
**/.next

View File

@@ -1 +1 @@
20
22

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
22

View File

@@ -59,7 +59,7 @@ representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to [the community leaders responsible for enforcement](mailto:hello@gcmp.io).
reported to [the community leaders responsible for enforcement](mailto:hello@garden.co).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -6,7 +6,7 @@ Thank you for considering contributing to Jazz! Jazz is an open-source framework
### 1. Reporting Bugs
If you find a bug, please [open an issue with as much detail as possible](https://github.com/gardencmp/jazz/issues). Include:
If you find a bug, please [open an issue with as much detail as possible](https://github.com/garden-co/jazz/issues). Include:
- A clear and descriptive title.
- Steps to reproduce the issue.
@@ -40,7 +40,7 @@ You'll need Node.js 20.x or 22.x installed (we're working on support for 23.x),
1. **Clone the repository**:
```bash
git clone https://github.com/gardencmp/jazz.git
git clone https://github.com/garden-co/jazz.git
```
2. **Install dependencies**:

View File

@@ -15,6 +15,6 @@ For community and support, please join our [Discord](https://discord.gg/utDMjHYg
- Homepage: [jazz.tools](https://jazz.tools)
- Docs: [jazz.tools/docs](https://jazz.tools/docs)
- Community & support: [Discord](https://discord.gg/utDMjHYg42)
- Updates: [X](https://x.com/jazz_tools) & [Email](https://gcmp.io/news)
- Updates: [X](https://x.com/jazz_tools) & [Email](https://garden.co/news)
Copyright 2024 &mdash; Garden Computing, Inc.

View File

@@ -25,7 +25,53 @@
"linter": {
"enabled": false,
"rules": {
"recommended": true
"recommended": true,
"correctness": {
"useImportExtensions": {
"level": "error",
"options": {
"suggestedExtensions": {
"ts": {
"module": "js",
"component": "jsx"
}
}
}
}
}
}
}
},
"overrides": [
{
"include": ["packages/**/src/**"],
"linter": {
"enabled": true,
"rules": {
"recommended": false
}
}
},
{
"include": ["packages/**/src/tests/**", "packages/**/src/test/**"],
"linter": {
"rules": {
"correctness": {
"useImportExtensions": "off"
}
}
}
},
{
"include": ["packages/cojson-storage-indexeddb/**"],
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "info"
}
}
}
}
]
}

View File

@@ -1,5 +1,54 @@
# jazz-example-book-shelf
## 0.1.33
### Patch Changes
- jazz-react@0.8.41
- jazz-tools@0.8.41
- jazz-browser-media-images@0.8.41
## 0.1.32
### Patch Changes
- jazz-browser-media-images@0.8.40
- jazz-react@0.8.40
## 0.1.31
### Patch Changes
- Updated dependencies [249eecb]
- jazz-tools@0.8.39
- jazz-browser-media-images@0.8.39
- jazz-react@0.8.39
## 0.1.30
### Patch Changes
- jazz-react@0.8.38
- jazz-tools@0.8.38
- jazz-browser-media-images@0.8.38
## 0.1.29
### Patch Changes
- jazz-react@0.8.37
- jazz-tools@0.8.37
- jazz-browser-media-images@0.8.37
## 0.1.28
### Patch Changes
- Updated dependencies [441fe27]
- jazz-tools@0.8.36
- jazz-react@0.8.36
- jazz-browser-media-images@0.8.36
## 0.1.27
### Patch Changes

View File

@@ -1,4 +1,4 @@
FROM caddy:2.7.3-alpine
LABEL org.opencontainers.image.source="https://github.com/gardencmp/jazz"
LABEL org.opencontainers.image.source="https://github.com/garden-co/jazz"
COPY ./dist /usr/share/caddy/

View File

@@ -1,6 +1,6 @@
{
"name": "jazz-example-book-shelf",
"version": "0.1.27",
"version": "0.1.33",
"private": true,
"scripts": {
"dev": "next dev",
@@ -11,19 +11,19 @@
},
"dependencies": {
"clsx": "^2.0.0",
"jazz-browser-media-images": "workspace:0.8.35",
"jazz-react": "workspace:0.8.35",
"jazz-tools": "workspace:0.8.35",
"jazz-browser-media-images": "workspace:0.8.41",
"jazz-react": "workspace:0.8.41",
"jazz-tools": "workspace:0.8.41",
"next": "14.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/node": "^22.5.1",
"@types/react": "^18.2.19",
"@types/react-dom": "^18.2.7",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"postcss": "^8.4.27",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3"
"tailwindcss": "^3.4.9",
"typescript": "~5.6.2"
}
}

View File

@@ -0,0 +1,8 @@
{
"build": {
"env": {
"APP_NAME": "books-demo"
}
},
"ignoreCommand": "node ../../ignore-vercel-build.js"
}

View File

@@ -1 +1 @@
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_ZXZpZGVudC1kYW5lLTg5LmNsZXJrLmFjY291bnRzLmRldiQ
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_ZXZpZGVudC1kYW5lLTg5LmNsZXJrLmFjY291bnRzLmRldiQ

View File

@@ -1,5 +1,63 @@
# chat-rn-clerk
## 1.0.33
### Patch Changes
- cdc7f9f: Fixing react-native examples
- Updated dependencies [cdc7f9f]
- jazz-react-native-auth-clerk@0.8.43
## 1.0.32
### Patch Changes
- jazz-react-native@0.8.41
- jazz-react-native-auth-clerk@0.8.41
- jazz-tools@0.8.41
- jazz-react-native-media-images@0.8.41
## 1.0.31
### Patch Changes
- Updated dependencies [0c6b0f3]
- Updated dependencies [249eecb]
- jazz-react-native@0.8.39
- jazz-tools@0.8.39
- jazz-react-native-auth-clerk@0.8.39
- jazz-react-native-media-images@0.8.39
## 1.0.30
### Patch Changes
- jazz-react-native@0.8.38
- jazz-react-native-auth-clerk@0.8.38
- jazz-tools@0.8.38
- jazz-react-native-media-images@0.8.38
## 1.0.29
### Patch Changes
- jazz-react-native@0.8.37
- jazz-react-native-auth-clerk@0.8.37
- jazz-tools@0.8.37
- jazz-react-native-media-images@0.8.28
## 1.0.28
### Patch Changes
- c84764a: feat: added jazz-react-native-auth-clerk package
- Updated dependencies [c84764a]
- Updated dependencies [441fe27]
- jazz-react-native-auth-clerk@0.8.36
- jazz-react-native@0.8.36
- jazz-tools@0.8.36
- jazz-react-native-media-images@0.8.27
## 1.0.27
### Patch Changes

View File

@@ -35,7 +35,9 @@
}
}
],
"expo-secure-store"
"expo-secure-store",
"expo-font",
"expo-router"
],
"extra": {
"eas": {

View File

@@ -1,3 +1,4 @@
import "../global.css";
import { ClerkLoaded, ClerkProvider } from "@clerk/clerk-expo";
import { useFonts } from "expo-font";
import { Slot } from "expo-router";

View File

@@ -1,7 +1,9 @@
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: ["nativewind/babel"],
presets: [
["babel-preset-expo", { jsxImportSource: "nativewind" }],
"nativewind/babel",
],
};
};

View File

@@ -4,7 +4,7 @@ import { Platform } from "react-native";
export interface TokenCache {
getToken: (key: string) => Promise<string | undefined | null>;
saveToken: (key: string, token: string) => Promise<void>;
clearToken?: (key: string) => void;
clearToken: (key: string) => void;
}
const createTokenCache = (): TokenCache => {
@@ -27,6 +27,9 @@ const createTokenCache = (): TokenCache => {
saveToken: (key: string, token: string) => {
return SecureStore.setItemAsync(key, token);
},
clearToken: (key: string) => {
return SecureStore.deleteItemAsync(key);
},
};
};

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -1,5 +1,6 @@
// Learn more https://docs.expo.dev/guides/monorepos
const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require("nativewind/metro");
const { FileStore } = require("metro-cache");
const path = require("path");
@@ -19,7 +20,10 @@ config.resolver.nodeModulesPaths = [
];
config.resolver.sourceExts = ["mjs", "js", "json", "ts", "tsx"];
config.resolver.unstable_enablePackageExports = true;
config.resolver.requireCycleIgnorePatterns = [/(^|\/|\\)node_modules($|\/|\\)/];
config.resolver.requireCycleIgnorePatterns = [
/(^|\/|\\)node_modules($|\/|\\)/,
/(^|\/|\\)packages($|\/|\\)/,
];
// Use turborepo to restore the cache when possible
config.cacheStores = [
@@ -28,4 +32,5 @@ config.cacheStores = [
}),
];
module.exports = config;
// module.exports = config;
module.exports = withNativeWind(config, { input: "./global.css" });

View File

@@ -1,7 +1,7 @@
{
"name": "chat-rn-clerk",
"main": "index.js",
"version": "1.0.27",
"version": "1.0.33",
"scripts": {
"build": "expo export -p ios",
"start": "expo start",
@@ -17,62 +17,61 @@
},
"dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@bam.tech/react-native-image-resizer": "^3.0.10",
"@bam.tech/react-native-image-resizer": "^3.0.11",
"@clerk/clerk-expo": "^2.2.21",
"@expo/vector-icons": "^14.0.2",
"@react-native-community/netinfo": "^11.3.1",
"@react-navigation/native": "^6.1.18",
"@react-navigation/native-stack": "^6.11.0",
"@react-native-community/netinfo": "^11.4.1",
"@react-navigation/native": "^7.0.13",
"@react-navigation/native-stack": "^7.1.14",
"base-64": "^1.0.0",
"buffer": "^6.0.3",
"clsx": "^2.0.0",
"expo": "~51.0.37",
"expo-build-properties": "~0.12.5",
"expo-clipboard": "~6.0.3",
"expo-constants": "~16.0.2",
"expo-crypto": "~13.0.2",
"expo-dev-client": "~4.0.28",
"expo-file-system": "^17.0.1",
"expo-font": "~12.0.4",
"expo-linking": "~6.3.1",
"expo-router": "~3.5.23",
"expo-secure-store": "~13.0.2",
"expo-splash-screen": "~0.27.5",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.7",
"expo-web-browser": "~13.0.3",
"jazz-react-auth-clerk": "workspace:*",
"expo": "^52.0.0",
"expo-build-properties": "~0.13.1",
"expo-clipboard": "~7.0.0",
"expo-constants": "~17.0.3",
"expo-crypto": "~14.0.1",
"expo-dev-client": "~5.0.5",
"expo-file-system": "^18.0.4",
"expo-font": "~13.0.1",
"expo-linking": "~7.0.3",
"expo-router": "~4.0.11",
"expo-secure-store": "~14.0.0",
"expo-splash-screen": "~0.29.16",
"expo-status-bar": "~2.0.0",
"expo-system-ui": "~4.0.5",
"expo-web-browser": "~14.0.1",
"jazz-react-native": "workspace:*",
"jazz-react-native-auth-clerk": "workspace:*",
"jazz-react-native-media-images": "workspace:*",
"jazz-tools": "workspace:*",
"nativewind": "^2.0.11",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-native": "~0.74.5",
"nativewind": "^4.1.21",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-native": "~0.76.3",
"react-native-fetch-api": "^3.0.0",
"react-native-gesture-handler": "~2.16.1",
"react-native-gesture-handler": "~2.20.2",
"react-native-get-random-values": "^1.11.0",
"react-native-mmkv": "3.0.1",
"react-native-polyfill-globals": "^3.1.0",
"react-native-quick-base64": "^2.1.2",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"react-native-reanimated": "~3.16.3",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "4.1.0",
"react-native-url-polyfill": "^2.0.0",
"react-native-web": "~0.19.10",
"react-native-web": "~0.19.13",
"text-encoding": "^0.7.0",
"web-streams-polyfill": "^3.2.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/jest": "^29.5.3",
"@types/react": "^18.2.19",
"@types/react": "^18.3.12",
"@types/react-test-renderer": "^18.0.7",
"jest": "^29.2.1",
"jest-expo": "~51.0.3",
"jest-expo": "~52.0.2",
"react-test-renderer": "18.2.0",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3"
"tailwindcss": "^3.4.15",
"typescript": "~5.6.2"
},
"private": true
}

View File

@@ -1,14 +1,14 @@
import { useClerk, useUser } from "@clerk/clerk-expo";
import { useJazzClerkAuth } from "jazz-react-auth-clerk";
import { useJazzClerkAuth } from "jazz-react-native-auth-clerk";
import React, {
useContext,
createContext,
PropsWithChildren,
useContext,
useEffect,
useState,
PropsWithChildren,
} from "react";
import { Text, View } from "react-native";
import { Jazz } from "./jazz";
import { Jazz, kvStore } from "./jazz";
const AuthContext = createContext<{
isAuthenticated: boolean;
@@ -25,7 +25,7 @@ export function useAuth() {
export function JazzAndAuth({ children }: PropsWithChildren) {
const { isSignedIn, isLoaded: isClerkLoaded } = useUser();
const clerk = useClerk();
const [auth, state] = useJazzClerkAuth(clerk);
const [auth, state] = useJazzClerkAuth(clerk, kvStore);
const [isAuthenticated, setIsAuthenticated] = useState(false);
useEffect(() => {
@@ -46,10 +46,10 @@ export function JazzAndAuth({ children }: PropsWithChildren) {
<Text style={{ color: "red" }}>{error}</Text>
</View>
))}
{auth ? (
{auth && clerk.user ? (
<Jazz.Provider
auth={auth}
peer="wss://cloud.jazz.tools/?key=chat-rn-clerk-example-jazz@gcmp.io"
peer="wss://cloud.jazz.tools/?key=chat-rn-clerk-example-jazz@garden.co"
storage={undefined}
>
{children}

View File

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

View File

@@ -1,10 +1,12 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
// NOTE: Update this to include the paths to all of your component files.
content: [
"./app/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}",
"./src/**/*.{js,jsx,ts,tsx}",
],
presets: [require("nativewind/preset")],
theme: {
extend: {},
},

View File

@@ -7,5 +7,5 @@
"@/*": ["./*"]
}
},
"include": ["**/*.ts", "**/*.tsx"]
"include": ["**/*.ts", "**/*.tsx", "nativewind-env.d.ts"]
}

View File

@@ -1,5 +1,44 @@
# chat-rn
## 1.0.30
### Patch Changes
- jazz-react-native@0.8.41
- jazz-tools@0.8.41
## 1.0.29
### Patch Changes
- Updated dependencies [0c6b0f3]
- Updated dependencies [249eecb]
- jazz-react-native@0.8.39
- jazz-tools@0.8.39
## 1.0.28
### Patch Changes
- jazz-react-native@0.8.38
- jazz-tools@0.8.38
## 1.0.27
### Patch Changes
- jazz-react-native@0.8.37
- jazz-tools@0.8.37
## 1.0.26
### Patch Changes
- Updated dependencies [c84764a]
- Updated dependencies [441fe27]
- jazz-react-native@0.8.36
- jazz-tools@0.8.36
## 1.0.25
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-rn",
"version": "1.0.25",
"version": "1.0.30",
"main": "index.js",
"scripts": {
"build": "expo export -p ios",
@@ -13,41 +13,40 @@
},
"dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@react-native-community/netinfo": "^11.3.1",
"@react-navigation/native": "^6.1.18",
"@react-navigation/native-stack": "^6.11.0",
"@react-native-community/netinfo": "^11.4.1",
"@react-navigation/native": "^7.0.13",
"@react-navigation/native-stack": "^7.1.14",
"base-64": "^1.0.0",
"clsx": "^2.0.0",
"expo": "~51.0.37",
"expo-build-properties": "~0.12.5",
"expo-clipboard": "~6.0.3",
"expo-constants": "~16.0.2",
"expo-crypto": "~13.0.2",
"expo-dev-client": "~4.0.28",
"expo-linking": "~6.3.1",
"expo-secure-store": "~13.0.2",
"expo-status-bar": "~1.12.1",
"expo-web-browser": "~13.0.3",
"expo": "^52.0.0",
"expo-build-properties": "~0.13.1",
"expo-clipboard": "~7.0.0",
"expo-constants": "~17.0.3",
"expo-crypto": "~14.0.1",
"expo-dev-client": "~5.0.5",
"expo-linking": "~7.0.3",
"expo-secure-store": "~14.0.0",
"expo-status-bar": "~2.0.0",
"expo-web-browser": "~14.0.1",
"jazz-react-native": "workspace:*",
"jazz-tools": "workspace:*",
"nativewind": "^2.0.11",
"react": "^18.2.0",
"react-native": "~0.74.5",
"react": "^18.3.1",
"react-native": "~0.76.3",
"react-native-fetch-api": "^3.0.0",
"react-native-get-random-values": "^1.11.0",
"react-native-mmkv": "3.0.1",
"react-native-polyfill-globals": "^3.1.0",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "4.1.0",
"react-native-url-polyfill": "^2.0.0",
"text-encoding": "^0.7.0",
"web-streams-polyfill": "^3.2.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/react": "^18.2.19",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3"
"@types/react": "^18.3.12",
"tailwindcss": "^3.4.9",
"typescript": "~5.6.2"
},
"private": true
}

View File

@@ -51,7 +51,7 @@ function App() {
<StrictMode>
<Jazz.Provider
auth={auth}
peer="wss://cloud.jazz.tools/?key=chat-rn-example-jazz@gcmp.io"
peer="wss://cloud.jazz.tools/?key=chat-rn-example-jazz@garden.co"
storage={undefined}
>
<NavigationContainer linking={linking} ref={navigationRef}>

View File

@@ -1,12 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,jsx,ts,tsx}",
"./components/**/*.{js,jsx,ts,tsx}",
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
};

View File

@@ -1,5 +1,56 @@
# chat-vue
## 0.0.24
### Patch Changes
- Updated dependencies [ac216b9]
- jazz-browser@0.8.41
- jazz-tools@0.8.41
- jazz-vue@0.8.41
## 0.0.23
### Patch Changes
- jazz-browser@0.8.40
- jazz-vue@0.8.40
## 0.0.22
### Patch Changes
- Updated dependencies [e386f2b]
- Updated dependencies [249eecb]
- jazz-browser@0.8.39
- jazz-tools@0.8.39
- jazz-vue@0.8.39
## 0.0.21
### Patch Changes
- jazz-browser@0.8.38
- jazz-tools@0.8.38
- jazz-vue@0.8.38
## 0.0.20
### Patch Changes
- jazz-browser@0.8.37
- jazz-tools@0.8.37
- jazz-vue@0.8.25
## 0.0.19
### Patch Changes
- Updated dependencies [441fe27]
- jazz-tools@0.8.36
- jazz-browser@0.8.36
- jazz-vue@0.8.24
## 0.0.18
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "chat-vue",
"version": "0.0.18",
"version": "0.0.24",
"private": true,
"type": "module",
"scripts": {
@@ -25,14 +25,14 @@
"@vitejs/plugin-vue": "^5.1.4",
"@vitejs/plugin-vue-jsx": "^4.0.1",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.14",
"eslint": "^8.46.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.7.0",
"eslint-plugin-vue": "^9.28.0",
"npm-run-all2": "^6.2.3",
"postcss": "^8.4.27",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10",
"tailwindcss": "^3.4.9",
"typescript": "~5.6.2",
"vite": "^5.4.10",
"vite-plugin-vue-devtools": "^7.4.6",
"vue-tsc": "^2.1.6"
}

View File

@@ -1,7 +1,7 @@
import "./index.css";
import { DemoAuthBasicUI, createJazzVueApp, useDemoAuth } from "jazz-vue";
import { createApp, defineComponent, h } from "vue";
import App from "./App.vue";
import "./index.css";
import router from "./router";
const Jazz = createJazzVueApp();
@@ -18,7 +18,7 @@ const RootComponent = defineComponent({
JazzProvider,
{
auth: authMethod.value,
peer: "wss://mesh.jazz.tools/?key=chat-example-jazz@gcmp.io",
peer: "wss://cloud.jazz.tools/?key=chat-example-jazz@garden.co",
},
{
default: () => h(App),

View File

@@ -1,8 +0,0 @@
/** @type {import('tailwindcss').Config} */
export default {
purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};

View File

@@ -0,0 +1,11 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};
export default config;

View File

@@ -1,5 +1,63 @@
# jazz-example-chat
## 0.0.119
### Patch Changes
- Updated dependencies [3252502]
- Updated dependencies [6370348]
- Updated dependencies [ac216b9]
- cojson@0.8.41
- jazz-react@0.8.41
- jazz-tools@0.8.41
- jazz-browser-media-images@0.8.41
## 0.0.118
### Patch Changes
- jazz-browser-media-images@0.8.40
- jazz-react@0.8.40
## 0.0.117
### Patch Changes
- Updated dependencies [249eecb]
- Updated dependencies [3121551]
- jazz-tools@0.8.39
- cojson@0.8.39
- jazz-browser-media-images@0.8.39
- jazz-react@0.8.39
## 0.0.116
### Patch Changes
- Updated dependencies [b00ee91]
- Updated dependencies [f488c09]
- cojson@0.8.38
- jazz-react@0.8.38
- jazz-tools@0.8.38
## 0.0.115
### Patch Changes
- Updated dependencies [3d9f12e]
- cojson@0.8.37
- jazz-react@0.8.37
- jazz-tools@0.8.37
## 0.0.114
### Patch Changes
- Updated dependencies [441fe27]
- cojson@0.8.36
- jazz-tools@0.8.36
- jazz-react@0.8.36
## 0.0.113
### Patch Changes

View File

@@ -1,4 +1,4 @@
FROM caddy:2.7.3-alpine
LABEL org.opencontainers.image.source="https://github.com/gardencmp/jazz"
LABEL org.opencontainers.image.source="https://github.com/garden-co/jazz"
COPY ./dist /usr/share/caddy/

View File

@@ -1,7 +1,7 @@
{
"name": "jazz-example-chat",
"private": true,
"version": "0.0.113",
"version": "0.0.119",
"type": "module",
"scripts": {
"dev": "vite",
@@ -18,14 +18,15 @@
"@radix-ui/react-toast": "^1.1.4",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"cojson": "workspace:0.8.35",
"cojson": "workspace:0.8.41",
"hash-slash": "workspace:0.2.1",
"jazz-react": "workspace:0.8.35",
"jazz-tools": "workspace:0.8.35",
"jazz-browser-media-images": "workspace:0.8.41",
"jazz-react": "workspace:0.8.41",
"jazz-tools": "workspace:0.8.41",
"lucide-react": "^0.274.0",
"qrcode": "^1.5.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router": "^6.16.0",
"react-router-dom": "^6.16.0",
"react-use": "^17.4.0",
@@ -36,14 +37,14 @@
"devDependencies": {
"@playwright/test": "^1.46.1",
"@types/qrcode": "^1.5.1",
"@types/react": "^18.2.19",
"@types/react-dom": "^18.2.7",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.14",
"autoprefixer": "^10.4.20",
"is-ci": "^3.0.1",
"postcss": "^8.4.27",
"tailwindcss": "3.3.2",
"typescript": "^5.3.3",
"vite": "^5.0.10"
"tailwindcss": "^3.4.9",
"typescript": "~5.6.2",
"vite": "^5.4.10"
}
}

View File

@@ -18,7 +18,7 @@ export function App() {
router.navigate("/#/chat/" + chat.id);
// for https://jazz.tools marketing site demo only
onChatLoad(chat, me);
onChatLoad(chat);
};
return (

View File

@@ -1,21 +1,54 @@
import { createImage } from "jazz-browser-media-images";
import { ID } from "jazz-tools";
import { useState } from "react";
import { useCoState } from "./main.tsx";
import { useAccount, useCoState } from "./main.tsx";
import { Chat, Message } from "./schema.ts";
import {
BubbleBody,
BubbleContainer,
BubbleImage,
BubbleInfo,
BubbleText,
ChatBody,
ChatInput,
EmptyChatMessage,
ImageInput,
InputBar,
TextInput,
} from "./ui.tsx";
export function ChatScreen(props: { chatID: ID<Chat> }) {
const chat = useCoState(Chat, props.chatID, [{}]);
const { me } = useAccount();
const [showNLastMessages, setShowNLastMessages] = useState(30);
return chat ? (
if (!chat)
return (
<div className="flex-1 flex justify-center items-center">Loading...</div>
);
const sendImage = (event: React.ChangeEvent<HTMLInputElement>) => {
if (!me?.profile) return;
const file = event.currentTarget.files?.[0];
if (!file) return;
if (file.size > 5000000) {
alert("Please upload an image less than 5MB.");
return;
}
createImage(file, { owner: chat._owner }).then((image) => {
chat.push(
Message.create(
{ text: file.name, image: image },
{ owner: chat._owner },
),
);
});
};
return (
<>
<ChatBody>
{chat.length > 0 ? (
@@ -35,24 +68,31 @@ export function ChatScreen(props: { chatID: ID<Chat> }) {
</button>
)}
</ChatBody>
<ChatInput
onSubmit={(text) => {
chat.push(Message.create({ text }, { owner: chat._owner }));
}}
/>
<InputBar>
<ImageInput onImageChange={sendImage} />
<TextInput
onSubmit={(text) => {
chat.push(Message.create({ text }, { owner: chat._owner }));
}}
/>
</InputBar>
</>
) : (
<div className="flex-1 flex justify-center items-center">Loading...</div>
);
}
function ChatBubble(props: { msg: Message }) {
const lastEdit = props.msg._edits.text;
const fromMe = lastEdit.by?.isMe;
const { text, image } = props.msg;
return (
<BubbleContainer fromMe={fromMe}>
<BubbleBody fromMe={fromMe}>{props.msg.text}</BubbleBody>
<BubbleBody fromMe={fromMe}>
{image && <BubbleImage image={image} />}
<BubbleText text={text} />
</BubbleBody>
<BubbleInfo by={lastEdit.by?.profile?.name} madeAt={lastEdit.madeAt} />
</BubbleContainer>
);

View File

@@ -13,7 +13,7 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
<>
<Jazz.Provider
auth={auth}
peer="wss://cloud.jazz.tools/?key=chat-example-jazz@gcmp.io"
peer="wss://cloud.jazz.tools/?key=chat-example-jazz@garden.co"
>
{children}
</Jazz.Provider>

View File

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

View File

@@ -1,5 +1,8 @@
import clsx from "clsx";
import { useId } from "react";
import { ProgressiveImg } from "jazz-react";
import { ImageDefinition } from "jazz-tools";
import { ImageIcon } from "lucide-react";
import { useId, useRef } from "react";
export function AppContainer(props: { children: React.ReactNode }) {
return (
@@ -56,7 +59,7 @@ export function BubbleBody(props: {
<div
className={clsx(
"line-clamp-10 text-ellipsis whitespace-pre-wrap",
"rounded-2xl max-w-full py-1 px-3 shadow-sm",
"rounded-2xl overflow-hidden max-w-[calc(100%-5rem)] shadow-sm p-1",
props.fromMe
? "bg-white dark:bg-stone-700 dark:text-white"
: "bg-blue text-white",
@@ -67,6 +70,23 @@ export function BubbleBody(props: {
);
}
export function BubbleText(props: { text: string }) {
return <p className="px-2 leading-relaxed">{props.text}</p>;
}
export function BubbleImage(props: { image: ImageDefinition }) {
return (
<ProgressiveImg image={props.image}>
{({ src }) => (
<img
className="h-auto max-h-[20rem] max-w-full rounded-t-xl mb-1"
src={src}
/>
)}
</ProgressiveImg>
);
}
export function BubbleInfo(props: { by: string | undefined; madeAt: Date }) {
return (
<div className="text-xs text-neutral-500 mt-1.5">
@@ -75,17 +95,59 @@ export function BubbleInfo(props: { by: string | undefined; madeAt: Date }) {
);
}
export function ChatInput(props: { onSubmit: (text: string) => void }) {
export function InputBar(props: { children: React.ReactNode }) {
return (
<div className="p-3 bg-white border-t shadow-2xl mt-auto flex gap-1 dark:bg-transparent dark:border-stone-800">
{props.children}
</div>
);
}
export function ImageInput({
onImageChange,
}: { onImageChange?: (event: React.ChangeEvent<HTMLInputElement>) => void }) {
const inputRef = useRef<HTMLInputElement>(null);
const onUploadClick = () => {
inputRef.current?.click();
};
return (
<>
<button
type="button"
aria-label="Send image"
title="Send image"
onClick={onUploadClick}
className="text-stone-500 p-1.5 rounded-full hover:bg-stone-100 hover:text-stone-800 dark:hover:bg-stone-800 dark:hover:text-stone-200 transition-colors"
>
<ImageIcon size={24} strokeWidth={1.5} />
</button>
<label className="sr-only">
Image
<input
ref={inputRef}
type="file"
accept="image/png, image/jpeg, image/gif"
onChange={onImageChange}
/>
</label>
</>
);
}
export function TextInput(props: { onSubmit: (text: string) => void }) {
const inputId = useId();
return (
<div className="p-3 bg-white border-t shadow-2xl mt-auto dark:bg-transparent dark:border-stone-800">
<div className="flex-1">
<label className="sr-only" htmlFor={inputId}>
Type a message and press Enter
</label>
<input
id={inputId}
className="rounded-full py-2 px-4 border block w-full dark:bg-black dark:text-white dark:border-stone-700"
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"
maxLength={2048}
onKeyDown={({ key, currentTarget: input }) => {

View File

@@ -2,20 +2,10 @@
// This is NOT needed to make the chat work
import { Chat } from "@/schema.ts";
import { Account, CoValue, ID } from "jazz-tools";
export function waitForUpload(id: ID<CoValue>, me: Account) {
const syncManager = me._raw.core.node.syncManager;
const peers = syncManager.getPeers();
return Promise.all(
peers.map((peer) => syncManager.waitForUploadIntoPeer(peer.id, id)),
);
}
export function onChatLoad(chat: Chat, me: Account) {
export function onChatLoad(chat: Chat) {
if (window.parent) {
waitForUpload(chat.id, me).then(() => {
chat.waitForSync().then(() => {
window.parent.postMessage(
{ type: "chat-load", id: "/chat/" + chat.id },
"*",

View File

@@ -1,82 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./app/**/*.{ts,tsx}",
"./src/**/*.{ts,tsx}",
],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
blue: {
700: "#3313F7",
DEFAULT: "#3313F7",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
lineClamp: {
10: "10",
},
},
},
plugins: [require("tailwindcss-animate")],
};

View File

@@ -1,5 +1,7 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
import type { Config } from "tailwindcss";
import animate from "tailwindcss-animate";
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{ts,tsx}",
@@ -58,12 +60,12 @@ module.exports = {
},
keyframes: {
"accordion-down": {
from: { height: 0 },
from: { height: "0" },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
to: { height: "0" },
},
},
animation: {
@@ -72,5 +74,7 @@ module.exports = {
},
},
},
plugins: [require("tailwindcss-animate")],
plugins: [animate],
};
export default config;

View File

@@ -0,0 +1,8 @@
{
"build": {
"env": {
"APP_NAME": "jazz-chat"
}
},
"ignoreCommand": "node ../../ignore-vercel-build.js"
}

View File

@@ -1,5 +1,54 @@
# minimal-auth-clerk
## 0.0.18
### Patch Changes
- jazz-react@0.8.41
- jazz-react-auth-clerk@0.8.41
- jazz-tools@0.8.41
## 0.0.17
### Patch Changes
- jazz-react@0.8.40
- jazz-react-auth-clerk@0.8.40
## 0.0.16
### Patch Changes
- Updated dependencies [249eecb]
- jazz-tools@0.8.39
- jazz-react@0.8.39
- jazz-react-auth-clerk@0.8.39
## 0.0.15
### Patch Changes
- jazz-react@0.8.38
- jazz-react-auth-clerk@0.8.38
- jazz-tools@0.8.38
## 0.0.14
### Patch Changes
- jazz-react@0.8.37
- jazz-react-auth-clerk@0.8.37
- jazz-tools@0.8.37
## 0.0.13
### Patch Changes
- Updated dependencies [441fe27]
- jazz-tools@0.8.36
- jazz-react@0.8.36
- jazz-react-auth-clerk@0.8.36
## 0.0.12
### Patch Changes

View File

@@ -1,4 +1,4 @@
# Passkey authentication example with Jazz and React
# Clerk authentication example with Jazz and React
This is an example of how to use clerk authentication with Jazz.

View File

@@ -1,7 +1,7 @@
{
"name": "clerk",
"private": true,
"version": "0.0.12",
"version": "0.0.18",
"type": "module",
"scripts": {
"dev": "vite",
@@ -12,9 +12,9 @@
},
"dependencies": {
"@clerk/clerk-react": "^5.4.1",
"jazz-tools": "workspace:*",
"jazz-react": "workspace:*",
"jazz-react-auth-clerk": "workspace:0.8.35",
"jazz-react-auth-clerk": "workspace:0.8.41",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1"
},

View File

@@ -28,7 +28,7 @@ function JazzAndAuth({ children }: { children: React.ReactNode }) {
{clerk.user && auth ? (
<Jazz.Provider
auth={auth}
peer="wss://cloud.jazz.tools/?key=minimal-auth-clerk-example@gcmp.io"
peer="wss://cloud.jazz.tools/?key=minimal-auth-clerk-example@garden.co"
>
{children}
</Jazz.Provider>

View File

@@ -0,0 +1,8 @@
{
"build": {
"env": {
"APP_NAME": "clerk-demo"
}
},
"ignoreCommand": "node ../../ignore-vercel-build.js"
}

23
examples/file-share-svelte/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
node_modules
# Output
.output
.vercel
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
playwright-report

View File

@@ -0,0 +1 @@
engine-strict=true

View File

@@ -0,0 +1,4 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock

View File

@@ -0,0 +1,16 @@
{
"useTabs": false,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

View File

@@ -0,0 +1,23 @@
# file-share-svelte
## 0.0.4
### Patch Changes
- jazz-tools@0.8.41
- jazz-svelte@0.8.41
## 0.0.3
### Patch Changes
- jazz-svelte@0.8.40
## 0.0.2
### Patch Changes
- Updated dependencies [249eecb]
- Updated dependencies [aa21072]
- jazz-tools@0.8.39
- jazz-svelte@0.8.39

View File

@@ -0,0 +1,56 @@
# File share example with Jazz and Svelte
This example app demonstrates how to implement secure file sharing in a Svelte application using Jazz.
## Features
This example showcases how to:
- Upload files securely with end-to-end encryption
- Generate and manage sharing links
- Handle file downloads with decryption
- Manage file access permissions
- Authenticate users using passkeys
## Getting Started
1. Clone the repository:
```sh
git clone https://github.com/garden-co/jazz.git
```
2. Navigate to the example directory:
```sh
cd examples/file-share-svelte
```
3. Install dependencies:
```sh
pnpm install
```
4. Run the development server:
```sh
turbo dev
```
5. Open your browser and visit [http://localhost:5173](http://localhost:5173)
---
Alternatively, you can build and preview the app:
```sh
turbo build
pnpm preview
```
## Learn More
- [Jazz Documentation](https://jazz.tools/docs/svelte)
- [Svelte Documentation](https://svelte.dev)
- [WebAuthn API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)

View File

@@ -0,0 +1,33 @@
import js from '@eslint/js';
import prettier from 'eslint-config-prettier';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import ts from 'typescript-eslint';
export default ts.config(
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs['flat/recommended'],
prettier,
...svelte.configs['flat/prettier'],
{
languageOptions: {
globals: {
...globals.browser,
...globals.node
}
}
},
{
files: ['**/*.svelte'],
languageOptions: {
parserOptions: {
parser: ts.parser
}
}
},
{
ignores: ['build/', '.svelte-kit/', 'dist/']
}
);

View File

@@ -0,0 +1,47 @@
{
"name": "file-share-svelte",
"version": "0.0.4",
"private": true,
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check . && eslint .",
"format-and-lint": "pnpm run format && pnpm run lint",
"format-and-lint:fix": "pnpm run format --write && pnpm run lint --fix",
"test": "playwright test",
"test:ui": "playwright test --ui"
},
"devDependencies": {
"@sveltejs/adapter-vercel": "^5.5.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^4.0.1",
"@types/is-ci": "^3.0.4",
"autoprefixer": "^10.4.20",
"eslint": "^9.7.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.36.0",
"globals": "^15.11.0",
"is-ci": "^3.0.1",
"prettier": "^3.3.2",
"prettier-plugin-svelte": "^3.2.6",
"prettier-plugin-tailwindcss": "^0.6.5",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwindcss": "^3.4.9",
"typescript": "~5.6.2",
"typescript-eslint": "^8.0.0",
"vite": "^5.4.10"
},
"dependencies": {
"@tailwindcss/typography": "^0.5.15",
"jazz-svelte": "workspace:*",
"jazz-tools": "workspace:*",
"lucide-svelte": "^0.463.0",
"svelte-sonner": "^0.3.28"
}
}

View File

@@ -0,0 +1,53 @@
import { defineConfig, devices } from "@playwright/test";
import isCI from "is-ci";
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// dotenv.config({ path: path.resolve(__dirname, '.env') });
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: isCI,
/* Retry on CI only */
retries: isCI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: isCI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:5173/",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
permissions: ["clipboard-read", "clipboard-write"],
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
/* Run your local dev server before starting the tests */
webServer: [
{
command: "pnpm preview --port 5173",
url: "http://localhost:5173/",
reuseExistingServer: !isCI,
},
],
});

View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
};

View File

@@ -0,0 +1,3 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

13
examples/file-share-svelte/src/app.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
// See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@@ -0,0 +1,117 @@
<script lang="ts">
import { slide } from 'svelte/transition';
import { SharedFile } from '$lib/schema';
import { FileStream } from 'jazz-tools';
import { File, FileDown, Trash2, Link2 } from 'lucide-svelte';
import { useAccount } from '$lib/jazz';
import { toast } from 'svelte-sonner';
import { formatFileSize } from '$lib/utils';
const {
file,
loading = false,
onDelete
}: {
file: SharedFile;
loading?: boolean;
onDelete: (file: SharedFile) => void;
} = $props();
const { me } = useAccount();
const isAdmin = $derived(me && file._owner?.myRole() === 'admin');
async function downloadFile() {
if (!file._refs.file?.id || !me) {
toast.error('Failed to download file');
return;
}
try {
const fileId = file._refs.file.id;
// Load the file as a blob, can take a while
const blob = await FileStream.loadAsBlob(fileId, me, {});
if (!blob) {
toast.error('Failed to download file');
return;
}
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
toast.success('File downloaded successfully');
} catch (error) {
console.error('Error downloading file:', error);
toast.error('Failed to download file');
}
}
async function shareFile() {
try {
const fileUrl = `${window.location.origin}/file/${file.id}`;
await navigator.clipboard.writeText(fileUrl);
toast.success('Share link copied to clipboard');
} catch (error) {
console.error('Error sharing file:', error);
toast.error('Failed to create share link');
}
}
</script>
<div
class="flex items-center justify-between rounded-lg border border-gray-200 bg-white p-4"
transition:slide={{ duration: 200 }}
>
<div class="flex items-center space-x-4">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600">
<File class="h-6 w-6" />
</div>
<div>
<a href="/file/{file.id}" class="hover:text-blue-600 hover:underline">
<h3 class="font-medium text-gray-900">{file.name}</h3>
</a>
<p class="text-sm text-gray-500">
{isAdmin ? 'Owned by you' : ''} • Uploaded {new Date(
file.createdAt || 0
).toLocaleDateString()}
{formatFileSize(file.size || 0)}
</p>
</div>
</div>
<div class="flex items-center space-x-2">
{#if loading}
<div class="text-sm text-gray-500">Uploading...</div>
{:else}
<button
onclick={downloadFile}
class="rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700"
aria-label="Download file"
>
<FileDown class="h-5 w-5" />
</button>
{#if isAdmin}
<button
onclick={shareFile}
class="rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700"
aria-label="Share file"
>
<Link2 class="h-5 w-5" />
</button>
<button
onclick={() => onDelete(file)}
class="rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 hover:text-red-600"
aria-label="Delete file"
>
<Trash2 class="h-5 w-5" />
</button>
{/if}
{/if}
</div>
</div>

View File

@@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.

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

@@ -0,0 +1,51 @@
import { Account, CoList, CoMap, FileStream, Profile, co, Group } from 'jazz-tools';
export class SharedFile extends CoMap {
name = co.string;
file = co.ref(FileStream);
createdAt = co.Date;
uploadedAt = co.Date;
size = co.number;
}
export class FileShareProfile extends Profile {
name = co.string;
}
export class ListOfSharedFiles extends CoList.Of(co.ref(SharedFile)) {}
export class FileShareAccountRoot extends CoMap {
type = co.string;
sharedFiles = co.ref(ListOfSharedFiles);
publicGroup = co.ref(Group);
}
export class FileShareAccount extends Account {
profile = co.ref(FileShareProfile);
root = co.ref(FileShareAccountRoot);
/** 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.
*/
async migrate(creationProps?: { name: string }) {
super.migrate(creationProps);
await this._refs.root?.load();
// Initialize root if it doesn't exist
if (!this.root || this.root.type !== 'file-share-account') {
// Create a group that will own all shared files
const publicGroup = Group.create({ owner: this });
publicGroup.addMember('everyone', 'reader');
this.root = FileShareAccountRoot.create(
{
type: 'file-share-account',
sharedFiles: ListOfSharedFiles.create([], { owner: publicGroup }),
publicGroup
},
{ owner: this }
);
}
}
}

View File

@@ -0,0 +1,22 @@
/**
* Formats a file size in bytes to a human readable string
* @param bytes The size in bytes
* @returns A formatted string like "1.5 MB"
*/
export function formatFileSize(bytes: number): string {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
}
/**
* Generates a temporary file ID based on the file name and creation time
* @param fileName The name of the file
* @param createdAt The creation date
* @returns A unique file ID string
*/
export function generateTempFileId(fileName: string, createdAt: Date): string {
return `file-${fileName}-${createdAt.getTime()}`;
}

View File

@@ -0,0 +1,32 @@
<script lang="ts">
import { Provider } from '$lib/jazz';
import { PasskeyAuthBasicUI, usePasskeyAuth } from 'jazz-svelte';
import { Toaster } from 'svelte-sonner';
import '../app.css';
let { children } = $props();
const auth = usePasskeyAuth({
appName: 'File Share'
});
</script>
<svelte:head>
<title>File Share</title>
</svelte:head>
<Toaster richColors />
{#if auth.state.state === 'ready'}
<div class="fixed inset-0 flex items-center justify-center bg-gray-50/80">
<div class="rounded-lg bg-white p-8 shadow-lg">
<PasskeyAuthBasicUI state={auth.state} />
</div>
</div>
{/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">
{@render children()}
</div>
</Provider>
{/if}

View File

@@ -0,0 +1,145 @@
<script lang="ts">
import { useAccount, useCoState } from '$lib/jazz';
import { SharedFile, ListOfSharedFiles } from '$lib/schema';
import { createInviteLink } from 'jazz-svelte';
import { FileStream } from 'jazz-tools';
import FileItem from '$lib/components/FileItem.svelte';
import { SvelteMap } from 'svelte/reactivity';
import { generateTempFileId } from '$lib/utils';
import { CloudUpload } from 'lucide-svelte';
const { me, logOut } = useAccount();
const mySharedFilesId = me?.root?._refs.sharedFiles.id;
const sharedFiles = $derived(useCoState(ListOfSharedFiles, mySharedFilesId, [{}]));
let fileInput: HTMLInputElement;
type PendingSharedFile = {
name: string;
id: string;
createdAt: Date;
};
// Track files that are currently uploading
const uploadingFiles = new SvelteMap<string, PendingSharedFile>();
async function handleFileUpload(event: Event) {
const input = event.target as HTMLInputElement;
const files = input.files;
if (!files || !files.length || !me?.root?.sharedFiles || !me.root.publicGroup) return;
const file = files[0];
const fileName = file.name;
const createdAt = new Date();
const fileId = generateTempFileId(fileName, createdAt);
const tempFile: PendingSharedFile = {
name: fileName,
id: fileId,
createdAt
};
// Add to uploading files
uploadingFiles.set(fileId, tempFile);
try {
const ownership = { owner: me.root.publicGroup };
// Create a FileStream from the uploaded file
const fileStream = await FileStream.createFromBlob(file, ownership);
// Create the shared file entry
const sharedFile = SharedFile.create(
{
name: fileName,
file: fileStream,
createdAt,
uploadedAt: new Date(),
size: file.size
},
ownership
);
// Add the file to the user's files list
me.root.sharedFiles.push(sharedFile);
} finally {
uploadingFiles.delete(fileId);
fileInput.value = ''; // reset input
}
}
async function shareFile(file: SharedFile) {
const inviteLink = createInviteLink(file, 'reader');
await navigator.clipboard.writeText(inviteLink);
alert('Share link copied to clipboard!');
}
async function deleteFile(file: SharedFile) {
if (!me?.root?.sharedFiles || !sharedFiles.current) return;
const index = sharedFiles.current.indexOf(file);
if (index > -1) {
me.root.sharedFiles.splice(index, 1);
}
}
</script>
<div class="min-h-screen bg-gray-50">
<div class="container mx-auto max-w-4xl px-4 py-8">
<div class="mb-12 flex items-center justify-between">
<div>
<h1 class="mb-2 text-4xl font-bold text-gray-900">File Share</h1>
<h2 class="text-xl text-gray-600">Welcome back, {me?.profile?.name}</h2>
</div>
<button
onclick={logOut}
class="rounded-lg bg-red-500 px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
>
Log Out
</button>
</div>
<!-- Upload Section -->
<div class="mb-8 rounded-xl bg-white p-6 shadow-sm">
<div
class="group relative flex cursor-pointer flex-col items-center justify-center rounded-lg border-2 border-dashed border-gray-300 bg-white p-12 text-center hover:border-blue-500 hover:bg-blue-50"
onclick={() => fileInput.click()}
onkeydown={(e) => e.key === 'Enter' && fileInput.click()}
role="button"
tabindex="0"
>
<CloudUpload class="mb-2 h-8 w-8 text-gray-400 group-hover:text-blue-600" />
<h3 class="mb-1 text-lg font-medium text-gray-900">Upload a new file</h3>
<p class="text-sm text-gray-500">Click to select a file from your computer</p>
<input
type="file"
bind:this={fileInput}
onchange={handleFileUpload}
class="hidden"
accept="*/*"
/>
</div>
</div>
<!-- Files List -->
<div class="space-y-4">
{#if sharedFiles.current}
{#if !(sharedFiles.current.length === 0 && uploadingFiles.size === 0)}
{#each [...sharedFiles.current, ...uploadingFiles.values()] as file (generateTempFileId(file?.name, file?.createdAt))}
<FileItem
{file}
loading={uploadingFiles.has(generateTempFileId(file?.name, file?.createdAt))}
onShare={shareFile}
onDelete={deleteFile}
/>
{/each}
{:else}
<p class="text-center text-gray-500">No files yet</p>
{/if}
{/if}
</div>
</div>
</div>

View File

@@ -0,0 +1,103 @@
<script lang="ts">
import { page } from '$app/stores';
import { useAccount, useCoState } from '$lib/jazz';
import { SharedFile } from '$lib/schema';
import { File, FileDown, Link2 } from 'lucide-svelte';
import type { ID } from 'jazz-tools';
import { FileStream } from 'jazz-tools';
import { toast } from 'svelte-sonner';
const { me } = useAccount();
const fileId = $page.params.fileId;
const file = $state(useCoState(SharedFile, fileId as ID<SharedFile>, {}));
const isAdmin = $derived(me && file.current?._owner?.myRole() === 'admin');
async function downloadFile() {
if (!file.current?._refs.file?.id || !me) {
toast.error('Failed to download file');
return;
}
try {
const fileId = file.current._refs.file.id;
const blob = await FileStream.loadAsBlob(fileId, me, {});
if (!blob) {
toast.error('Failed to download file');
return;
}
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file.current.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
toast.success('File downloaded successfully');
} catch (error) {
console.error('Error downloading file:', error);
toast.error('Failed to download file');
}
}
async function shareFile() {
try {
const fileUrl = `${window.location.origin}/file/${file.current?.id}`;
await navigator.clipboard.writeText(fileUrl);
toast.success('Share link copied to clipboard');
} catch (error) {
console.error('Error sharing file:', error);
toast.error('Failed to copy share link');
}
}
</script>
<svelte:head>
<title>{file.current?.name} | File Share</title>
</svelte:head>
{#if file.current}
<div class="container mx-auto max-w-3xl p-4">
<div class="rounded-lg bg-white p-6 shadow-md">
<div class="mb-6 flex items-center justify-between">
<div class="flex items-center gap-3">
<File class="h-6 w-6" />
<h1 class="text-2xl font-semibold">{file.current.name}</h1>
</div>
<div class="flex gap-2">
{#if isAdmin}
<button
onclick={shareFile}
class="flex items-center gap-2 rounded-md bg-gray-100 px-4 py-2 text-gray-700 hover:bg-gray-200"
>
<Link2 class="h-4 w-4" />
Share
</button>
{/if}
{#if file.current._refs.file}
<button
onclick={downloadFile}
class="flex items-center gap-2 rounded-md bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
>
<FileDown class="h-4 w-4" />
Download
</button>
{/if}
</div>
</div>
<p class="text-gray-600">
{isAdmin ? 'You own this file' : 'Shared with you'} • Uploaded {new Date(
file.current.createdAt || 0
).toLocaleDateString()}
</p>
</div>
</div>
{:else}
<div class="container mx-auto max-w-3xl p-4">
<div class="rounded-lg bg-white p-6 shadow-md">
<p class="text-gray-600">Loading file...</p>
</div>
</div>
{/if}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -0,0 +1,15 @@
import adapter from '@sveltejs/adapter-vercel';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
adapter: adapter()
}
};
export default config;

View File

@@ -0,0 +1,12 @@
import typography from '@tailwindcss/typography';
import type { Config } from 'tailwindcss';
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: [typography]
} satisfies Config;

View File

@@ -0,0 +1 @@
This is a test file for e2e testing

View File

@@ -0,0 +1,82 @@
import { expect, test } from '@playwright/test';
import type { BrowserContext } from 'playwright-core';
import path from 'path';
async function mockAuthenticator(context: BrowserContext) {
await context.addInitScript(() => {
Object.defineProperty(window.navigator, 'credentials', {
value: {
...window.navigator.credentials,
create: async () => ({
type: 'public-key',
id: new Uint8Array([1, 2, 3, 4]),
rawId: new Uint8Array([1, 2, 3, 4]),
response: {
clientDataJSON: new Uint8Array([1]),
attestationObject: new Uint8Array([2])
}
}),
get: async () => ({
type: 'public-key',
id: new Uint8Array([1, 2, 3, 4]),
rawId: new Uint8Array([1, 2, 3, 4]),
response: {
authenticatorData: new Uint8Array([1]),
clientDataJSON: new Uint8Array([2]),
signature: new Uint8Array([3])
}
})
},
configurable: true
});
});
}
// Configure the authenticator
test.beforeEach(async ({ context }) => {
// Enable virtual authenticator environment
await mockAuthenticator(context);
});
test('can login with passkey and upload file', async ({ page, browser }) => {
// Navigate to the home page
await page.goto('/');
// Click login and handle the passkey authentication
await page.getByRole('textbox').fill('Capitan Hook');
await page.getByRole('button', { name: "Sign up" }).click();
// Verify successful login by checking for user-specific element
await expect(page.getByText("File Share")).toBeVisible();
// Prepare file upload
const filePath = path.join(import.meta.dirname, 'fixtures/test-file.txt');
// Click upload button and handle file selection
const fileChooserPromise = page.waitForEvent('filechooser');
await page.getByRole('button', { name: /upload|add file/i }).click();
const fileChooser = await fileChooserPromise;
await fileChooser.setFiles(filePath);
// Verify the uploaded file appears in the list
await expect(page.getByText('test-file.txt')).toBeVisible();
await page.getByRole('button', { name: 'Share file' }).click();
const inviteLink = await page.evaluate(() => navigator.clipboard.readText());
// Create a new incognito instance and try to load the shared file
const newContext = await browser.newContext();
await mockAuthenticator(newContext);
const newUserPage = await newContext.newPage();
await newUserPage.goto(`/`);
await newUserPage.getByRole('textbox').fill('Mr. Smee');
await newUserPage.getByRole('button', { name: "Sign up" }).click();
await expect(newUserPage.getByText("File Share")).toBeVisible();
await newUserPage.goto(inviteLink);
await expect(newUserPage.getByText("test-file.txt")).toBeVisible();
});

View File

@@ -0,0 +1,19 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}

View File

@@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [sveltekit()],
});

27
examples/form/.gitignore vendored Normal file
View File

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

View File

@@ -0,0 +1,16 @@
# form
## 0.0.14
### Patch Changes
- jazz-react@0.8.41
- jazz-tools@0.8.41
- jazz-browser-media-images@0.8.41
## 0.0.13
### Patch Changes
- jazz-browser-media-images@0.8.40
- jazz-react@0.8.40

50
examples/form/README.md Normal file
View File

@@ -0,0 +1,50 @@
# Form example with Jazz and React
Live version: [https://form-demo.jazz.tools](https://form-demo.jazz.tools)
This is a simple form example that shows you how to make a form for creating and editing a `CoValue`,
called `BubbleTeaOrder`, with fields of different types such
as single-select, multi-select, date, text, and boolean.
To create a new `BubbleTeaOrder`, we create an empty order. Because `BubbleTeaOrder` has some
required fields, we can't create an empty `BubbleTeaOrder` directly.
Instead, we create a `DraftBubbleTeaOrder`,
which has the same structure as `BubbleTeaOrder`, but with all fields set to `optional`.
When the user is ready to submit the order, we treat `DraftBubbleTeaOrder` as a "real order" by
converting it into a `BubbleTeaOrder`.
## Installing & running the example locally
(This requires `pnpm` to be installed, see [https://pnpm.io/installation](https://pnpm.io/installation))
Start by downloading the [jazz repository](https://github.com/garden-co/jazz):
```bash
npx degit gardencmp/jazz jazz
```
Go to the form example directory:
```bash
cd jazz/examples/form
```
Install and build dependencies:
```bash
pnpm i && npx turbo build
```
Start the dev server:
```bash
pnpm dev
```
## 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 the `<Jazz.Provider>` provider component in [./src/main.tsx](./src/main.tsx).

12
examples/form/index.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en" class="h-full">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jazz | Form example</title>
</head>
<body class="h-full flex flex-col bg-white text-stone-700 dark:text-stone-400 dark:bg-stone-925">
<div id="root" class="align-self-center flex-1"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -0,0 +1,37 @@
{
"name": "form",
"private": true,
"version": "0.0.14",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"format-and-lint": "biome check .",
"format-and-lint:fix": "biome check . --write"
},
"dependencies": {
"hash-slash": "workspace:*",
"jazz-browser-media-images": "workspace:*",
"jazz-react": "workspace:*",
"jazz-tools": "workspace:*",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.41.5"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@playwright/test": "^1.46.1",
"@tailwindcss/forms": "^0.5.9",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"autoprefixer": "^10.4.20",
"is-ci": "^3.0.1",
"globals": "^15.11.0",
"postcss": "^8.4.27",
"tailwindcss": "^3.4.9",
"typescript": "~5.6.2",
"vite": "^5.4.10"
}
}

View File

@@ -0,0 +1,46 @@
import { defineConfig, devices } from "@playwright/test";
import isCI from "is-ci";
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: isCI,
/* Retry on CI only */
retries: isCI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: isCI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:5173/",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
permissions: ["clipboard-read", "clipboard-write"],
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
/* Run your local dev server before starting the tests */
webServer: [
{
command: "pnpm preview --port 5173",
url: "http://localhost:5173/",
reuseExistingServer: !isCI,
},
],
});

View File

@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

40
examples/form/src/App.tsx Normal file
View File

@@ -0,0 +1,40 @@
import { useIframeHashRouter } from "hash-slash";
import { ID } from "jazz-tools";
import { CreateOrder } from "./CreateOrder.tsx";
import { EditOrder } from "./EditOrder.tsx";
import { Orders } from "./Orders.tsx";
import { useAccount } from "./main";
import { BubbleTeaOrder } from "./schema.ts";
function App() {
const { me, logOut } = useAccount();
const router = useIframeHashRouter();
return (
<>
<header>
<nav className="container py-2 border-b flex items-center justify-between">
<span>
You're logged in as <strong>{me?.profile?.name}</strong>
</span>
<button
className="bg-stone-100 py-1.5 px-3 text-sm rounded-md dark:bg-stone-900 dark:text-white"
onClick={() => logOut()}
>
Log out
</button>
</nav>
</header>
<main className="container py-8 space-y-8">
{router.route({
"/": () => <Orders />,
"/order": () => <CreateOrder />,
"/order/:id": (id) => <EditOrder id={id as ID<BubbleTeaOrder>} />,
})}
</main>
</>
);
}
export default App;

View File

@@ -0,0 +1,77 @@
import { useIframeHashRouter } from "hash-slash";
import { ID } from "jazz-tools";
import { useState } from "react";
import { Errors } from "./Errors.tsx";
import { LinkToHome } from "./LinkToHome.tsx";
import { OrderForm } from "./OrderForm.tsx";
import { useAccount, useCoState } from "./main.tsx";
import {
BubbleTeaOrder,
DraftBubbleTeaOrder,
ListOfBubbleTeaAddOns,
} from "./schema.ts";
export function CreateOrder() {
const { me } = useAccount({ profile: { draft: {}, orders: [] } });
const router = useIframeHashRouter();
const [errors, setErrors] = useState<string[]>([]);
if (!me?.profile) return;
const onSave = (draft: DraftBubbleTeaOrder) => {
// validate if the draft is a valid order
const validation = draft.validate();
setErrors(validation.errors);
if (validation.errors.length > 0) {
return;
}
// turn the draft into a real order
me.profile.orders.push(draft as BubbleTeaOrder);
// reset the draft
me.profile.draft = DraftBubbleTeaOrder.create(
{
addOns: ListOfBubbleTeaAddOns.create([], { owner: me.profile._owner }),
},
{ owner: me.profile._owner },
);
router.navigate("/");
};
return (
<>
<LinkToHome />
<h1 className="text-lg">
<strong>Make a new bubble tea order 🧋</strong>
</h1>
<Errors errors={errors} />
<CreateOrderForm id={me?.profile?.draft.id} onSave={onSave} />
</>
);
}
function CreateOrderForm({
id,
onSave,
}: {
id: ID<DraftBubbleTeaOrder>;
onSave: (draft: DraftBubbleTeaOrder) => void;
}) {
const draft = useCoState(DraftBubbleTeaOrder, id, {
addOns: [],
});
if (!draft) return;
const addOrder = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
onSave(draft);
};
return <OrderForm order={draft} onSave={addOrder} />;
}

View File

@@ -0,0 +1,15 @@
import { useAccount } from "./main.tsx";
export function DraftIndicator() {
const { me } = useAccount({
profile: { draft: {} },
});
if (me?.profile.draft?.hasChanges) {
return (
<div className="absolute -top-1 -right-1 bg-blue-500 border-2 border-white w-3 h-3 rounded-full dark:border-stone-925">
<span className="sr-only">You have a draft</span>
</div>
);
}
}

View File

@@ -0,0 +1,26 @@
import { ID } from "jazz-tools";
import { LinkToHome } from "./LinkToHome.tsx";
import { OrderForm } from "./OrderForm.tsx";
import { OrderThumbnail } from "./OrderThumbnail.tsx";
import { useCoState } from "./main.tsx";
import { BubbleTeaOrder } from "./schema.ts";
export function EditOrder(props: { id: ID<BubbleTeaOrder> }) {
const order = useCoState(BubbleTeaOrder, props.id, []);
if (!order) return;
return (
<>
<LinkToHome />
<OrderThumbnail order={order} />
<h1 className="text-lg">
<strong>Edit your bubble tea order 🧋</strong>
</h1>
<OrderForm order={order} />
</>
);
}

View File

@@ -0,0 +1,13 @@
export function Errors({ errors }: { errors: string[] }) {
if (errors.length === 0) return null;
return (
<div className="rounded-md bg-red-50 border border-red-50 p-4 text-sm text-red-600 dark:bg-transparent dark:border-red-500 dark:text-red-500">
<ul role="list" className="list-disc space-y-1 pl-5">
{errors.map((error, i) => (
<li key={i}>{error}</li>
))}
</ul>
</div>
);
}

View File

@@ -0,0 +1,7 @@
export function LinkToHome() {
return (
<a href="/#" className="text-sm text-stone-600">
&lt; Back to all orders
</a>
);
}

View File

@@ -0,0 +1,107 @@
import {
BubbleTeaAddOnTypes,
BubbleTeaBaseTeaTypes,
BubbleTeaOrder,
DraftBubbleTeaOrder,
} from "./schema.ts";
export function OrderForm({
order,
onSave,
}: {
order: BubbleTeaOrder | DraftBubbleTeaOrder;
onSave?: (e: React.FormEvent<HTMLFormElement>) => void;
}) {
return (
<form onSubmit={onSave} className="grid gap-5">
<div className="flex flex-col gap-2">
<label htmlFor="baseTea">Base tea</label>
<select
name="baseTea"
id="baseTea"
value={order.baseTea || ""}
className="dark:bg-transparent"
onChange={(e) => (order.baseTea = e.target.value as any)}
required
>
<option value="" disabled>
Please select your preferred base tea
</option>
{BubbleTeaBaseTeaTypes.map((teaType) => (
<option key={teaType} value={teaType}>
{teaType}
</option>
))}
</select>
</div>
<fieldset>
<legend className="mb-2">Add-ons</legend>
{BubbleTeaAddOnTypes.map((addOn) => (
<div key={addOn} className="flex items-center gap-2">
<input
type="checkbox"
value={addOn}
name={addOn}
id={addOn}
checked={order.addOns?.includes(addOn) || false}
onChange={(e) => {
if (e.target.checked) {
order.addOns?.push(addOn);
} else {
order.addOns?.splice(order.addOns?.indexOf(addOn), 1);
}
}}
/>
<label htmlFor={addOn}>{addOn}</label>
</div>
))}
</fieldset>
<div className="flex flex-col gap-2">
<label htmlFor="deliveryDate">Delivery date</label>
<input
type="date"
name="deliveryDate"
id="deliveryDate"
className="dark:bg-transparent"
value={order.deliveryDate?.toISOString().split("T")[0] || ""}
onChange={(e) => (order.deliveryDate = new Date(e.target.value))}
required
/>
</div>
<div className="flex items-center gap-2">
<input
type="checkbox"
name="withMilk"
id="withMilk"
checked={order.withMilk}
onChange={(e) => (order.withMilk = e.target.checked)}
/>
<label htmlFor="withMilk">With milk?</label>
</div>
<div className="flex flex-col gap-2">
<label htmlFor="instructions">Special instructions</label>
<textarea
name="instructions"
id="instructions"
value={order.instructions}
className="dark:bg-transparent"
onChange={(e) => (order.instructions = e.target.value)}
></textarea>
</div>
{onSave && (
<button
type="submit"
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
>
Submit
</button>
)}
</form>
);
}

View File

@@ -0,0 +1,28 @@
import { BubbleTeaOrder } from "./schema.ts";
export function OrderThumbnail({ order }: { order: BubbleTeaOrder }) {
const { id, baseTea, addOns, instructions, deliveryDate, withMilk } = order;
const date = deliveryDate.toLocaleDateString();
return (
<a
href={`/#/order/${id}`}
className="border p-3 flex justify-between items-start gap-3"
>
<div>
<strong>
{baseTea} {withMilk ? "milk " : ""} tea
</strong>
{addOns && addOns?.length > 0 && (
<p className="text-sm text-stone-600">
with {addOns?.join(", ").toLowerCase()}
</p>
)}
{instructions && (
<p className="text-sm text-stone-600 italic">{instructions}</p>
)}
</div>
<div className="text-sm text-stone-600">{date}</div>
</a>
);
}

View File

@@ -0,0 +1,37 @@
import { DraftIndicator } from "./DraftIndicator.tsx";
import { OrderThumbnail } from "./OrderThumbnail.tsx";
import { useAccount } from "./main.tsx";
export function Orders() {
const { me } = useAccount({
profile: { orders: [] },
});
return (
<>
<section className="space-y-5">
<a
href={`/#/order`}
className="block relative p-3 bg-white border text-center rounded-md dark:bg-stone-900"
>
<strong>Add new order</strong>
<DraftIndicator />
</a>
<div className="space-y-3">
<h1 className="text-lg pb-2 border-b mb-3">
<strong>Your orders 🧋</strong>
</h1>
{me?.profile?.orders?.length ? (
me?.profile?.orders.map((order) =>
order ? <OrderThumbnail key={order.id} order={order} /> : null,
)
) : (
<p>You have no orders yet.</p>
)}
</div>
</section>
</>
);
}

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