340 Commits

Author SHA1 Message Date
cb4a03015a feat: backup script 2025-05-19 21:08:22 +01:00
7f8b345e77 ios stuff 2025-05-12 21:27:21 +01:00
df9c42136e feat: submodule 2025-05-12 20:57:17 +01:00
019c4c6b0c chore: removing unnecessary comment 2025-05-12 20:51:21 +01:00
ad2a70aaf3 feat: multiple listeners on channels
Multiple device notifications supported.

Actually beautiful
2025-05-12 20:51:06 +01:00
076e230a01 feat: making SSE work on mobiles 2025-05-12 20:11:58 +01:00
636bd9df0e wipwipwip 2025-05-12 19:54:09 +01:00
3eab20049e fix: back button 2025-05-11 16:19:18 +01:00
64879ac9d6 wip 2025-05-11 16:16:18 +01:00
e674043daa wip 2025-05-11 16:15:15 +01:00
71049a7f26 vibe coding screenshot sharing 2025-05-11 15:18:21 +01:00
e8a51ecc52 fix: the reason this wasn't working
This was also silent failing, so should probably have a look at it
2025-05-11 14:30:31 +01:00
a6a6026a11 Merge branch 'ios/testflight-account' of ssh://192.168.1.111:2222/JohnCosta27/Haystack into ios/testflight-account 2025-05-10 22:19:28 +01:00
a9749f062e feat: setting up a different share extension
idk what happened to the old one
2025-05-10 22:18:49 +01:00
5a2b990c0c fix: adding extension hack
fix
2025-05-10 22:05:24 +01:00
b97eae10a3 hack: allowing demo@email.com to login straight away for test flight submittion 2025-05-10 21:03:32 +01:00
cc07ef983f feat: correctly re-requesting 2025-05-10 17:42:23 +01:00
b4a0383be7 chore: no more processing image stuff 2025-05-10 17:40:16 +01:00
a4b94fc6c2 feat: frontend receiving processing images and showing them as such 2025-05-10 17:39:09 +01:00
71dfe5647e feat: adding processing image component 2025-05-10 16:57:02 +01:00
90b863b6cf feat: frontend notification manager 2025-05-10 16:43:30 +01:00
64439d9041 feat: using struct to send notification and improved image model 2025-05-10 16:03:31 +01:00
2f3d643278 feat: not deleting images to process 2025-05-10 15:12:25 +01:00
8e6424aa63 feat: sending notifications 2025-05-10 15:04:11 +01:00
c69ca7da5c chore: adding log to check error 2025-05-10 14:30:26 +01:00
7b0c84e88e feat: adding allowed keys to only send when we have a userId
This is to prevent users that aren't connected to the socket (somehow),
to not fill up memory with buffered messages we'll never need.
2025-05-10 14:29:48 +01:00
ff7960e2dd feat: notifier module with buffered channels 2025-05-10 14:21:18 +01:00
d08fd452f9 chore: git ignore 2025-05-10 13:35:11 +01:00
0d64e90bbf fix: android intents 2025-05-08 18:05:38 +01:00
a7119dfda4 fix 2025-05-08 18:05:15 +01:00
c0f6af7a05 hack: setting prod url to build macos app 2025-05-08 18:04:56 +01:00
ac92f80dc6 feat: IOS stuff 2025-05-08 10:18:33 +01:00
52cb50b168 hack: using prod url 2025-05-08 09:52:46 +01:00
eaa029cce1 fix 2025-05-08 09:52:04 +01:00
9a7654ae2d fix: logs 2025-05-08 09:44:44 +01:00
a9ab92b7b3 key 2025-05-07 16:26:40 +01:00
378900d1b1 feat: better UI when clicking on cards 2025-05-07 13:15:49 +01:00
4fa8bfb7bd fix: UI for images 2025-05-07 10:36:36 +01:00
ac4fd30b0a feat: entity dialog extract out 2025-05-07 10:31:16 +01:00
7d1498c3eb fix: login UI 2025-05-07 10:21:17 +01:00
ce32291437 fix: allowing date created to be null 2025-05-07 10:21:13 +01:00
33b8d51f89 fix: adding full height to cards 2025-05-07 10:21:07 +01:00
a2ba328097 feat: adding a back button 2025-05-05 17:18:28 +01:00
23d91890f5 wip: UI to show image and associated properties
wip

fix
2025-05-05 16:24:36 +01:00
07b83aa728 feat: allowing user to get a list of their images
feat: UI to show and organise user images
2025-05-05 16:24:15 +01:00
9c325c7799 feat: adding timestamps to all important tables 2025-05-05 15:38:05 +01:00
7970e8670c refactor(App.tsx): re-enable event listener setup for Android platform 2025-05-04 14:06:35 +02:00
2deba39907 chore: update .DS_Store binary file 2025-05-04 14:06:23 +02:00
0a766e1ebb feat: add bun.lockb and refactor App.tsx for improved event handling 2025-05-04 13:57:43 +02:00
6119938e52 mini just is better :( 2025-05-04 10:19:39 +01:00
a8d12b5d53 fix: sending multiple images at the same time 2025-05-04 10:14:20 +01:00
ce8d546447 fix: not sleeping 2025-05-04 10:07:31 +01:00
b57a703812 feat: improving search 2025-05-04 09:56:41 +01:00
6952aa16da feat: refresh button 2025-05-03 19:03:24 +01:00
63e3081a69 feat(tray-menu): for screenshot 2025-05-03 18:56:01 +01:00
b046a928b0 feat: using gpt-4.1-mini
feat: createExistingContact

feat: using nano instead of mini so I don't run out of money instantly
2025-05-03 18:25:35 +01:00
9860dd2dc5 feat(agents): providing a seed so it has more predictable results 2025-05-03 17:31:55 +01:00
94920c01fb fix: unique android app name 2025-05-03 15:11:12 +01:00
bb280f52fe feat: android version correctly working alongside iOS version 2025-05-03 13:16:28 +01:00
92e346578a chore: removing submodule of forked version of sharetarget 2025-05-03 13:00:22 +01:00
e9617f86ec feat: only saving token on iOS 2025-05-03 12:46:40 +01:00
875d1d778c chore: cleaning up code to allow all platforms to co-exist 2025-05-03 12:43:47 +01:00
372a891f97 feat: iOS sharing is now working 2025-05-03 11:21:58 +01:00
9ea466610b fix 2025-05-03 11:14:57 +01:00
9fb926db03 fixc 2025-05-03 11:03:46 +01:00
50b8645897 fix: build 2025-05-03 11:02:00 +01:00
4541b366e5 fix 2025-05-03 11:01:10 +01:00
4ed42678f1 fix: naming 2025-05-03 10:59:06 +01:00
a93fd7500a fix: permissions 2025-05-03 10:54:29 +01:00
b50ca077e0 fix 2025-05-03 10:51:21 +01:00
12cd338967 debugging 2025-05-03 10:51:15 +01:00
2a838c81f2 feat: extension code to send image to servers 2025-05-03 10:40:36 +01:00
cd39559834 changes 2025-05-03 10:40:08 +01:00
4c5f3d92e6 fix: app grup id 2025-05-03 10:39:35 +01:00
54bb75956c feat: app group + share extension 2025-05-03 10:26:04 +01:00
0a2d27c150 wip 2025-05-01 18:45:59 +01:00
a05a625516 wip 2025-05-01 18:43:41 +01:00
7e9b33f625 wip(ios): correct command and permissions 2025-05-01 18:40:30 +01:00
9f3a2a473a FIXUP: removing target 2025-05-01 18:23:06 +01:00
61e9258538 feat: saveToken plugin for app groups on iOS
This will allow the share extension to access the Bearer token to send
images to the backend.
2025-05-01 18:20:26 +01:00
c8d9ae7aff wip: using local package for development 2025-05-01 16:14:20 +01:00
2eda77827a wip: showing the file name 2025-05-01 15:50:03 +01:00
afd2e03234 wip: forking sharetarget plugin to add iOS support 2025-05-01 15:30:00 +01:00
3a3acc4a1c fix(ios): fully working mobile versions
fix

fix

fix

testing

testing

fix
2025-04-29 17:27:34 +01:00
d102ab3f6e feat: managing dependencies and building on different platforms 2025-04-29 16:48:04 +01:00
9b006836c6 fix: holy motherfucking shit that took so long 2025-04-29 15:31:32 +01:00
385a0cd186 feat(ios): adding iOS build files 2025-04-27 17:06:54 +01:00
365ef387dd feat(os-info): only showing screenshot button on linux 2025-04-27 15:01:37 +01:00
4922df6682 fix(sse): some bugs 2025-04-27 14:56:06 +01:00
a9ecd5818a fix: re-requesting image when all agents are done
This means the agents are no longer parallel. Which will eventually be a
bottleneck, but I need to spend a bit more time on allowing for it to be
parallel, but now is not the time.

TODO: add a ticket
2025-04-27 14:45:23 +01:00
84d66a1c3b shameful comment 2025-04-26 20:36:10 +01:00
d34805030f feat: frontend responding to backend SSE and refetching images 2025-04-26 20:32:01 +01:00
78a28dee8d fix: working http client 2025-04-26 17:17:19 +01:00
7f7a2975af fix
wip

fix
2025-04-26 17:08:33 +01:00
151142fa9b feat: linux screenshots 2025-04-26 16:12:48 +01:00
fa187b3a79 fix: rebasing errors 2025-04-26 11:51:22 +01:00
b27e191e5c feat(processing-image): displaying initial status from response 2025-04-26 11:47:51 +01:00
e2a4b85d15 WIP: not closing channels quite yet 2025-04-26 11:47:33 +01:00
f1500837e0 feat: request to get a singular image 2025-04-26 11:47:33 +01:00
e6c027aca7 fix: returning correct array of entity deps 2025-04-26 11:47:33 +01:00
495cd742b0 feat(frontend): validators 2025-04-26 11:47:33 +01:00
8cdb4367c7 feat: returning better values to frontend 2025-04-26 11:47:33 +01:00
1388383909 feat(sql): model function to allow user to request image properties based on events 2025-04-26 11:47:33 +01:00
3cd60d4dfc feat(sse): adding info logs 2025-04-26 11:47:33 +01:00
526044d1e3 fix(sse): sending correctly formatted events & exiting function 2025-04-26 11:47:33 +01:00
90ea845521 feat: bringing back shortcuts 2025-04-26 11:47:33 +01:00
dcd3bbb4fb chore(platforms): seperating permissions and inits on different platforms 2025-04-26 11:47:30 +01:00
7aef91c5e0 feat(images): share target working and receiving images! 2025-04-26 11:47:20 +01:00
9245187056 feat: working android dev environment 2025-04-26 11:47:05 +01:00
e84655a181 wip: working release sdk 2025-04-26 11:46:35 +01:00
9a25d2e839 wip: sorting out various versioning problems 2025-04-26 11:46:27 +01:00
f02b22f2fa BIGWIP(android): trying to make an android release
fucking stupid shit why is it so hard
2025-04-26 11:46:09 +01:00
6e9dc81e2b fix: rebasing errors 2025-04-26 11:45:19 +01:00
08b4175b73 fix: mobile entry point cfg_attr + java sdk versions 2025-04-26 11:44:02 +01:00
fa5d38d796 feat(share-target): seperate component to handle sharing 2025-04-26 11:44:02 +01:00
fdb607caea feat: bringing back shortcuts 2025-04-26 11:44:02 +01:00
169b95c450 chore(platforms): seperating permissions and inits on different platforms 2025-04-26 11:43:57 +01:00
191ed3db40 fix: backend err 2025-04-26 11:43:37 +01:00
88bb2fafe2 feat: sending image to the backend 2025-04-26 11:43:37 +01:00
a859abfc17 feat(images): share target working and receiving images! 2025-04-26 11:43:37 +01:00
8cad29a661 feat: working android dev environment 2025-04-26 11:43:10 +01:00
a5d74a97a6 wip: working release sdk 2025-04-26 11:43:00 +01:00
cf71d26f14 wip: sorting out various versioning problems 2025-04-26 11:43:00 +01:00
7e31af27f1 BIGWIP(android): trying to make an android release
fucking stupid shit why is it so hard
2025-04-26 11:43:00 +01:00
78fe25497b refactor(image-viewer): update ImageViewer component structure and remove commented code 2025-04-22 22:13:40 +02:00
dc83bdb3fb feat(screenshot): implement area screenshot functionality and integrate with shortcut management 2025-04-22 22:04:26 +02:00
f6f31540af feat(shortcuts): add screenshot shortcut management and registration 2025-04-22 21:36:37 +02:00
2eb346bb6a feat(shortcuts): improve global shortcut management and documentation 2025-04-22 21:00:48 +02:00
2b022c31cb feat(image-viewer): enhance window focus and visibility handling in ImageViewer component 2025-04-22 20:56:08 +02:00
c3f4403145 fix(linux-tauri): window building on linux 2025-04-19 15:42:14 +01:00
1d07fa271d wip(logs): displaying image
WIP because we need to bypass authorization here
2025-04-19 14:06:05 +01:00
839a1af51b feat(logs): route to view the logs for each image 2025-04-19 14:03:18 +01:00
0324216753 chore(code): cleaning 2025-04-19 12:16:48 +01:00
335d4403f1 feat(logging): split logging to stdout & database to allow us to view it on webbrowser 2025-04-19 12:14:04 +01:00
89ba950c5b fix: enabling note agent 2025-04-19 10:30:49 +01:00
2b8e0695c6 feat(events): a better prompt with good integration with location agent 2025-04-19 10:30:29 +01:00
d448a41a9f feat(contacts): not creating duplicates 2025-04-19 10:07:51 +01:00
a69d4e4d55 feat(location): prompt tweak + going back to faster model 2025-04-18 15:36:51 +01:00
6edc1e2915 feat(location): correctly updating an image if it contains a duplicate locatino 2025-04-18 15:32:07 +01:00
57f1e70c98 feat(agents): improving rationality by adding tool to allow the models to think through choices.
This works pretty nicely actually. I'm starting to understand how to
demistify the system prompt and have the tools the agent needs to do a
good job.
2025-04-18 15:06:20 +01:00
1b1f957e01 wip 2025-04-18 14:21:23 +01:00
49969b0608 feat(location-agent): using createLocation instead of updateLocation to simplify 2025-04-18 13:26:42 +01:00
9b95ffb59e feat(contact-agent): using createContact with an ID field to provide updates 2025-04-17 18:57:13 +01:00
c9560f6881 feat(event-agent): update events function 2025-04-17 18:19:54 +01:00
c5535a5b3b feat(location-agent): seperating the tool to allow for replying
This means it makes less mistakes and doesnt get as confused.
2025-04-17 18:09:00 +01:00
5ab0d13b21 fix(location-events): adding location id to the database from agent call 2025-04-17 15:32:50 +01:00
15289e4965 feat(prompts): adding better prompts & restoring tool_stop
Mistral's models seem to do something really strange if you allow for
`tool_choice` to be anything but `any`. They start putting the tool call
inside the `content` instead of an actual tool call. This means that I
need this `stop` mechanism using a tool call instead because I cannot
trust the model to do it by itself.

I quite like this model though, it's cheap, it's fast and it's open
source. And all the answers are pretty good!
2025-04-17 15:24:21 +01:00
181da1f09d feat(orchestrator): removing the end tool call
fix
2025-04-17 13:00:39 +01:00
90b90a8185 chore: removing unnecessary logging 2025-04-17 13:00:24 +01:00
fb30eb4ad6 wip(orchestrator): improving orchestrator system prompt and tool description 2025-04-17 12:52:54 +01:00
5454a1cfaf feat(event-location): communicating using tool calls correctly 2025-04-17 11:15:02 +01:00
3716d22eca fix(logger): nil pointer error + log debug level clean 2025-04-17 11:07:37 +01:00
6d2f0c6108 refactor(agents): not returning an error on factory method 2025-04-17 11:02:11 +01:00
61c158d5b6 refactor(agents): encapsulating prompt and calls inside factory method 2025-04-17 10:58:19 +01:00
82331c0833 fix: using correct eventAgent instead of orchestrator bug + better logging 2025-04-17 10:48:30 +01:00
e42aa75639 refactor(agents): no need to wrap them in another struct 2025-04-17 10:36:11 +01:00
fa486153b4 feat: event agent calling location agent about location ID
This is pretty nice. We can now have agents spawn other agents and
actually get super cool functionality from it.

The pattern might be a little fragile.
2025-04-16 14:43:07 +01:00
aacecfffac wip(agents): allowing event agent to call location agent 2025-04-15 16:44:00 +01:00
e89a342751 feat: Adding text message to describe an action3 2025-04-15 16:43:27 +01:00
e16b6f4529 fix 2025-04-14 20:08:07 +01:00
6ddae3426d rollback: not using link functions as they are very problematic 2025-04-14 10:59:08 +01:00
67468bddb6 fix(network): restore conditional base URL for development environment
- Reintroduced conditional logic for the base URL to switch between local and production endpoints based on the environment.
2025-04-14 11:41:29 +02:00
10bc0a04a2 Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-04-14 11:41:11 +02:00
8a57236f04 ffix 2025-04-14 10:40:02 +01:00
b138661991 prompt 2025-04-14 10:38:25 +01:00
6db9bb2ab3 Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-04-14 11:37:34 +02:00
6ae2458186 refactor(network): simplify base URL and clean up validators
- Updated the base URL to a fixed production endpoint, removing the conditional logic for development.
- Commented out Location and Organizer validations in the eventValidator for future consideration.
- Added a console log in getUserImages to assist with backend response tracking.
2025-04-14 11:37:29 +02:00
51d36bf15b more prompt 2025-04-14 10:36:21 +01:00
ecc2da5f86 fix more prompt 2025-04-14 10:33:56 +01:00
d7ab3f56dc stupid 2025-04-14 10:30:46 +01:00
55aa1e67ba horrible 2025-04-14 10:30:21 +01:00
1f83b721a6 fix: prompts 2025-04-14 10:28:31 +01:00
0596ea2b1e debug 2025-04-14 10:22:54 +01:00
3c1f6ba40f fix(network): update base URL for development and production environments
- Changed the base URL to use localhost for development and the production URL for other environments.
- Added Location validation back into the eventValidator and removed commented-out code for clarity.
- Cleaned up debugging logs in getUserImages function.
2025-04-14 10:56:32 +02:00
0eff145f02 push 2025-04-14 09:55:50 +01:00
1fa1db7d1b Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-04-14 10:54:24 +02:00
a1369719d7 feat(search): improve Search component with conditional rendering and debugging logs
- Added conditional rendering for the "No results found" message using the Show component.
- Introduced debugging logs in getUserImages and Search component to track data flow.
- Cleaned up the data mapping process in getUserImages for better readability.
2025-04-14 10:54:18 +02:00
40ddf737c8 pushhh 2025-04-14 09:54:09 +01:00
ad14254ecb debnug 2025-04-14 09:50:03 +01:00
e8d996cec5 debug 2025-04-14 09:44:29 +01:00
0ed6b4c123 debug 2025-04-14 09:44:19 +01:00
0bc556f47c Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-04-14 10:36:58 +02:00
5a530b2e39 feat(login): implement logout functionality and redirect after login
- Added a logout function in the Settings component to clear user session data and redirect to the login page.
- Updated the Login component to redirect to the home page upon successful login.
- Adjusted styling in the Search component for better spacing in the "No results found" message.
2025-04-14 10:36:55 +02:00
868c8e6409 fix 2025-04-14 09:31:27 +01:00
30143019d6 feat: making all codes upper case + fetching fixes 2025-04-14 09:28:08 +01:00
cd5dd347d3 fix 2025-04-14 09:15:48 +01:00
ab09378fcd chore: removing SQL debug 2025-04-14 09:12:16 +01:00
18f85a8929 feat(search): enhance Search component with shortcuts and item modal
- Added functionality to fetch and display global shortcuts in the Search component.
- Introduced ItemModal for displaying detailed information about selected items.
- Updated SearchCard components to improve layout and information presentation.
- Enhanced user experience with better styling and accessibility features.
2025-04-14 10:03:37 +02:00
55614b34c7 feat(image-viewer): integrate ImageViewer component and update FolderPicker layout
- Added ImageViewer component to the App for displaying processed images.
- Updated FolderPicker layout for improved user guidance and aesthetics.
- Refactored ShortcutItem and Shortcuts components for better structure and clarity.
- Introduced ItemModal component for future use.
2025-04-14 09:25:53 +02:00
664918f431 Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-04-14 08:55:42 +02:00
048fc38032 refactor(settings): reorganize FolderPicker component and update layout
- Moved FolderPicker to a new folder structure for better organization.
- Updated the Settings page layout to enhance visual hierarchy by increasing the title size.
- Removed the old FolderPicker component file after restructuring.
2025-04-14 08:55:36 +02:00
2f26b5dfd9 feat(app): restructure routing and implement Search component
- Refactored the App component to streamline routing using the Router and Route components.
- Introduced a new Search component to handle search functionality, including input handling and result display.
- Removed inline search logic from the App component for better separation of concerns.
- Updated index.tsx to render the App component directly, simplifying the routing structure.
2025-04-14 08:47:57 +02:00
4f6c198307 feat: registering users if their email is not known 2025-04-13 22:29:25 +01:00
c99d6e4e6b feat(app): refactor App component and add Settings page
- Refactored the App component to utilize a new SearchCard component for rendering search results.
- Introduced a Settings page with FolderPicker and Shortcuts components for user configuration.
- Removed the ImagePage component as it was no longer needed.
- Updated routing to include the new Settings page and adjusted imports accordingly.
- Added a settings button to the main interface for easy access to the new settings functionality.
2025-04-13 22:48:26 +02:00
b97cf63484 feat(search): add autofocus to search input and emit focus event on shortcut
- Added autofocus attribute to the search input field for improved user experience.
- Updated global shortcut handling to emit a "focus-search" event when the shortcut is triggered, enhancing the application's responsiveness to user actions.
- Updated dependencies in Cargo.toml to specific beta versions for better compatibility.
2025-04-13 21:57:36 +02:00
7af536bd9c feat(capabilities): add localhost URL to default permissions
- Updated the default capabilities configuration to allow access to http://localhost:3040 in addition to the existing https://haystack.johncosta.tech URL.
2025-04-13 21:28:14 +02:00
5406e79fc8 chore: update dependencies and add new packages
- Updated several dependencies in Cargo.lock to their latest versions, including `anyhow`, `ashpd`, `bitflags`, `chrono`, and `http`.
- Added new dependencies such as `tauri-plugin-http`, `cookie_store`, and `h2`.
- Removed outdated dependencies related to `wayland` and updated the `windows` related packages for better compatibility.
2025-04-13 21:24:20 +02:00
0e88f77474 Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-04-13 21:21:43 +02:00
878a47ffd1 refactor: using tauri http client 2025-04-13 19:34:02 +01:00
eba4268718 fix 2025-04-13 19:18:07 +01:00
5ae6a3403f chore: removing old agent that was messy and too coupled
chore
2025-04-13 16:30:20 +01:00
3156cea904 feat(event): seperate event agent 2025-04-13 16:30:20 +01:00
d432d16752 feat(location): agent to create locations 2025-04-13 16:30:20 +01:00
98328be39d fix(email) 2025-04-13 16:28:40 +01:00
4d903f40bf feat: add global shortcut functionality and update dependencies
- Introduced global shortcut management in the Tauri application, allowing users to set, change, and unregister shortcuts.
- Added new dependencies for global shortcut functionality in Cargo.toml and updated package.json.
- Enhanced the default capabilities to include global shortcut permissions.
- Refactored the main application logic to integrate the new shortcut features.
2025-04-13 16:40:04 +02:00
24bed2aafb Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-04-13 16:20:32 +02:00
349dcc2275 feat: update app description and enhance folder watching functionality
- Updated the app description in package.json and Cargo.toml to "Screenshots that organize themselves".
- Refactored the Tauri backend to introduce a new command for handling folder selection and watching for PNG file changes.
- Added utility functions for processing PNG files and managing the watcher state.
- Improved the frontend by integrating an ImageViewer component and setting up event listeners for search input focus.
2025-04-13 16:19:51 +02:00
47c871523d feat(sse): very rough events. Not used in the client yet
feat(sse): very rough events. Not used in the client yet
2025-04-13 14:27:59 +01:00
dcfed6a746 Revert "FIXUP wip: notifications on starting progress"
This reverts commit 91b9e5402e9f153348f1326ee269533e1e47f777.
2025-04-12 15:57:36 +01:00
91b9e5402e FIXUP wip: notifications on starting progress 2025-04-12 15:55:58 +01:00
cf7d5e0305 chore: removing unused files 2025-04-12 14:44:16 +01:00
9bb07c1b9b fix: tests 2025-04-12 14:43:01 +01:00
959b741fcb refactor(agent): main agent loop extracted away
Still not super sure how to represent these agents in code.
It doesn't make the most amount of sense to keep them in structs. A
curried function is more like it, with system prompt and tooling.

Maybe that's what I'll end up doing.
2025-04-12 14:39:16 +01:00
91cc54aaec fix(event) 2025-04-12 14:15:07 +01:00
d786ab15c9 fix(orchestrator): better describing the note taking agent 2025-04-12 07:53:43 +01:00
47e65e1609 fix(notes): improving note taking capabilities 2025-04-12 07:48:42 +01:00
91dd2f54ef fix(log): removing access token logging 2025-04-12 07:46:07 +01:00
42771ea958 feat(contact-agent): linking to existing instead of creating new ones 2025-04-12 07:29:29 +01:00
77a0901352 fix: removing extra log line 2025-04-12 07:22:35 +01:00
a43efa014f feat(log): pretty logging agent responses and tool calls 2025-04-12 07:16:30 +01:00
4990cf9c43 feat(contact-agent): working contact agent
Built this in under 20 minutes. Getting some really good agents
2025-04-11 21:12:06 +01:00
9660c99a14 feat: contacts working 2025-04-11 20:31:51 +01:00
f89de6db50 feat(authorization): e2e working authorization 2025-04-11 19:58:25 +01:00
6290c4b843 feat: checking user authorization on image retrieval 2025-04-11 19:41:36 +01:00
fba1618888 wip(token): verifying user when getting the image 2025-04-11 19:35:49 +01:00
5fee1f9ccc fix: not using cookies anymore
I think Tauri doesn't like it very much
2025-04-11 13:27:19 +01:00
3960203d26 feat(cookies): using HTTP setCookie instead of manually doing it 2025-04-11 11:34:32 +01:00
2302ba5eeb feat: minimal UI for login 2025-04-11 11:08:33 +01:00
c9a6c83649 feat(jwt): validating token 2025-04-10 15:49:53 +01:00
3294c1854c feat(jwt): adding access and refresh token generation 2025-04-10 15:35:35 +01:00
29a5adb40a feat(email): endpoint for sending auth code 2025-04-09 18:24:26 +01:00
51dc8daf35 wip(email-auth): auth and email modules 2025-04-09 18:13:49 +01:00
a22c56fd2c refactor: moving image listener to own function 2025-04-09 17:20:27 +01:00
11c5c8921b feat(orchestrator): async processing and ending the loop3 2025-04-09 15:23:51 +01:00
1a503c8320 fix(tool-calls): ToolLoop 2025-04-09 15:15:31 +01:00
f169fd2ba2 fix(tools): testing and processing
fix
2025-04-09 13:56:30 +01:00
d36dec8d60 fix(types): agent processing stuff 2025-04-09 12:12:09 +01:00
e065492dd4 feat(chat): more simplified chat messages and tool handling 2025-04-09 12:04:44 +01:00
26c6edb6ba fixup(chat): better way to organize agent messages and tool calls 2025-04-06 20:24:40 +01:00
5c5df168ad fix(tools): dont error if AI invested a tool 2025-04-05 15:04:09 +01:00
e101070851 refactor(tools): removing pointer map
This is not needed
2025-04-05 14:59:50 +01:00
5278727c51 feat(tools): return error to agent if any happened 2025-04-05 14:58:38 +01:00
9a354c38a5 test(tools): more robust multiple tool call handling 2025-04-05 14:52:31 +01:00
cd8375ce0f test(tools): starting test suite for tools 2025-04-05 14:35:54 +01:00
6549643340 feat(orchestrator): calling needed agents when it needs to 2025-04-05 11:01:43 +01:00
33fb206e2f fix(tool): raw text not scaling so well ey? 2025-04-04 22:50:19 +01:00
49f1990341 refactor(agents): working e2e now
I guess some repeated code doesnt hurt anyone, if it keeps things
simpler. Trying to be fancy with the interfaces didn't work so well.
2025-04-04 22:40:45 +01:00
40392e6da3 refactor(tool-calls): to be handled more generally 2025-04-04 22:17:58 +01:00
d3bc840555 refactor(ai-client): moving tool handling and client into seperate folders 2025-04-04 22:03:46 +01:00
ede5f16dc1 wip(orchestrator): basic scaffolding for the agent 2025-04-04 20:40:31 +01:00
75132503c0 feat: sample data 2025-04-02 17:32:52 +00:00
393eaea2f4 feat(notes): allowing frontend to save 2025-04-01 20:54:15 +00:00
a385ef21cf feat(notes): saving the notes for any images for easy text searching 2025-04-01 20:45:43 +00:00
a37818fc49 feat(events): search through organizer 2025-04-01 19:59:17 +00:00
0d3f86532e feat: adding rawData search 2025-04-01 19:48:06 +00:00
55e50d31ca fix(validators): allowing location in event fields 2025-04-01 19:33:31 +00:00
1b2a99a3c8 fix: adding location to general query 2025-04-01 19:32:55 +00:00
ae62d2bea5 Merge branch 'integrating-frontend' 2025-04-01 19:30:51 +00:00
0126125837 fix 2025-03-31 20:17:14 +00:00
c5278554cc feat(contacts): events can now have organizers 2025-03-31 18:40:36 +00:00
bb5f2bc2fe feat(schema): basic contact tables 2025-03-31 18:10:04 +00:00
b7ed4e2169 chore(imports): organisation 2025-03-31 18:03:02 +00:00
c609b45d99 feat(cards): adjusting for backend data types 2025-03-31 17:49:17 +00:00
c817654f3e feat(events): adding start and end times 2025-03-31 17:32:55 +00:00
3f53317c06 feat(schema): removing coordinates and adding start times to events
.
2025-03-31 16:44:42 +00:00
254edf3421 fix(backend): SQL statements without returns 2025-03-26 16:51:46 +00:00
0814e19a68 refactor(validators): frontend to new schema 2025-03-26 16:51:35 +00:00
382a1f53bd feat: attaching both to image 2025-03-26 16:22:23 +00:00
f90876f499 feat: creating events and attaching locations 2025-03-26 16:16:48 +00:00
caf168c7a1 feat(frontend): add new search card components and update styling
- Introduced new search card components for Contact, Event, Location, Note, Receipt, and Website.
- Updated the App component to utilize these new components for displaying search results.
- Changed the default font from Manrope to Switzer and updated related styles.
- Added a new dependency `solid-motionone` to package.json.
- Improved search functionality with a new sample data structure and enhanced search logic.
2025-03-23 21:56:09 +01:00
4c85f1de79 refactor(frontend): clean up App component and improve search functionality 2025-03-23 19:10:18 +01:00
410df01b4d feat(tool-calling) Big refactor on how tool calling is handled
these commits are too big
2025-03-22 20:46:26 +00:00
13e5ed9f9e feat(locations): allowing AI to attach it to the image 2025-03-22 17:47:02 +00:00
dfb4b34de3 feat(location): working e2e with tool calling 2025-03-22 12:22:31 +00:00
7b6c7090f8 feat(tool-calls): listLocation tool call handling 2025-03-22 11:14:00 +00:00
87869543f7 feat: using tools for event loocation agent 2025-03-22 10:12:51 +00:00
1cd4698969 refactor(naming): using Agent instead of openai 2025-03-21 17:07:00 +00:00
4ea817e81f fix: docker image 2025-03-21 14:49:51 +00:00
3541a4755c wip(frontend): adding more information 2025-03-21 14:36:03 +00:00
ea5802b61b fix: app to re-include images 2025-03-21 14:23:38 +00:00
cf703f3eee fix: re-adding location to event
Figured it out
2025-03-21 14:08:06 +00:00
84881c5c2d fix: simplifying query
I do have some learning to do about go-jet specifically.

I can't include the Location field on events, because the QRM will add
any location to the events
2025-03-21 14:01:21 +00:00
992a8ea282 feat: frontend validation 2025-03-21 13:44:42 +00:00
f7382b0d2b feat: returning events and locations from end point 2025-03-20 18:34:11 +00:00
47dd025ae3 feat: working e2e solution 2025-03-20 17:59:00 +00:00
f114ca06d8 merging 2025-03-19 09:46:52 +00:00
20213ff17b feat: adding events and locations to json schema 2025-03-19 09:46:42 +00:00
9932568986 feat(events): also working 2025-03-18 18:37:12 +00:00
3a0f93e406 feat(locations): now working 2025-03-18 18:18:01 +00:00
b09063f74a refactor(text,tags,links): to foreign key to image instead of user_image 2025-03-18 17:48:38 +00:00
b3b37d252d wip: add sample data and types 2025-03-17 22:20:26 +01:00
3c71fddbd2 fix: linter and format issues
format
2025-03-17 21:16:40 +01:00
a3e1db3d77 Merge branch 'main' of https://git.johncosta.tech/JohnCosta27/Haystack 2025-03-17 21:01:15 +01:00
5a766b8371 wip 2025-03-17 21:00:52 +01:00
fd804ae515 fix: frontend parsers 2025-03-16 18:41:26 +00:00
4b120982d0 fix: returning whole tag object 2025-03-16 18:29:15 +00:00
7582e4d8d9 fix: returns correct image ID 2025-03-16 18:20:29 +00:00
8acf25a2a7 refactor(models): using more organised structure 2025-03-16 18:13:30 +00:00
e505a1617e Merge branch 'main' of https://github.com/dimuuu/haystack-app 2025-03-13 17:25:16 +01:00
028e45bb7a wip 2025-03-13 17:24:53 +01:00
536a49fe1c feat(tags): correctly inserting new tags and adding them to images 2025-03-11 22:47:28 +00:00
40e854fb87 feat(tags): creating and getting user tags 2025-03-11 21:23:41 +00:00
5df6c67ee5 feat: new schema to support user tags better 2025-03-11 20:29:56 +00:00
05263d1089 fix: actually searching properly 2025-03-08 15:50:21 +00:00
1bc1b79042 feat: better result display 2025-03-08 15:42:16 +00:00
863716c096 feat: super basic image search 2025-03-08 15:37:10 +00:00
53ebbb6e8d feat: sending images and receiving them is now working 2025-03-08 13:13:05 +00:00
bf07c18fd7 feat: sending base64 image to backend
This is silly, but binary is apparently hard to do????
2025-03-08 12:30:16 +00:00
d212584486 wip: dialog to choose folder to watch 2025-03-08 11:58:25 +00:00
1424ec22f4 fix: using json response header 2025-03-07 14:14:40 +00:00
e595783d89 wip: Using mistral instead of OpenAi 2025-03-07 13:42:50 +00:00
2df18869e5 chore: running format 2025-02-26 21:27:43 +00:00
ee69d9c2fe feat: network file with validators for backend requests 2025-02-26 21:27:37 +00:00
7e7f3ff732 feat: making prompt be more generic with tags 2025-02-26 20:53:12 +00:00
3fe48464e4 feat: using different prompt 2025-02-26 20:49:55 +00:00
d1d6ee6762 fix: some spam from get images request 2025-02-26 20:48:52 +00:00
ad61b8e1fa fix: getting user images 2025-02-26 20:09:19 +00:00
d8095b0c67 refactor: tables for image and processing_image
This allows a single table to be used to process images, meaning if
anything happens to the system we can always return to polling the
database and process these images individually.

Because of this we also want an `image` table to contain the actual
binary data for the image, so we aren't selecting and writing it each
time, as it is potentially a bottleneck.
2025-02-26 20:01:56 +00:00
410270e217 refactor: using chi router + bug fixes 2025-02-26 18:04:30 +00:00
5bec6c9590 fix: actually saving to the correct db table 2025-02-26 15:54:27 +00:00
971f705288 fix: actually returning all the user images
fix
2025-02-24 21:19:59 +00:00
13ebd80ce9 chore: documentation 2025-02-24 21:04:25 +00:00
b99432c202 feat: saving AI information to database 2025-02-24 21:00:05 +00:00
ee0587a16b feat: method for getting images 2025-02-24 20:05:56 +00:00
64f6bde6a9 feat: methods to get image 2025-02-24 20:02:58 +00:00
f49589907a feat: instructions for docker compose 2025-02-24 20:02:54 +00:00
2115da85b5 feat: working docker image and compose file 2025-02-24 19:44:19 +00:00
43092fa4f5 feat: using parsing on response 2025-02-24 19:05:11 +00:00
46e4043994 chore: updating gitignore
fix
2025-02-24 19:01:18 +00:00
24ef31e00f feat: parsing response from open ai
bruh
2025-02-24 19:01:18 +00:00
993fbb30eb build very basic ui 2025-02-23 22:16:41 +01:00
8cc7e4002f some updates 2025-02-23 20:11:58 +01:00
1fc1079484 messing around with ui 2025-02-23 20:02:06 +01:00
df16298b1f added a bunch of frontend things 2025-02-23 19:30:11 +01:00
f4690b52a9 Merge branch 'main' of https://github.com/dimuuu/haystack-app 2025-02-23 14:59:04 +01:00
81590fe622 some window ui tweaks 2025-02-23 14:59:01 +01:00
97b1619b01 refactor: moving all files to backend 2025-02-22 23:30:59 +00:00
c0ce4892cd Merge branch 'main' of github.com:dimuuu/haystack-app 2025-02-22 23:29:49 +00:00
90431f824a add biome 2025-02-22 16:41:52 +01:00
fe60149769 v0 2025-02-22 16:30:41 +01:00
165 changed files with 6510 additions and 1372 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,38 @@
---
description:
globs:
alwaysApply: true
---
You are an expert AI programming assistant focused on producing clean, readable TypeScript and Rust code for modern cross-platform desktop apps.
Use these rules for any code under /frontend folder.
You always use the latest versions of Tauri, Rust, SolidJS, and you're fluent in their latest features, best practices, and patterns.
You give accurate, thoughtful answers and think like a real dev—step-by-step.
Follow the users specs exactly. If a specs folder exists, check it before coding.
Begin with a detailed pseudo-code plan and confirm it with the user before writing actual code.
Write correct, complete, idiomatic, secure, performant, and bug-free code.
Prioritize readability unless performance is explicitly required.
Fully implement all requested features—no TODOs, stubs, or placeholders.
Use TypeScript's type system thoroughly for clarity and safety.
Style with TailwindCSS using utility-first principles.
Use Kobalte components effectively, building with Solids reactive model in mind.
Offload performance-heavy logic to Rust and ensure smooth integration with Tauri.
Guarantee tight coordination between SolidJS, Tauri, and Rust for a polished desktop UX.
When needed, provide bash scripts to generate config files or folder structures.
Be concise—cut the fluff.
If there's no solid answer, say so. If you're unsure, don't guess—own it.

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "haystack"]
path = haystack-arch
url = https://aur.archlinux.org/haystack

View File

@ -12,7 +12,9 @@ import "github.com/go-jet/jet/v2/postgres"
var Progress = &struct { var Progress = &struct {
NotStarted postgres.StringExpression NotStarted postgres.StringExpression
InProgress postgres.StringExpression InProgress postgres.StringExpression
Complete postgres.StringExpression
}{ }{
NotStarted: postgres.NewEnumValue("not-started"), NotStarted: postgres.NewEnumValue("not-started"),
InProgress: postgres.NewEnumValue("in-progress"), InProgress: postgres.NewEnumValue("in-progress"),
Complete: postgres.NewEnumValue("complete"),
} }

View File

@ -9,6 +9,7 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type Contacts struct { type Contacts struct {
@ -17,4 +18,5 @@ type Contacts struct {
Description *string Description *string
PhoneNumber *string PhoneNumber *string
Email *string Email *string
CreatedAt *time.Time
} }

View File

@ -20,4 +20,5 @@ type Events struct {
EndDateTime *time.Time EndDateTime *time.Time
LocationID *uuid.UUID LocationID *uuid.UUID
OrganizerID *uuid.UUID OrganizerID *uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type ImageContacts struct { type ImageContacts struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
ImageID uuid.UUID ImageID uuid.UUID
ContactID uuid.UUID ContactID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type ImageEvents struct { type ImageEvents struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
EventID uuid.UUID EventID uuid.UUID
ImageID uuid.UUID ImageID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type ImageLocations struct { type ImageLocations struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
LocationID uuid.UUID LocationID uuid.UUID
ImageID uuid.UUID ImageID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type ImageNotes struct { type ImageNotes struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
ImageID uuid.UUID ImageID uuid.UUID
NoteID uuid.UUID NoteID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,6 +9,7 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type Locations struct { type Locations struct {
@ -16,4 +17,5 @@ type Locations struct {
Name string Name string
Address *string Address *string
Description *string Description *string
CreatedAt *time.Time
} }

View File

@ -9,9 +9,11 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type Logs struct { type Logs struct {
Log string Log string
ImageID uuid.UUID ImageID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,6 +9,7 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type Notes struct { type Notes struct {
@ -16,4 +17,5 @@ type Notes struct {
Name string Name string
Description *string Description *string
Content string Content string
CreatedAt *time.Time
} }

View File

@ -14,11 +14,13 @@ type Progress string
const ( const (
Progress_NotStarted Progress = "not-started" Progress_NotStarted Progress = "not-started"
Progress_InProgress Progress = "in-progress" Progress_InProgress Progress = "in-progress"
Progress_Complete Progress = "complete"
) )
var ProgressAllValues = []Progress{ var ProgressAllValues = []Progress{
Progress_NotStarted, Progress_NotStarted,
Progress_InProgress, Progress_InProgress,
Progress_Complete,
} }
func (e *Progress) Scan(value interface{}) error { func (e *Progress) Scan(value interface{}) error {
@ -37,6 +39,8 @@ func (e *Progress) Scan(value interface{}) error {
*e = Progress_NotStarted *e = Progress_NotStarted
case "in-progress": case "in-progress":
*e = Progress_InProgress *e = Progress_InProgress
case "complete":
*e = Progress_Complete
default: default:
return errors.New("jet: Invalid scan value '" + enumValue + "' for Progress enum") return errors.New("jet: Invalid scan value '" + enumValue + "' for Progress enum")
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type UserContacts struct { type UserContacts struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
UserID uuid.UUID UserID uuid.UUID
ContactID uuid.UUID ContactID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type UserEvents struct { type UserEvents struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
EventID uuid.UUID EventID uuid.UUID
UserID uuid.UUID UserID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type UserImages struct { type UserImages struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
ImageID uuid.UUID ImageID uuid.UUID
UserID uuid.UUID UserID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type UserLocations struct { type UserLocations struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
LocationID uuid.UUID LocationID uuid.UUID
UserID uuid.UUID UserID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -9,10 +9,12 @@ package model
import ( import (
"github.com/google/uuid" "github.com/google/uuid"
"time"
) )
type UserNotes struct { type UserNotes struct {
ID uuid.UUID `sql:"primary_key"` ID uuid.UUID `sql:"primary_key"`
UserID uuid.UUID UserID uuid.UUID
NoteID uuid.UUID NoteID uuid.UUID
CreatedAt *time.Time
} }

View File

@ -22,6 +22,7 @@ type contactsTable struct {
Description postgres.ColumnString Description postgres.ColumnString
PhoneNumber postgres.ColumnString PhoneNumber postgres.ColumnString
Email postgres.ColumnString Email postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -67,8 +68,9 @@ func newContactsTableImpl(schemaName, tableName, alias string) contactsTable {
DescriptionColumn = postgres.StringColumn("description") DescriptionColumn = postgres.StringColumn("description")
PhoneNumberColumn = postgres.StringColumn("phone_number") PhoneNumberColumn = postgres.StringColumn("phone_number")
EmailColumn = postgres.StringColumn("email") EmailColumn = postgres.StringColumn("email")
allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, PhoneNumberColumn, EmailColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, PhoneNumberColumn, EmailColumn} allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, PhoneNumberColumn, EmailColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, PhoneNumberColumn, EmailColumn, CreatedAtColumn}
) )
return contactsTable{ return contactsTable{
@ -80,6 +82,7 @@ func newContactsTableImpl(schemaName, tableName, alias string) contactsTable {
Description: DescriptionColumn, Description: DescriptionColumn,
PhoneNumber: PhoneNumberColumn, PhoneNumber: PhoneNumberColumn,
Email: EmailColumn, Email: EmailColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -24,6 +24,7 @@ type eventsTable struct {
EndDateTime postgres.ColumnTimestamp EndDateTime postgres.ColumnTimestamp
LocationID postgres.ColumnString LocationID postgres.ColumnString
OrganizerID postgres.ColumnString OrganizerID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -71,8 +72,9 @@ func newEventsTableImpl(schemaName, tableName, alias string) eventsTable {
EndDateTimeColumn = postgres.TimestampColumn("end_date_time") EndDateTimeColumn = postgres.TimestampColumn("end_date_time")
LocationIDColumn = postgres.StringColumn("location_id") LocationIDColumn = postgres.StringColumn("location_id")
OrganizerIDColumn = postgres.StringColumn("organizer_id") OrganizerIDColumn = postgres.StringColumn("organizer_id")
allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, StartDateTimeColumn, EndDateTimeColumn, LocationIDColumn, OrganizerIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, StartDateTimeColumn, EndDateTimeColumn, LocationIDColumn, OrganizerIDColumn} allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, StartDateTimeColumn, EndDateTimeColumn, LocationIDColumn, OrganizerIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, StartDateTimeColumn, EndDateTimeColumn, LocationIDColumn, OrganizerIDColumn, CreatedAtColumn}
) )
return eventsTable{ return eventsTable{
@ -86,6 +88,7 @@ func newEventsTableImpl(schemaName, tableName, alias string) eventsTable {
EndDateTime: EndDateTimeColumn, EndDateTime: EndDateTimeColumn,
LocationID: LocationIDColumn, LocationID: LocationIDColumn,
OrganizerID: OrganizerIDColumn, OrganizerID: OrganizerIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -20,6 +20,7 @@ type imageContactsTable struct {
ID postgres.ColumnString ID postgres.ColumnString
ImageID postgres.ColumnString ImageID postgres.ColumnString
ContactID postgres.ColumnString ContactID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -63,8 +64,9 @@ func newImageContactsTableImpl(schemaName, tableName, alias string) imageContact
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
ImageIDColumn = postgres.StringColumn("image_id") ImageIDColumn = postgres.StringColumn("image_id")
ContactIDColumn = postgres.StringColumn("contact_id") ContactIDColumn = postgres.StringColumn("contact_id")
allColumns = postgres.ColumnList{IDColumn, ImageIDColumn, ContactIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{ImageIDColumn, ContactIDColumn} allColumns = postgres.ColumnList{IDColumn, ImageIDColumn, ContactIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{ImageIDColumn, ContactIDColumn, CreatedAtColumn}
) )
return imageContactsTable{ return imageContactsTable{
@ -74,6 +76,7 @@ func newImageContactsTableImpl(schemaName, tableName, alias string) imageContact
ID: IDColumn, ID: IDColumn,
ImageID: ImageIDColumn, ImageID: ImageIDColumn,
ContactID: ContactIDColumn, ContactID: ContactIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -17,9 +17,10 @@ type imageEventsTable struct {
postgres.Table postgres.Table
// Columns // Columns
ID postgres.ColumnString ID postgres.ColumnString
EventID postgres.ColumnString EventID postgres.ColumnString
ImageID postgres.ColumnString ImageID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -60,20 +61,22 @@ func newImageEventsTable(schemaName, tableName, alias string) *ImageEventsTable
func newImageEventsTableImpl(schemaName, tableName, alias string) imageEventsTable { func newImageEventsTableImpl(schemaName, tableName, alias string) imageEventsTable {
var ( var (
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
EventIDColumn = postgres.StringColumn("event_id") EventIDColumn = postgres.StringColumn("event_id")
ImageIDColumn = postgres.StringColumn("image_id") ImageIDColumn = postgres.StringColumn("image_id")
allColumns = postgres.ColumnList{IDColumn, EventIDColumn, ImageIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{EventIDColumn, ImageIDColumn} allColumns = postgres.ColumnList{IDColumn, EventIDColumn, ImageIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{EventIDColumn, ImageIDColumn, CreatedAtColumn}
) )
return imageEventsTable{ return imageEventsTable{
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...), Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
//Columns //Columns
ID: IDColumn, ID: IDColumn,
EventID: EventIDColumn, EventID: EventIDColumn,
ImageID: ImageIDColumn, ImageID: ImageIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -20,6 +20,7 @@ type imageLocationsTable struct {
ID postgres.ColumnString ID postgres.ColumnString
LocationID postgres.ColumnString LocationID postgres.ColumnString
ImageID postgres.ColumnString ImageID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -63,8 +64,9 @@ func newImageLocationsTableImpl(schemaName, tableName, alias string) imageLocati
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
LocationIDColumn = postgres.StringColumn("location_id") LocationIDColumn = postgres.StringColumn("location_id")
ImageIDColumn = postgres.StringColumn("image_id") ImageIDColumn = postgres.StringColumn("image_id")
allColumns = postgres.ColumnList{IDColumn, LocationIDColumn, ImageIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{LocationIDColumn, ImageIDColumn} allColumns = postgres.ColumnList{IDColumn, LocationIDColumn, ImageIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{LocationIDColumn, ImageIDColumn, CreatedAtColumn}
) )
return imageLocationsTable{ return imageLocationsTable{
@ -74,6 +76,7 @@ func newImageLocationsTableImpl(schemaName, tableName, alias string) imageLocati
ID: IDColumn, ID: IDColumn,
LocationID: LocationIDColumn, LocationID: LocationIDColumn,
ImageID: ImageIDColumn, ImageID: ImageIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -17,9 +17,10 @@ type imageNotesTable struct {
postgres.Table postgres.Table
// Columns // Columns
ID postgres.ColumnString ID postgres.ColumnString
ImageID postgres.ColumnString ImageID postgres.ColumnString
NoteID postgres.ColumnString NoteID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -60,20 +61,22 @@ func newImageNotesTable(schemaName, tableName, alias string) *ImageNotesTable {
func newImageNotesTableImpl(schemaName, tableName, alias string) imageNotesTable { func newImageNotesTableImpl(schemaName, tableName, alias string) imageNotesTable {
var ( var (
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
ImageIDColumn = postgres.StringColumn("image_id") ImageIDColumn = postgres.StringColumn("image_id")
NoteIDColumn = postgres.StringColumn("note_id") NoteIDColumn = postgres.StringColumn("note_id")
allColumns = postgres.ColumnList{IDColumn, ImageIDColumn, NoteIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{ImageIDColumn, NoteIDColumn} allColumns = postgres.ColumnList{IDColumn, ImageIDColumn, NoteIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{ImageIDColumn, NoteIDColumn, CreatedAtColumn}
) )
return imageNotesTable{ return imageNotesTable{
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...), Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
//Columns //Columns
ID: IDColumn, ID: IDColumn,
ImageID: ImageIDColumn, ImageID: ImageIDColumn,
NoteID: NoteIDColumn, NoteID: NoteIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -21,6 +21,7 @@ type locationsTable struct {
Name postgres.ColumnString Name postgres.ColumnString
Address postgres.ColumnString Address postgres.ColumnString
Description postgres.ColumnString Description postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -65,8 +66,9 @@ func newLocationsTableImpl(schemaName, tableName, alias string) locationsTable {
NameColumn = postgres.StringColumn("name") NameColumn = postgres.StringColumn("name")
AddressColumn = postgres.StringColumn("address") AddressColumn = postgres.StringColumn("address")
DescriptionColumn = postgres.StringColumn("description") DescriptionColumn = postgres.StringColumn("description")
allColumns = postgres.ColumnList{IDColumn, NameColumn, AddressColumn, DescriptionColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{NameColumn, AddressColumn, DescriptionColumn} allColumns = postgres.ColumnList{IDColumn, NameColumn, AddressColumn, DescriptionColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{NameColumn, AddressColumn, DescriptionColumn, CreatedAtColumn}
) )
return locationsTable{ return locationsTable{
@ -77,6 +79,7 @@ func newLocationsTableImpl(schemaName, tableName, alias string) locationsTable {
Name: NameColumn, Name: NameColumn,
Address: AddressColumn, Address: AddressColumn,
Description: DescriptionColumn, Description: DescriptionColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -17,8 +17,9 @@ type logsTable struct {
postgres.Table postgres.Table
// Columns // Columns
Log postgres.ColumnString Log postgres.ColumnString
ImageID postgres.ColumnString ImageID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -59,18 +60,20 @@ func newLogsTable(schemaName, tableName, alias string) *LogsTable {
func newLogsTableImpl(schemaName, tableName, alias string) logsTable { func newLogsTableImpl(schemaName, tableName, alias string) logsTable {
var ( var (
LogColumn = postgres.StringColumn("log") LogColumn = postgres.StringColumn("log")
ImageIDColumn = postgres.StringColumn("image_id") ImageIDColumn = postgres.StringColumn("image_id")
allColumns = postgres.ColumnList{LogColumn, ImageIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{LogColumn, ImageIDColumn} allColumns = postgres.ColumnList{LogColumn, ImageIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{LogColumn, ImageIDColumn, CreatedAtColumn}
) )
return logsTable{ return logsTable{
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...), Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
//Columns //Columns
Log: LogColumn, Log: LogColumn,
ImageID: ImageIDColumn, ImageID: ImageIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -21,6 +21,7 @@ type notesTable struct {
Name postgres.ColumnString Name postgres.ColumnString
Description postgres.ColumnString Description postgres.ColumnString
Content postgres.ColumnString Content postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -65,8 +66,9 @@ func newNotesTableImpl(schemaName, tableName, alias string) notesTable {
NameColumn = postgres.StringColumn("name") NameColumn = postgres.StringColumn("name")
DescriptionColumn = postgres.StringColumn("description") DescriptionColumn = postgres.StringColumn("description")
ContentColumn = postgres.StringColumn("content") ContentColumn = postgres.StringColumn("content")
allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, ContentColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, ContentColumn} allColumns = postgres.ColumnList{IDColumn, NameColumn, DescriptionColumn, ContentColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{NameColumn, DescriptionColumn, ContentColumn, CreatedAtColumn}
) )
return notesTable{ return notesTable{
@ -77,6 +79,7 @@ func newNotesTableImpl(schemaName, tableName, alias string) notesTable {
Name: NameColumn, Name: NameColumn,
Description: DescriptionColumn, Description: DescriptionColumn,
Content: ContentColumn, Content: ContentColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -20,6 +20,7 @@ type userContactsTable struct {
ID postgres.ColumnString ID postgres.ColumnString
UserID postgres.ColumnString UserID postgres.ColumnString
ContactID postgres.ColumnString ContactID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -63,8 +64,9 @@ func newUserContactsTableImpl(schemaName, tableName, alias string) userContactsT
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
UserIDColumn = postgres.StringColumn("user_id") UserIDColumn = postgres.StringColumn("user_id")
ContactIDColumn = postgres.StringColumn("contact_id") ContactIDColumn = postgres.StringColumn("contact_id")
allColumns = postgres.ColumnList{IDColumn, UserIDColumn, ContactIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{UserIDColumn, ContactIDColumn} allColumns = postgres.ColumnList{IDColumn, UserIDColumn, ContactIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{UserIDColumn, ContactIDColumn, CreatedAtColumn}
) )
return userContactsTable{ return userContactsTable{
@ -74,6 +76,7 @@ func newUserContactsTableImpl(schemaName, tableName, alias string) userContactsT
ID: IDColumn, ID: IDColumn,
UserID: UserIDColumn, UserID: UserIDColumn,
ContactID: ContactIDColumn, ContactID: ContactIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -17,9 +17,10 @@ type userEventsTable struct {
postgres.Table postgres.Table
// Columns // Columns
ID postgres.ColumnString ID postgres.ColumnString
EventID postgres.ColumnString EventID postgres.ColumnString
UserID postgres.ColumnString UserID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -60,20 +61,22 @@ func newUserEventsTable(schemaName, tableName, alias string) *UserEventsTable {
func newUserEventsTableImpl(schemaName, tableName, alias string) userEventsTable { func newUserEventsTableImpl(schemaName, tableName, alias string) userEventsTable {
var ( var (
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
EventIDColumn = postgres.StringColumn("event_id") EventIDColumn = postgres.StringColumn("event_id")
UserIDColumn = postgres.StringColumn("user_id") UserIDColumn = postgres.StringColumn("user_id")
allColumns = postgres.ColumnList{IDColumn, EventIDColumn, UserIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{EventIDColumn, UserIDColumn} allColumns = postgres.ColumnList{IDColumn, EventIDColumn, UserIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{EventIDColumn, UserIDColumn, CreatedAtColumn}
) )
return userEventsTable{ return userEventsTable{
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...), Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
//Columns //Columns
ID: IDColumn, ID: IDColumn,
EventID: EventIDColumn, EventID: EventIDColumn,
UserID: UserIDColumn, UserID: UserIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -17,9 +17,10 @@ type userImagesTable struct {
postgres.Table postgres.Table
// Columns // Columns
ID postgres.ColumnString ID postgres.ColumnString
ImageID postgres.ColumnString ImageID postgres.ColumnString
UserID postgres.ColumnString UserID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -60,20 +61,22 @@ func newUserImagesTable(schemaName, tableName, alias string) *UserImagesTable {
func newUserImagesTableImpl(schemaName, tableName, alias string) userImagesTable { func newUserImagesTableImpl(schemaName, tableName, alias string) userImagesTable {
var ( var (
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
ImageIDColumn = postgres.StringColumn("image_id") ImageIDColumn = postgres.StringColumn("image_id")
UserIDColumn = postgres.StringColumn("user_id") UserIDColumn = postgres.StringColumn("user_id")
allColumns = postgres.ColumnList{IDColumn, ImageIDColumn, UserIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{ImageIDColumn, UserIDColumn} allColumns = postgres.ColumnList{IDColumn, ImageIDColumn, UserIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{ImageIDColumn, UserIDColumn, CreatedAtColumn}
) )
return userImagesTable{ return userImagesTable{
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...), Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
//Columns //Columns
ID: IDColumn, ID: IDColumn,
ImageID: ImageIDColumn, ImageID: ImageIDColumn,
UserID: UserIDColumn, UserID: UserIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -20,6 +20,7 @@ type userLocationsTable struct {
ID postgres.ColumnString ID postgres.ColumnString
LocationID postgres.ColumnString LocationID postgres.ColumnString
UserID postgres.ColumnString UserID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -63,8 +64,9 @@ func newUserLocationsTableImpl(schemaName, tableName, alias string) userLocation
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
LocationIDColumn = postgres.StringColumn("location_id") LocationIDColumn = postgres.StringColumn("location_id")
UserIDColumn = postgres.StringColumn("user_id") UserIDColumn = postgres.StringColumn("user_id")
allColumns = postgres.ColumnList{IDColumn, LocationIDColumn, UserIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{LocationIDColumn, UserIDColumn} allColumns = postgres.ColumnList{IDColumn, LocationIDColumn, UserIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{LocationIDColumn, UserIDColumn, CreatedAtColumn}
) )
return userLocationsTable{ return userLocationsTable{
@ -74,6 +76,7 @@ func newUserLocationsTableImpl(schemaName, tableName, alias string) userLocation
ID: IDColumn, ID: IDColumn,
LocationID: LocationIDColumn, LocationID: LocationIDColumn,
UserID: UserIDColumn, UserID: UserIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -17,9 +17,10 @@ type userNotesTable struct {
postgres.Table postgres.Table
// Columns // Columns
ID postgres.ColumnString ID postgres.ColumnString
UserID postgres.ColumnString UserID postgres.ColumnString
NoteID postgres.ColumnString NoteID postgres.ColumnString
CreatedAt postgres.ColumnTimestampz
AllColumns postgres.ColumnList AllColumns postgres.ColumnList
MutableColumns postgres.ColumnList MutableColumns postgres.ColumnList
@ -60,20 +61,22 @@ func newUserNotesTable(schemaName, tableName, alias string) *UserNotesTable {
func newUserNotesTableImpl(schemaName, tableName, alias string) userNotesTable { func newUserNotesTableImpl(schemaName, tableName, alias string) userNotesTable {
var ( var (
IDColumn = postgres.StringColumn("id") IDColumn = postgres.StringColumn("id")
UserIDColumn = postgres.StringColumn("user_id") UserIDColumn = postgres.StringColumn("user_id")
NoteIDColumn = postgres.StringColumn("note_id") NoteIDColumn = postgres.StringColumn("note_id")
allColumns = postgres.ColumnList{IDColumn, UserIDColumn, NoteIDColumn} CreatedAtColumn = postgres.TimestampzColumn("created_at")
mutableColumns = postgres.ColumnList{UserIDColumn, NoteIDColumn} allColumns = postgres.ColumnList{IDColumn, UserIDColumn, NoteIDColumn, CreatedAtColumn}
mutableColumns = postgres.ColumnList{UserIDColumn, NoteIDColumn, CreatedAtColumn}
) )
return userNotesTable{ return userNotesTable{
Table: postgres.NewTable(schemaName, tableName, alias, allColumns...), Table: postgres.NewTable(schemaName, tableName, alias, allColumns...),
//Columns //Columns
ID: IDColumn, ID: IDColumn,
UserID: UserIDColumn, UserID: UserIDColumn,
NoteID: NoteIDColumn, NoteID: NoteIDColumn,
CreatedAt: CreatedAtColumn,
AllColumns: allColumns, AllColumns: allColumns,
MutableColumns: mutableColumns, MutableColumns: mutableColumns,

View File

@ -142,8 +142,12 @@ func (m TextMessageContent) IsImageMessage() bool {
} }
type ImageMessageContent struct { type ImageMessageContent struct {
ImageType string `json:"type"` ImageType string `json:"type"`
ImageUrl string `json:"image_url"` ImageUrl ImageMessageUrl `json:"image_url"`
}
type ImageMessageUrl struct {
Url string `json:"url"`
} }
func (m ImageMessageContent) IsImageMessage() bool { func (m ImageMessageContent) IsImageMessage() bool {
@ -161,6 +165,7 @@ type ImageContentUrl struct {
type ToolCall struct { type ToolCall struct {
Index int `json:"index"` Index int `json:"index"`
Id string `json:"id"` Id string `json:"id"`
Type string `json:"type,omitzero"`
Function FunctionCall `json:"function"` Function FunctionCall `json:"function"`
} }
@ -186,7 +191,10 @@ func (chat *Chat) AddImage(imageName string, image []byte, query *string) error
extension := filepath.Ext(imageName) extension := filepath.Ext(imageName)
if len(extension) == 0 { if len(extension) == 0 {
// TODO: could also validate for image types we support. // TODO: could also validate for image types we support.
return errors.New("Image does not have extension") // return errors.New("Image does not have extension")
// Hacky! It seems apple doesnt add extension.
// BIG TODO: take better metadata from the image.
extension = "png"
} }
extension = extension[1:] extension = extension[1:]
@ -213,7 +221,9 @@ func (chat *Chat) AddImage(imageName string, image []byte, query *string) error
messageContent.Content[index] = ImageMessageContent{ messageContent.Content[index] = ImageMessageContent{
ImageType: "image_url", ImageType: "image_url",
ImageUrl: fmt.Sprintf("data:image/%s;base64,%s", extension, encodedString), ImageUrl: ImageMessageUrl{
Url: fmt.Sprintf("data:image/%s;base64,%s", extension, encodedString),
},
} }
arrayMessage := ChatUserMessage{Role: User, MessageContent: messageContent} arrayMessage := ChatUserMessage{Role: User, MessageContent: messageContent}

View File

@ -14,7 +14,7 @@ import (
type ResponseFormat struct { type ResponseFormat struct {
Type string `json:"type"` Type string `json:"type"`
JsonSchema any `json:"json_schema"` JsonSchema any `json:"json_schema,omitzero"`
} }
type AgentRequestBody struct { type AgentRequestBody struct {
@ -25,6 +25,8 @@ type AgentRequestBody struct {
Tools *any `json:"tools,omitempty"` Tools *any `json:"tools,omitempty"`
ToolChoice *string `json:"tool_choice,omitempty"` ToolChoice *string `json:"tool_choice,omitempty"`
RandomSeed *int `json:"random_seed,omitempty"`
EndToolCall string `json:"-"` EndToolCall string `json:"-"`
Chat *Chat `json:"messages"` Chat *Chat `json:"messages"`
@ -80,7 +82,7 @@ type AgentClient struct {
Options CreateAgentClientOptions Options CreateAgentClientOptions
} }
const OPENAI_API_KEY = "OPENAI_API_KEY" const OPENAI_API_KEY = "REAL_OPEN_AI_KEY"
type CreateAgentClientOptions struct { type CreateAgentClientOptions struct {
Log *log.Logger Log *log.Logger
@ -99,7 +101,7 @@ func CreateAgentClient(options CreateAgentClientOptions) AgentClient {
return AgentClient{ return AgentClient{
apiKey: apiKey, apiKey: apiKey,
url: "https://api.mistral.ai/v1/chat/completions", url: "https://api.openai.com/v1/chat/completions",
Do: func(req *http.Request) (*http.Response, error) { Do: func(req *http.Request) (*http.Response, error) {
client := &http.Client{} client := &http.Client{}
return client.Do(req) return client.Do(req)
@ -237,12 +239,14 @@ func (client *AgentClient) RunAgent(userId uuid.UUID, imageId uuid.UUID, imageNa
panic(err) panic(err)
} }
toolChoice := "any" toolChoice := "auto"
seed := 42
request := AgentRequestBody{ request := AgentRequestBody{
Tools: &tools, Tools: &tools,
ToolChoice: &toolChoice, ToolChoice: &toolChoice,
Model: "pixtral-12b-2409", Model: "gpt-4.1-mini",
RandomSeed: &seed,
Temperature: 0.3, Temperature: 0.3,
EndToolCall: client.Options.EndToolCall, EndToolCall: client.Options.EndToolCall,
ResponseFormat: ResponseFormat{ ResponseFormat: ResponseFormat{

View File

@ -21,13 +21,14 @@ const contactPrompt = `
**Workflow:** **Workflow:**
1. **Scan Image:** Extract all contact details. If none, call stopAgent. 1. **Scan Image:** Extract all contact details. If none, call stopAgent.
2. **Think:** Using the think tool, you must layout your thoughts about the contacts on the image. If they are duplicates or not, and what your next action should be, 2. **Think:** Using the think tool, you must layout your thoughts about the contacts on the image. If they are duplicates or not, and what your next action should be,
3. **Check Duplicates:** If contacts found, *first* call listContacts. Compare extracted info to list. If all found contacts already exist, call stopAgent. 3. **Check Duplicates:** If contacts found, *first* call listContacts. Compare extracted info to list. If all found contacts already exist, use createExistingContact.
4. **Add New:** If you detect a new contact on the image, call createContact to create a new contact. 4. **Add New:** If you detect a new contact on the image, call createContact to create a new contact.
5. **Finish:** Call stopAgent once all new contacts are created OR if steps 1 or 2 determined no action/creation was needed. 5. **Finish:** Call stopAgent once all new contacts are created OR if steps 1 or 2 determined no action/creation was needed.
**Tools:** **Tools:**
* listContacts: Check existing contacts (Use first if contacts found). * listContacts: Check existing contacts (Use first if contacts found).
* createContact: Add a NEW contact (Name required). * createContact: Add a NEW contact (Name required).
* createExistingContact: Adds this image to an existing contact, if one is found in listContacts.
* stopAgent: Signal task completion. * stopAgent: Signal task completion.
` `
@ -80,21 +81,38 @@ const contactTools = `
}, },
"phoneNumber": { "phoneNumber": {
"type": "string", "type": "string",
"description": "The contact's primary phone number, including area or country code if available. Provide this if extracted from the image." "description": "The contact's primary phone number, including area or country code if available. Provide this if extracted from the image. Only include this if you see a phone number, do not make it up."
}, },
"address": { "address": {
"type": "string", "type": "string",
"description": "The complete physical mailing address of the contact (e.g., street number, street name, city, state/province, postal code, country). Provide this if extracted from the image." "description": "The complete physical mailing address of the contact (e.g., street number, street name, city, state/province, postal code, country). Provide this if extracted from the image. Only include this if you see an address. No not make it up."
}, },
"email": { "email": {
"type": "string", "type": "string",
"description": "The contact's primary email address. Provide this if extracted from the image." "description": "The contact's primary email address. Provide this if extracted from the image. Only include this if you see an email, do not make it up."
} }
}, },
"required": ["name"] "required": ["name"]
} }
} }
}, },
{
"type": "function",
"function": {
"name": "createExistingContact",
"description": "Called when a contact already exists in the users list, from listContas. Only call this to indicate this image contains a duplicate.",
"parameters": {
"type": "object",
"properties": {
"contactId": {
"type": "string",
"description": "The UUID of the contact"
}
},
"required": ["contactId"]
}
}
},
{ {
"type": "function", "type": "function",
"function": { "function": {
@ -118,6 +136,9 @@ type createContactsArguments struct {
Address *string `json:"address"` Address *string `json:"address"`
Email *string `json:"email"` Email *string `json:"email"`
} }
type createExistingContactArguments struct {
ContactID string `json:"contactId"`
}
func NewContactAgent(log *log.Logger, contactModel models.ContactModel) client.AgentClient { func NewContactAgent(log *log.Logger, contactModel models.ContactModel) client.AgentClient {
agentClient := client.CreateAgentClient(client.CreateAgentClientOptions{ agentClient := client.CreateAgentClient(client.CreateAgentClientOptions{
@ -173,5 +194,27 @@ func NewContactAgent(log *log.Logger, contactModel models.ContactModel) client.A
return contact, nil return contact, nil
}) })
agentClient.ToolHandler.AddTool("createExistingContact", func(info client.ToolHandlerInfo, _args string, call client.ToolCall) (any, error) {
args := createExistingContactArguments{}
err := json.Unmarshal([]byte(_args), &args)
if err != nil {
return "", err
}
ctx := context.Background()
contactId, err := uuid.Parse(args.ContactID)
if err != nil {
return "", err
}
_, err = contactModel.SaveToImage(ctx, info.ImageId, contactId)
if err != nil {
return "", err
}
return "", nil
})
return agentClient return agentClient
} }

View File

@ -153,6 +153,43 @@ type updateEventArguments struct {
EventID string `json:"eventId"` EventID string `json:"eventId"`
} }
const layout = "2006-01-02T15:04:05Z"
func getArguments(args createEventArguments) (model.Events, error) {
event := model.Events{
Name: args.Name,
}
if args.StartDateTime != nil {
startTime, err := time.Parse(layout, *args.StartDateTime)
if err != nil {
return event, err
}
event.StartDateTime = &startTime
}
if args.EndDateTime != nil {
endTime, err := time.Parse(layout, *args.EndDateTime)
if err != nil {
return event, err
}
event.EndDateTime = &endTime
}
if args.LocationID != nil {
locationId, err := uuid.Parse(*args.LocationID)
if err != nil {
return model.Events{}, err
}
event.LocationID = &locationId
}
return event, nil
}
func NewEventAgent(log *log.Logger, eventsModel models.EventModel, locationModel models.LocationModel) client.AgentClient { func NewEventAgent(log *log.Logger, eventsModel models.EventModel, locationModel models.LocationModel) client.AgentClient {
agentClient := client.CreateAgentClient(client.CreateAgentClientOptions{ agentClient := client.CreateAgentClient(client.CreateAgentClientOptions{
SystemPrompt: eventPrompt, SystemPrompt: eventPrompt,
@ -181,32 +218,12 @@ func NewEventAgent(log *log.Logger, eventsModel models.EventModel, locationModel
} }
ctx := context.Background() ctx := context.Background()
event, err := getArguments(args)
layout := "2006-01-02T15:04:05Z"
// TODO: check for nil pointers.
startTime, err := time.Parse(layout, *args.StartDateTime)
if err != nil { if err != nil {
return model.Events{}, err return model.Events{}, err
} }
endTime, err := time.Parse(layout, *args.EndDateTime) events, err := eventsModel.Save(ctx, info.UserId, event)
if err != nil {
return model.Events{}, err
}
locationId, err := uuid.Parse(*args.LocationID)
if err != nil {
return model.Events{}, err
}
events, err := eventsModel.Save(ctx, info.UserId, model.Events{
Name: args.Name,
StartDateTime: &startTime,
EndDateTime: &endTime,
LocationID: &locationId,
})
if err != nil { if err != nil {
return model.Events{}, err return model.Events{}, err

View File

@ -57,7 +57,7 @@ const replyTool = `
"properties": { "properties": {
"locationId": { "locationId": {
"type": "string", "type": "string",
"description": "The unique identifier of the saved location that the user is asking about." "description": "The UUID of the saved location that the user is asking about."
} }
}, },
"required": ["locationId"] "required": ["locationId"]
@ -121,7 +121,7 @@ const locationTools = `
"type": "function", "type": "function",
"function": { "function": {
"name": "createExistingLocation", "name": "createExistingLocation",
"description": "Called when a location already exists in the users list, from listLocations. Only call this to indicate this image contains a duplicate. And only after using the doesLocationExist tol", "description": "Called when a location already exists in the users list, from listLocations. Only call this to indicate this image contains a duplicate.",
"parameters": { "parameters": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -30,7 +30,7 @@ type NoteAgent struct {
func (agent NoteAgent) GetNotes(userId uuid.UUID, imageId uuid.UUID, imageName string, imageData []byte) error { func (agent NoteAgent) GetNotes(userId uuid.UUID, imageId uuid.UUID, imageName string, imageData []byte) error {
request := client.AgentRequestBody{ request := client.AgentRequestBody{
Model: "pixtral-12b-2409", Model: "gpt-4.1-nano",
Temperature: 0.3, Temperature: 0.3,
ResponseFormat: client.ResponseFormat{ ResponseFormat: client.ResponseFormat{
Type: "text", Type: "text",

View File

@ -32,6 +32,7 @@ const orchestratorPrompt = `
* **noAgent**: Call this when you are done working on this image. * **noAgent**: Call this when you are done working on this image.
* Call all applicable specialized agents (noteAgent, contactAgent, locationAgent, eventAgent) simultaneously (in parallel). * Call all applicable specialized agents (noteAgent, contactAgent, locationAgent, eventAgent) simultaneously (in parallel).
* Do not call agents if you dont think they are relevant. It's better to be sound than complete.
` `
const orchestratorTools = ` const orchestratorTools = `
@ -139,25 +140,25 @@ func NewOrchestratorAgent(log *log.Logger, noteAgent NoteAgent, contactAgent cli
}) })
agent.ToolHandler.AddTool("noteAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) { agent.ToolHandler.AddTool("noteAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) {
go noteAgent.GetNotes(info.UserId, info.ImageId, imageName, imageData) noteAgent.GetNotes(info.UserId, info.ImageId, imageName, imageData)
return "noteAgent called successfully", nil return "noteAgent called successfully", nil
}) })
agent.ToolHandler.AddTool("contactAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) { agent.ToolHandler.AddTool("contactAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) {
go contactAgent.RunAgent(info.UserId, info.ImageId, imageName, imageData) contactAgent.RunAgent(info.UserId, info.ImageId, imageName, imageData)
return "contactAgent called successfully", nil return "contactAgent called successfully", nil
}) })
agent.ToolHandler.AddTool("locationAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) { agent.ToolHandler.AddTool("locationAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) {
go locationAgent.RunAgent(info.UserId, info.ImageId, imageName, imageData) locationAgent.RunAgent(info.UserId, info.ImageId, imageName, imageData)
return "locationAgent called successfully", nil return "locationAgent called successfully", nil
}) })
agent.ToolHandler.AddTool("eventAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) { agent.ToolHandler.AddTool("eventAgent", func(info client.ToolHandlerInfo, args string, call client.ToolCall) (any, error) {
go eventAgent.RunAgent(info.UserId, info.ImageId, imageName, imageData) eventAgent.RunAgent(info.UserId, info.ImageId, imageName, imageData)
return "eventAgent called successfully", nil return "eventAgent called successfully", nil
}) })

View File

@ -3,9 +3,13 @@ package main
import ( import (
"context" "context"
"database/sql" "database/sql"
"encoding/json"
"fmt"
"net/http"
"os" "os"
"screenmark/screenmark/agents" "screenmark/screenmark/agents"
"screenmark/screenmark/models" "screenmark/screenmark/models"
"strconv"
"time" "time"
"github.com/charmbracelet/log" "github.com/charmbracelet/log"
@ -13,7 +17,12 @@ import (
"github.com/lib/pq" "github.com/lib/pq"
) )
func ListenNewImageEvents(db *sql.DB, eventManager *EventManager) { type Notification struct {
ImageID uuid.UUID
Status string
}
func ListenNewImageEvents(db *sql.DB, notifier *Notifier[Notification]) {
listener := pq.NewListener(os.Getenv("DB_CONNECTION"), time.Second, time.Second, func(event pq.ListenerEventType, err error) { listener := pq.NewListener(os.Getenv("DB_CONNECTION"), time.Second, time.Second, func(event pq.ListenerEventType, err error) {
if err != nil { if err != nil {
panic(err) panic(err)
@ -39,7 +48,6 @@ func ListenNewImageEvents(db *sql.DB, eventManager *EventManager) {
select { select {
case parameters := <-listener.Notify: case parameters := <-listener.Notify:
imageId := uuid.MustParse(parameters.Extra) imageId := uuid.MustParse(parameters.Extra)
eventManager.listeners[parameters.Extra] = make(chan string)
databaseEventLog.Debug("Starting processing image", "ImageID", imageId) databaseEventLog.Debug("Starting processing image", "ImageID", imageId)
@ -68,28 +76,17 @@ func ListenNewImageEvents(db *sql.DB, eventManager *EventManager) {
orchestrator.RunAgent(image.UserID, image.ImageID, image.Image.ImageName, image.Image.Image) orchestrator.RunAgent(image.UserID, image.ImageID, image.Image.ImageName, image.Image.Image)
_, err = imageModel.FinishProcessing(ctx, image.ID) _, err = imageModel.FinishProcessing(ctx, image.ID)
if err != nil { if err != nil {
databaseEventLog.Error("Failed to finish processing", "ImageID", imageId) databaseEventLog.Error("Failed to finish processing", "ImageID", imageId, "error", err)
return return
} }
databaseEventLog.Debug("Starting processing image", "ImageID", imageId) databaseEventLog.Debug("Finished processing image", "ImageID", imageId)
}() }()
} }
} }
} }
type EventManager struct { func ListenProcessingImageStatus(db *sql.DB, images models.ImageModel, notifier *Notifier[Notification]) {
// Maps processing image UUID to a channel
listeners map[string]chan string
}
func NewEventManager() EventManager {
return EventManager{
listeners: make(map[string]chan string),
}
}
func ListenProcessingImageStatus(db *sql.DB, eventManager *EventManager) {
listener := pq.NewListener(os.Getenv("DB_CONNECTION"), time.Second, time.Second, func(event pq.ListenerEventType, err error) { listener := pq.NewListener(os.Getenv("DB_CONNECTION"), time.Second, time.Second, func(event pq.ListenerEventType, err error) {
if err != nil { if err != nil {
panic(err) panic(err)
@ -97,6 +94,8 @@ func ListenProcessingImageStatus(db *sql.DB, eventManager *EventManager) {
}) })
defer listener.Close() defer listener.Close()
logger := createLogger("Image Status 📊", os.Stdout)
if err := listener.Listen("new_processing_image_status"); err != nil { if err := listener.Listen("new_processing_image_status"); err != nil {
panic(err) panic(err)
} }
@ -104,18 +103,91 @@ func ListenProcessingImageStatus(db *sql.DB, eventManager *EventManager) {
for { for {
select { select {
case data := <-listener.Notify: case data := <-listener.Notify:
stringUuid := data.Extra[0:36] imageStringUuid := data.Extra[0:36]
status := data.Extra[36:] status := data.Extra[36:]
imageListener, exists := eventManager.listeners[stringUuid] imageUuid, err := uuid.Parse(imageStringUuid)
if !exists { if err != nil {
logger.Error(err)
continue continue
} }
imageListener <- status processingImage, err := images.GetToProcess(context.Background(), imageUuid)
if err != nil {
logger.Error("GetToProcess failed", "err", err)
continue
}
close(imageListener) logger.Info("Update", "id", imageStringUuid, "status", status)
delete(eventManager.listeners, stringUuid)
notification := Notification{
ImageID: processingImage.ImageID,
Status: status,
}
if err := notifier.SendAndCreate(processingImage.UserID.String(), notification); err != nil {
logger.Error(err)
}
}
}
}
func CreateEventsHandler(notifier *Notifier[Notification]) http.HandlerFunc {
counter := 0
userSplitters := make(map[string]*ChannelSplitter[Notification])
return func(w http.ResponseWriter, r *http.Request) {
userId := r.Context().Value(USER_ID).(uuid.UUID)
if userId == uuid.Nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
// w.(http.Flusher).Flush()
if _, exists := notifier.Listeners[userId.String()]; !exists {
notifier.Create(userId.String())
}
userNotifications := notifier.Listeners[userId.String()]
if _, exists := userSplitters[userId.String()]; !exists {
splitter := NewChannelSplitter(userNotifications)
userSplitters[userId.String()] = &splitter
splitter.Listen()
}
splitter := userSplitters[userId.String()]
id := strconv.Itoa(counter)
counter += 1
notifications := splitter.Add(id)
defer splitter.Remove(id)
for {
select {
case <-r.Context().Done():
fmt.Fprint(w, "event: close\ndata: Connection closed\n\n")
w.(http.Flusher).Flush()
return
case msg := <-notifications:
msgString, err := json.Marshal(msg)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
fmt.Printf("Sending msg %s\n", msg)
fmt.Fprintf(w, "event: data\ndata: %s\n\n", string(msgString))
w.(http.Flusher).Flush()
}
} }
} }
} }

View File

@ -82,7 +82,7 @@ func createLogHandler(logWriter *DatabaseWriter) func(r chi.Router) {
html := "" html := ""
imageTag := fmt.Sprintf(`<image src="http://localhost:3040/image/%s">`, stringImageId) imageTag := fmt.Sprintf(`<image src="https://haystack.johncosta.tech/image/%s">`, stringImageId)
for _, log := range logs { for _, log := range logs {
html += fmt.Sprintf("<div>%s</div>", string(ansihtml.ConvertToHTML([]byte(log)))+"\n") html += fmt.Sprintf("<div>%s</div>", string(ansihtml.ConvertToHTML([]byte(log)))+"\n")

View File

@ -2,7 +2,6 @@ package main
import ( import (
"bytes" "bytes"
"context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -13,7 +12,6 @@ import (
"screenmark/screenmark/.gen/haystack/haystack/model" "screenmark/screenmark/.gen/haystack/haystack/model"
"screenmark/screenmark/agents/client" "screenmark/screenmark/agents/client"
"screenmark/screenmark/models" "screenmark/screenmark/models"
"time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
@ -50,34 +48,78 @@ func main() {
auth := CreateAuth(mail) auth := CreateAuth(mail)
eventManager := NewEventManager() notifier := NewNotifier[Notification](10)
go ListenNewImageEvents(db, &eventManager) go ListenNewImageEvents(db, &notifier)
go ListenProcessingImageStatus(db, &eventManager) go ListenProcessingImageStatus(db, imageModel, &notifier)
r := chi.NewRouter() r := chi.NewRouter()
r.Use(middleware.Logger) r.Use(middleware.Logger)
r.Use(CorsMiddleware) r.Use(CorsMiddleware)
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
})
r.Options("/*", func(w http.ResponseWriter, r *http.Request) { r.Options("/*", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
}) })
// Temporarily not in protect route because we aren't using cookies.
// Therefore they don't get automatically attached to the request.
// So <img src=""> cannot send the tokensend the token
r.Get("/image/{id}", func(w http.ResponseWriter, r *http.Request) {
stringImageId := r.PathValue("id")
// userId := r.Context().Value(USER_ID).(uuid.UUID)
imageId, err := uuid.Parse(stringImageId)
if err != nil {
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "You cannot read this")
return
}
// if authorized := imageModel.IsUserAuthorized(r.Context(), imageId, userId); !authorized {
// w.WriteHeader(http.StatusForbidden)
// fmt.Fprintf(w, "You cannot read this")
// return
// }
image, err := imageModel.Get(r.Context(), imageId)
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Could not get image")
return
}
// TODO: this could be part of the db table
extension := filepath.Ext(image.ImageName)
if len(extension) == 0 {
// Same hack
extension = "png"
}
extension = extension[1:]
w.Header().Add("Content-Type", "image/"+extension)
w.Write(image.Image)
})
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {
r.Use(ProtectedRoute) r.Use(ProtectedRoute)
r.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
})
r.Get("/image", func(w http.ResponseWriter, r *http.Request) { r.Get("/image", func(w http.ResponseWriter, r *http.Request) {
userId := r.Context().Value(USER_ID).(uuid.UUID) userId := r.Context().Value(USER_ID).(uuid.UUID)
if err != nil {
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "You cannot read this")
return
}
images, err := userModel.ListWithProperties(r.Context(), userId) imageProperties, err := userModel.ListWithProperties(r.Context(), userId)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
@ -85,67 +127,25 @@ func main() {
return return
} }
type DataType struct { images, err := userModel.GetUserImages(r.Context(), userId)
Type string `json:"type"` if err != nil {
Data any `json:"data"` log.Println(err)
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Something went wrong")
return
} }
dataTypes := make([]DataType, 0) type ImagesReturn struct {
UserImages []models.UserImageWithImage
// lord ImageProperties []models.TypedProperties
// forgive me
idMap := make(map[uuid.UUID]bool)
for _, image := range images {
for _, location := range image.Locations {
_, exists := idMap[location.ID]
if exists {
continue
}
dataTypes = append(dataTypes, DataType{
Type: "location",
Data: location,
})
idMap[location.ID] = true
}
for _, event := range image.Events {
_, exists := idMap[event.ID]
if exists {
continue
}
dataTypes = append(dataTypes, DataType{
Type: "event",
Data: event,
})
idMap[event.ID] = true
}
for _, note := range image.Notes {
dataTypes = append(dataTypes, DataType{
Type: "note",
Data: note,
})
idMap[note.ID] = true
}
for _, contact := range image.Contacts {
_, exists := idMap[contact.ID]
if exists {
continue
}
dataTypes = append(dataTypes, DataType{
Type: "contact",
Data: contact,
})
idMap[contact.ID] = true
}
} }
jsonImages, err := json.Marshal(dataTypes) imagesReturn := ImagesReturn{
UserImages: images,
ImageProperties: models.GetTypedImageProperties(imageProperties),
}
jsonImages, err := json.Marshal(imagesReturn)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -156,9 +156,9 @@ func main() {
w.Write(jsonImages) w.Write(jsonImages)
}) })
r.Get("/image/{id}", func(w http.ResponseWriter, r *http.Request) { r.Get("/image-properties/{id}", func(w http.ResponseWriter, r *http.Request) {
stringImageId := r.PathValue("id")
userId := r.Context().Value(USER_ID).(uuid.UUID) userId := r.Context().Value(USER_ID).(uuid.UUID)
stringImageId := r.PathValue("id")
imageId, err := uuid.Parse(stringImageId) imageId, err := uuid.Parse(stringImageId)
if err != nil { if err != nil {
@ -167,27 +167,23 @@ func main() {
return return
} }
if authorized := imageModel.IsUserAuthorized(r.Context(), imageId, userId); !authorized { image, err := userModel.ListImageWithProperties(r.Context(), userId, imageId)
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "You cannot read this")
return
}
// TODO: really need authorization here!
image, err := imageModel.Get(r.Context(), imageId)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Could not get image") fmt.Fprintf(w, "Something went wrong")
return return
} }
// TODO: this could be part of the db table jsonImages, err := json.Marshal(models.GetTypedImageProperties([]models.ImageWithProperties{image})[0])
extension := filepath.Ext(image.Image.ImageName) if err != nil {
extension = extension[1:] log.Println(err)
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Could not create JSON response for this image")
return
}
w.Header().Add("Content-Type", "image/"+extension) w.Write(jsonImages)
w.Write(image.Image.Image)
}) })
r.Post("/image/{name}", func(w http.ResponseWriter, r *http.Request) { r.Post("/image/{name}", func(w http.ResponseWriter, r *http.Request) {
@ -202,6 +198,8 @@ func main() {
contentType := r.Header.Get("Content-Type") contentType := r.Header.Get("Content-Type")
fmt.Printf("Content-Type: %s\n", contentType)
// TODO: length checks on body // TODO: length checks on body
// TODO: extract this shit out // TODO: extract this shit out
image := make([]byte, 0) image := make([]byte, 0)
@ -221,7 +219,7 @@ func main() {
fmt.Println(decodedIamge) fmt.Println(decodedIamge)
image = buf.Bytes() image = buf.Bytes()
} else if contentType == "application/oclet-stream" { } else if contentType == "application/oclet-stream" || contentType == "image/png" {
bodyData, err := io.ReadAll(r.Body) bodyData, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
@ -275,39 +273,10 @@ func main() {
}) })
r.Get("/image-events/{id}", func(w http.ResponseWriter, r *http.Request) { r.Route("/notifications", func(r chi.Router) {
// TODO: authentication :) r.Use(GetUserIdFromUrl)
id := r.PathValue("id") r.Get("/", CreateEventsHandler(&notifier))
imageNotifier, exists := eventManager.listeners[id]
if !exists {
fmt.Println("Not found!")
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
w.(http.Flusher).Flush()
ctx, cancel := context.WithCancel(r.Context())
for {
select {
case <-ctx.Done():
fmt.Fprint(w, "event: close\ndata: Connection closed\n\n")
w.(http.Flusher).Flush()
cancel()
return
case data := <-imageNotifier:
fmt.Printf("Status received: %s\n", data)
fmt.Fprintf(w, "data: %s-%s\n", data, time.Now().String())
w.(http.Flusher).Flush()
cancel()
}
}
}) })
r.Post("/login", func(w http.ResponseWriter, r *http.Request) { r.Post("/login", func(w http.ResponseWriter, r *http.Request) {
@ -331,17 +300,17 @@ func main() {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
}) })
type CodeReturn struct {
Access string `json:"access"`
Refresh string `json:"refresh"`
}
r.Post("/code", func(w http.ResponseWriter, r *http.Request) { r.Post("/code", func(w http.ResponseWriter, r *http.Request) {
type CodeBody struct { type CodeBody struct {
Email string `json:"email"` Email string `json:"email"`
Code string `json:"code"` Code string `json:"code"`
} }
type CodeReturn struct {
Access string `json:"access"`
Refresh string `json:"refresh"`
}
codeBody := CodeBody{} codeBody := CodeBody{}
if err := json.NewDecoder(r.Body).Decode(&codeBody); err != nil { if err := json.NewDecoder(r.Body).Decode(&codeBody); err != nil {
log.Println(err) log.Println(err)
@ -379,6 +348,41 @@ func main() {
Refresh: refresh, Refresh: refresh,
} }
fmt.Println(codeReturn)
json, err := json.Marshal(codeReturn)
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Something went wrong.")
return
}
w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
fmt.Fprint(w, string(json))
})
r.Get("/demo-login", func(w http.ResponseWriter, r *http.Request) {
uuid, err := userModel.GetUserIdFromEmail(r.Context(), "demo@email.com")
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "Something went wrong.")
return
}
refresh := CreateRefreshToken(uuid)
access := CreateAccessToken(uuid)
codeReturn := CodeReturn{
Access: access,
Refresh: refresh,
}
fmt.Println(codeReturn)
json, err := json.Marshal(codeReturn) json, err := json.Marshal(codeReturn)
if err != nil { if err != nil {
log.Println(err) log.Println(err)

View File

@ -37,3 +37,25 @@ func ProtectedRoute(next http.Handler) http.Handler {
next.ServeHTTP(w, newR) next.ServeHTTP(w, newR)
}) })
} }
func GetUserIdFromUrl(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.URL.Query().Get("token")
if len(token) == 0 {
w.WriteHeader(http.StatusUnauthorized)
return
}
userId, err := GetUserIdFromAccess(token)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
return
}
contextWithUserId := context.WithValue(r.Context(), USER_ID, userId)
newR := r.WithContext(contextWithUserId)
next.ServeHTTP(w, newR)
})
}

View File

@ -117,15 +117,35 @@ func (m ImageModel) FinishProcessing(ctx context.Context, imageId uuid.UUID) (mo
return model.UserImages{}, err return model.UserImages{}, err
} }
removeProcessingStmt := UserImagesToProcess. // Hacky. Update the status before removing so we can get our regular triggers
DELETE(). // to work.
updateStatusStmt := UserImagesToProcess.
UPDATE(UserImagesToProcess.Status).
SET(model.Progress_Complete).
WHERE(UserImagesToProcess.ID.EQ(UUID(imageToProcess.ID))) WHERE(UserImagesToProcess.ID.EQ(UUID(imageToProcess.ID)))
_, err = removeProcessingStmt.ExecContext(ctx, tx) _, err = updateStatusStmt.ExecContext(ctx, tx)
if err != nil { if err != nil {
return model.UserImages{}, err return model.UserImages{}, err
} }
// TODO:
// We cannot delete the image to process because our events rely on it.
// This indicates our DB structure with the two tables might need some adjusting.
// Or re-doing all together perhaps.
// (switching to a one table (user_images) could work)
// But for now, we can just not delete the images to process and set them to complete
// removeProcessingStmt := UserImagesToProcess.
// DELETE().
// WHERE(UserImagesToProcess.ID.EQ(UUID(imageToProcess.ID)))
//
// _, err = removeProcessingStmt.ExecContext(ctx, tx)
// if err != nil {
// return model.UserImages{}, err
// }
err = tx.Commit() err = tx.Commit()
return userImage, err return userImage, err
} }
@ -141,21 +161,14 @@ func (m ImageModel) StartProcessing(ctx context.Context, processingImageId uuid.
return err return err
} }
func (m ImageModel) Get(ctx context.Context, imageId uuid.UUID) (ImageData, error) { func (m ImageModel) Get(ctx context.Context, imageId uuid.UUID) (model.Image, error) {
getImageStmt := SELECT(UserImages.AllColumns, Image.AllColumns). getImageStmt := Image.SELECT(Image.AllColumns).
FROM( WHERE(Image.ID.EQ(UUID(imageId)))
UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID)),
).
WHERE(UserImages.ID.EQ(UUID(imageId)))
images := []ImageData{} image := model.Image{}
err := getImageStmt.QueryContext(ctx, m.dbPool, &images) err := getImageStmt.QueryContext(ctx, m.dbPool, &image)
if len(images) != 1 { return image, err
return ImageData{}, errors.New(fmt.Sprintf("Expected 1, got %d\n", len(images)))
}
return images[0], err
} }
func (m ImageModel) IsUserAuthorized(ctx context.Context, imageId uuid.UUID, userId uuid.UUID) bool { func (m ImageModel) IsUserAuthorized(ctx context.Context, imageId uuid.UUID, userId uuid.UUID) bool {

View File

@ -22,19 +22,180 @@ type ImageWithProperties struct {
Image model.Image Image model.Image
Tags []struct {
model.ImageTags
Tag model.UserTags
}
Links []model.ImageLinks
Text []model.ImageText
Locations []model.Locations Locations []model.Locations
Events []model.Events Events []model.Events
Notes []model.Notes Notes []model.Notes
Contacts []model.Contacts Contacts []model.Contacts
} }
type PropertiesWithImage struct {
Locations []struct {
model.Locations
Images uuid.UUIDs
}
Contacts []struct {
model.Contacts
Images uuid.UUIDs
}
Events []struct {
model.Events
Images uuid.UUIDs
}
Notes []struct {
model.Notes
Images uuid.UUIDs
}
}
func transpose(imageProperties []ImageWithProperties) PropertiesWithImage {
// EntityID -> []ImageIDs
dependencies := make(map[uuid.UUID]uuid.UUIDs)
addDependency := func(entityId uuid.UUID, imageId uuid.UUID) {
deps, exists := dependencies[entityId]
if !exists {
dep := uuid.UUIDs{imageId}
dependencies[entityId] = dep
return
}
dependencies[entityId] = append(deps, imageId)
}
contactMap := make(map[uuid.UUID]model.Contacts)
locationMap := make(map[uuid.UUID]model.Locations)
noteMap := make(map[uuid.UUID]model.Notes)
eventMap := make(map[uuid.UUID]model.Events)
for _, image := range imageProperties {
for _, contact := range image.Contacts {
contactMap[contact.ID] = contact
addDependency(contact.ID, image.Image.ID)
}
for _, location := range image.Locations {
locationMap[location.ID] = location
addDependency(location.ID, image.Image.ID)
}
for _, note := range image.Notes {
noteMap[note.ID] = note
addDependency(note.ID, image.Image.ID)
}
for _, event := range image.Events {
eventMap[event.ID] = event
addDependency(event.ID, image.Image.ID)
}
}
properties := PropertiesWithImage{
Contacts: make([]struct {
model.Contacts
Images uuid.UUIDs
}, 0),
Locations: make([]struct {
model.Locations
Images uuid.UUIDs
}, 0),
Notes: make([]struct {
model.Notes
Images uuid.UUIDs
}, 0),
Events: make([]struct {
model.Events
Images uuid.UUIDs
}, 0),
}
for contactId, contact := range contactMap {
properties.Contacts = append(properties.Contacts, struct {
model.Contacts
Images uuid.UUIDs
}{
Contacts: contact,
Images: dependencies[contactId],
})
}
for locationId, location := range locationMap {
properties.Locations = append(properties.Locations, struct {
model.Locations
Images uuid.UUIDs
}{
Locations: location,
Images: dependencies[locationId],
})
}
for noteId, note := range noteMap {
properties.Notes = append(properties.Notes, struct {
model.Notes
Images uuid.UUIDs
}{
Notes: note,
Images: dependencies[noteId],
})
}
for eventId, event := range eventMap {
properties.Events = append(properties.Events, struct {
model.Events
Images uuid.UUIDs
}{
Events: event,
Images: dependencies[eventId],
})
}
return properties
}
type TypedProperties struct {
Type string `json:"type"`
Data any `json:"data"`
}
func propertiesToTypeArray(properties PropertiesWithImage) []TypedProperties {
typedProperties := make([]TypedProperties, 0)
for _, location := range properties.Locations {
typedProperties = append(typedProperties, TypedProperties{
Type: "location",
Data: location,
})
}
for _, contact := range properties.Contacts {
typedProperties = append(typedProperties, TypedProperties{
Type: "contact",
Data: contact,
})
}
for _, note := range properties.Notes {
typedProperties = append(typedProperties, TypedProperties{
Type: "note",
Data: note,
})
}
for _, event := range properties.Events {
typedProperties = append(typedProperties, TypedProperties{
Type: "event",
Data: event,
})
}
return typedProperties
}
func GetTypedImageProperties(imageProperties []ImageWithProperties) []TypedProperties {
return propertiesToTypeArray(transpose(imageProperties))
}
func getUserIdFromImage(ctx context.Context, dbPool *sql.DB, imageId uuid.UUID) (uuid.UUID, error) { func getUserIdFromImage(ctx context.Context, dbPool *sql.DB, imageId uuid.UUID) (uuid.UUID, error) {
getUserIdStmt := UserImages.SELECT(UserImages.UserID).WHERE(UserImages.ImageID.EQ(UUID(imageId))) getUserIdStmt := UserImages.SELECT(UserImages.UserID).WHERE(UserImages.ImageID.EQ(UUID(imageId)))
@ -53,8 +214,8 @@ func getUserIdFromImage(ctx context.Context, dbPool *sql.DB, imageId uuid.UUID)
return userImages[0].UserID, nil return userImages[0].UserID, nil
} }
func (m UserModel) ListWithProperties(ctx context.Context, userId uuid.UUID) ([]ImageWithProperties, error) { func getListImagesStmt() SelectStatement {
listWithPropertiesStmt := SELECT( return SELECT(
UserImages.ID.AS("ImageWithProperties.ID"), UserImages.ID.AS("ImageWithProperties.ID"),
Image.ID, Image.ID,
Image.ImageName, Image.ImageName,
@ -84,15 +245,26 @@ func (m UserModel) ListWithProperties(ctx context.Context, userId uuid.UUID) ([]
LEFT_JOIN(ImageContacts, ImageContacts.ImageID.EQ(UserImages.ImageID)). LEFT_JOIN(ImageContacts, ImageContacts.ImageID.EQ(UserImages.ImageID)).
LEFT_JOIN(Contacts, Contacts.ID.EQ(ImageContacts.ContactID)). LEFT_JOIN(Contacts, Contacts.ID.EQ(ImageContacts.ContactID)).
LEFT_JOIN(ImageNotes, ImageNotes.ImageID.EQ(UserImages.ImageID)). LEFT_JOIN(ImageNotes, ImageNotes.ImageID.EQ(UserImages.ImageID)).
LEFT_JOIN(Notes, Notes.ID.EQ(ImageNotes.NoteID))). LEFT_JOIN(Notes, Notes.ID.EQ(ImageNotes.NoteID)))
}
func (m UserModel) ListImageWithProperties(ctx context.Context, userId uuid.UUID, imageId uuid.UUID) (ImageWithProperties, error) {
listImagePropertiesStmt := getListImagesStmt().
WHERE(UserImages.ImageID.EQ(UUID(imageId)))
image := ImageWithProperties{}
err := listImagePropertiesStmt.QueryContext(ctx, m.dbPool, &image)
return image, err
}
func (m UserModel) ListWithProperties(ctx context.Context, userId uuid.UUID) ([]ImageWithProperties, error) {
listWithPropertiesStmt := getListImagesStmt().
WHERE(UserImages.UserID.EQ(UUID(userId))) WHERE(UserImages.UserID.EQ(UUID(userId)))
images := []ImageWithProperties{} images := []ImageWithProperties{}
err := listWithPropertiesStmt.QueryContext(ctx, m.dbPool, &images) err := listWithPropertiesStmt.QueryContext(ctx, m.dbPool, &images)
if err != nil {
return images, err
}
return images, err return images, err
} }
@ -123,6 +295,27 @@ func (m UserModel) Save(ctx context.Context, user model.Users) (model.Users, err
return insertedUser, err return insertedUser, err
} }
type UserImageWithImage struct {
model.UserImages
Image model.Image
}
func (m UserModel) GetUserImages(ctx context.Context, userId uuid.UUID) ([]UserImageWithImage, error) {
getUserImagesStmt := SELECT(
UserImages.AllColumns,
Image.ID,
Image.ImageName,
).
FROM(UserImages.INNER_JOIN(Image, Image.ID.EQ(UserImages.ImageID))).
WHERE(UserImages.UserID.EQ(UUID(userId)))
userImages := []UserImageWithImage{}
err := getUserImagesStmt.QueryContext(ctx, m.dbPool, &userImages)
return userImages, err
}
func NewUserModel(db *sql.DB) UserModel { func NewUserModel(db *sql.DB) UserModel {
return UserModel{dbPool: db} return UserModel{dbPool: db}
} }

97
backend/notifications.go Normal file
View File

@ -0,0 +1,97 @@
package main
import (
"errors"
)
type Notifier[TNotification any] struct {
bufferSize int
Listeners map[string]chan TNotification
}
func (n *Notifier[TNotification]) Create(id string) error {
if _, exists := n.Listeners[id]; exists {
return errors.New("This listener already exists")
}
n.Listeners[id] = make(chan TNotification, n.bufferSize)
return nil
}
var ChannelFullErr = errors.New("Channel is full")
// Ensures the listener exists before sending
func (n *Notifier[TNotification]) SendAndCreate(id string, notification TNotification) error {
if _, exists := n.Listeners[id]; !exists {
if err := n.Create(id); err != nil {
return err
}
}
ch := n.Listeners[id]
select {
case ch <- notification:
return nil
default:
return ChannelFullErr
}
}
func (n *Notifier[TNotification]) Delete(id string) error {
if _, exists := n.Listeners[id]; !exists {
return errors.New("This listener does not exists")
}
delete(n.Listeners, id)
return nil
}
func NewNotifier[TNotification any](bufferSize int) Notifier[TNotification] {
return Notifier[TNotification]{
bufferSize: bufferSize,
Listeners: make(map[string]chan TNotification),
}
}
// ----------------------------------
type ChannelSplitter[TNotification any] struct {
ch chan TNotification
Listeners map[string]chan TNotification
}
func (s *ChannelSplitter[TNotification]) Listen() {
go func() {
for {
select {
case msg := <-s.ch:
for _, v := range s.Listeners {
v <- msg
}
}
}
}()
}
func (s *ChannelSplitter[TNotification]) Add(id string) chan TNotification {
ch := make(chan TNotification)
s.Listeners[id] = ch
return ch
}
func (s *ChannelSplitter[TNotification]) Remove(id string) {
delete(s.Listeners, id)
}
func NewChannelSplitter[TNotification any](ch chan TNotification) ChannelSplitter[TNotification] {
return ChannelSplitter[TNotification]{
ch: ch,
Listeners: make(map[string]chan TNotification),
}
}

View File

@ -0,0 +1,48 @@
package main
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSendingNotifications(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
notifier := NewNotifier[string](3)
err := notifier.SendAndCreate("1", "a")
require.NoError(err)
err = notifier.SendAndCreate("1", "b")
require.NoError(err)
err = notifier.SendAndCreate("1", "c")
require.NoError(err)
ch := notifier.Listeners["1"]
a := <-ch
b := <-ch
c := <-ch
assert.Equal(a, "a")
assert.Equal(b, "b")
assert.Equal(c, "c")
}
func TestFullBuffer(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
notifier := NewNotifier[string](1)
err := notifier.SendAndCreate("1", "a")
require.NoError(err)
err = notifier.SendAndCreate("1", "b")
assert.Error(err)
}

View File

@ -4,7 +4,7 @@ CREATE SCHEMA haystack;
/* -----| Enums |----- */ /* -----| Enums |----- */
CREATE TYPE haystack.progress AS ENUM('not-started','in-progress'); CREATE TYPE haystack.progress AS ENUM('not-started','in-progress', 'complete');
/* -----| Schema tables |----- */ /* -----| Schema tables |----- */
@ -29,9 +29,13 @@ CREATE TABLE haystack.user_images_to_process (
CREATE TABLE haystack.user_images ( CREATE TABLE haystack.user_images (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
image_id uuid NOT NULL UNIQUE REFERENCES haystack.image (id), image_id uuid NOT NULL UNIQUE REFERENCES haystack.image (id),
user_id uuid NOT NULL REFERENCES haystack.users (id) user_id uuid NOT NULL REFERENCES haystack.users (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
/* ===== DEPRECATED ===== */
CREATE TABLE haystack.user_tags ( CREATE TABLE haystack.user_tags (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
tag VARCHAR(32) UNIQUE NOT NULL, tag VARCHAR(32) UNIQUE NOT NULL,
@ -56,23 +60,31 @@ CREATE TABLE haystack.image_links (
image_id UUID NOT NULL REFERENCES haystack.image (id) image_id UUID NOT NULL REFERENCES haystack.image (id)
); );
/* ===== END DEPRECATED ===== */
CREATE TABLE haystack.locations ( CREATE TABLE haystack.locations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL, name TEXT NOT NULL,
address TEXT, address TEXT,
description TEXT description TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.image_locations ( CREATE TABLE haystack.image_locations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
location_id UUID NOT NULL REFERENCES haystack.locations (id), location_id UUID NOT NULL REFERENCES haystack.locations (id),
image_id UUID NOT NULL REFERENCES haystack.image (id) image_id UUID NOT NULL REFERENCES haystack.image (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.user_locations ( CREATE TABLE haystack.user_locations (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
location_id UUID NOT NULL REFERENCES haystack.locations (id), location_id UUID NOT NULL REFERENCES haystack.locations (id),
user_id UUID NOT NULL REFERENCES haystack.users (id) user_id UUID NOT NULL REFERENCES haystack.users (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.contacts ( CREATE TABLE haystack.contacts (
@ -83,19 +95,25 @@ CREATE TABLE haystack.contacts (
description TEXT, description TEXT,
phone_number TEXT, phone_number TEXT,
email TEXT email TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.user_contacts ( CREATE TABLE haystack.user_contacts (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES haystack.users (id), user_id UUID NOT NULL REFERENCES haystack.users (id),
contact_id UUID NOT NULL REFERENCES haystack.contacts (id) contact_id UUID NOT NULL REFERENCES haystack.contacts (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.image_contacts ( CREATE TABLE haystack.image_contacts (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
image_id UUID NOT NULL REFERENCES haystack.image (id), image_id UUID NOT NULL REFERENCES haystack.image (id),
contact_id UUID NOT NULL REFERENCES haystack.contacts (id) contact_id UUID NOT NULL REFERENCES haystack.contacts (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.events ( CREATE TABLE haystack.events (
@ -109,19 +127,25 @@ CREATE TABLE haystack.events (
end_date_time TIMESTAMP, end_date_time TIMESTAMP,
location_id UUID REFERENCES haystack.locations (id), location_id UUID REFERENCES haystack.locations (id),
organizer_id UUID REFERENCES haystack.contacts (id) organizer_id UUID REFERENCES haystack.contacts (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.image_events ( CREATE TABLE haystack.image_events (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
event_id UUID NOT NULL REFERENCES haystack.events (id), event_id UUID NOT NULL REFERENCES haystack.events (id),
image_id UUID NOT NULL REFERENCES haystack.image (id) image_id UUID NOT NULL REFERENCES haystack.image (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.user_events ( CREATE TABLE haystack.user_events (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
event_id UUID NOT NULL REFERENCES haystack.events (id), event_id UUID NOT NULL REFERENCES haystack.events (id),
user_id UUID NOT NULL REFERENCES haystack.users (id) user_id UUID NOT NULL REFERENCES haystack.users (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.notes ( CREATE TABLE haystack.notes (
@ -131,24 +155,32 @@ CREATE TABLE haystack.notes (
name TEXT NOT NULL, name TEXT NOT NULL,
description TEXT, description TEXT,
content TEXT NOT NULL content TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.image_notes ( CREATE TABLE haystack.image_notes (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
image_id UUID NOT NULL REFERENCES haystack.image (id), image_id UUID NOT NULL REFERENCES haystack.image (id),
note_id UUID NOT NULL REFERENCES haystack.notes (id) note_id UUID NOT NULL REFERENCES haystack.notes (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.user_notes ( CREATE TABLE haystack.user_notes (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(), id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES haystack.users (id), user_id UUID NOT NULL REFERENCES haystack.users (id),
note_id UUID NOT NULL REFERENCES haystack.notes (id) note_id UUID NOT NULL REFERENCES haystack.notes (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
CREATE TABLE haystack.logs ( CREATE TABLE haystack.logs (
log TEXT NOT NULL, log TEXT NOT NULL,
image_id UUID NOT NULL REFERENCES haystack.image (id) image_id UUID NOT NULL REFERENCES haystack.image (id),
created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
); );
/* -----| Indexes |----- */ /* -----| Indexes |----- */

4
backup.bash Normal file
View File

@ -0,0 +1,4 @@
name=haystack-db-dump-$(date "+%Y-%m-%d").sql
pg_dump haystack > $name
rsync -avH $name zh3586@zh3586.rsync.net:Backups/Haystack/
rm $name

BIN
frontend/.DS_Store vendored Normal file

Binary file not shown.

53
frontend/.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="NONE" />
</component>
<component name="ChangeListManager">
<list default="true" id="4ea94c05-c21c-40f9-ad16-43233a3011ee" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 5
}</component>
<component name="ProjectId" id="2w23zazSC8gW9XDwUxbl8Fam8DV" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.cidr.known.project.marker": "true",
"RunOnceActivity.git.unshallow": "true",
"RunOnceActivity.readMode.enableVisualFormatting": "true",
"cf.first.check.clang-format": "false",
"cidr.known.project.marker": "true",
"com.google.services.firebase.aqiPopupShown": "true",
"git-widget-placeholder": "feat/android-version",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "/home/johnc/Code/haystack-app/frontend",
"settings.editor.selected.configurable": "AndroidSdkUpdater"
}
}]]></component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="4ea94c05-c21c-40f9-ad16-43233a3011ee" name="Changes" comment="" />
<created>1745226104717</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1745226104717</updated>
</task>
<servers />
</component>
</project>

932
frontend/bun.lock Normal file
View File

@ -0,0 +1,932 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "haystack",
"dependencies": {
"@kobalte/core": "^0.13.9",
"@kobalte/tailwindcss": "^0.9.0",
"@solidjs/router": "^0.15.3",
"@tabler/icons-solidjs": "^3.30.0",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "~2",
"@tauri-apps/plugin-fs": "~2",
"@tauri-apps/plugin-http": "2.4.3",
"@tauri-apps/plugin-log": "~2",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-os": "2.2.1",
"clsx": "^2.1.1",
"fuse.js": "^7.1.0",
"jwt-decode": "^4.0.0",
"solid-js": "^1.9.3",
"solid-markdown": "^2.0.14",
"solid-motionone": "^1.0.3",
"solidjs-markdown": "^0.2.0",
"tailwind-scrollbar-hide": "^2.0.0",
"tauri-plugin-ios-shared-token-api": "file:../tauri-plugin-ios-shared-token",
"tauri-plugin-sharetarget-api": "^0.1.6",
"valibot": "^1.0.0-rc.2",
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@tauri-apps/cli": "^2.5.0",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.3",
"postcss-cli": "^11.0.0",
"tailwindcss": "3.4.0",
"typescript": "~5.6.2",
"vite": "^6.0.3",
"vite-plugin-solid": "^2.11.0",
},
},
},
"packages": {
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
"@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
"@babel/compat-data": ["@babel/compat-data@7.26.8", "", {}, "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ=="],
"@babel/core": ["@babel/core@7.26.10", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.10", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.10", "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", "@babel/traverse": "^7.26.10", "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ=="],
"@babel/generator": ["@babel/generator@7.27.0", "", { "dependencies": { "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw=="],
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.0", "", { "dependencies": { "@babel/compat-data": "^7.26.8", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA=="],
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="],
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.26.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw=="],
"@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.26.5", "", {}, "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg=="],
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="],
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.25.9", "", {}, "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="],
"@babel/helpers": ["@babel/helpers@7.27.0", "", { "dependencies": { "@babel/template": "^7.27.0", "@babel/types": "^7.27.0" } }, "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg=="],
"@babel/parser": ["@babel/parser@7.27.0", "", { "dependencies": { "@babel/types": "^7.27.0" }, "bin": "./bin/babel-parser.js" }, "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg=="],
"@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA=="],
"@babel/template": ["@babel/template@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0" } }, "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA=="],
"@babel/traverse": ["@babel/traverse@7.27.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.27.0", "@babel/parser": "^7.27.0", "@babel/template": "^7.27.0", "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA=="],
"@babel/types": ["@babel/types@7.27.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg=="],
"@biomejs/biome": ["@biomejs/biome@1.9.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.9.4", "@biomejs/cli-darwin-x64": "1.9.4", "@biomejs/cli-linux-arm64": "1.9.4", "@biomejs/cli-linux-arm64-musl": "1.9.4", "@biomejs/cli-linux-x64": "1.9.4", "@biomejs/cli-linux-x64-musl": "1.9.4", "@biomejs/cli-win32-arm64": "1.9.4", "@biomejs/cli-win32-x64": "1.9.4" }, "bin": { "biome": "bin/biome" } }, "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="],
"@corvu/utils": ["@corvu/utils@0.4.2", "", { "dependencies": { "@floating-ui/dom": "^1.6.11" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA=="],
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.3", "", { "os": "android", "cpu": "arm" }, "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A=="],
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.3", "", { "os": "android", "cpu": "arm64" }, "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ=="],
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.3", "", { "os": "android", "cpu": "x64" }, "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ=="],
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w=="],
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A=="],
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw=="],
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q=="],
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.3", "", { "os": "linux", "cpu": "arm" }, "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ=="],
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A=="],
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw=="],
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.3", "", { "os": "linux", "cpu": "none" }, "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g=="],
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.3", "", { "os": "linux", "cpu": "none" }, "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag=="],
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg=="],
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.3", "", { "os": "linux", "cpu": "none" }, "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA=="],
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ=="],
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.3", "", { "os": "linux", "cpu": "x64" }, "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA=="],
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.3", "", { "os": "none", "cpu": "arm64" }, "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA=="],
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.3", "", { "os": "none", "cpu": "x64" }, "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g=="],
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ=="],
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w=="],
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA=="],
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ=="],
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew=="],
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.3", "", { "os": "win32", "cpu": "x64" }, "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg=="],
"@floating-ui/core": ["@floating-ui/core@1.6.9", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw=="],
"@floating-ui/dom": ["@floating-ui/dom@1.6.13", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.9" } }, "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w=="],
"@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="],
"@internationalized/date": ["@internationalized/date@3.8.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-J51AJ0fEL68hE4CwGPa6E0PO6JDaVLd8aln48xFCSy7CZkZc96dGEGmLs2OEEbBxcsVZtfrqkXJwI2/MSG8yKw=="],
"@internationalized/number": ["@internationalized/number@3.6.1", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-UVsb4bCwbL944E0SX50CHFtWEeZ2uB5VozZ5yDXJdq6iPZsZO5p+bjVMZh2GxHf4Bs/7xtDCcPwEa2NU9DaG/g=="],
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
"@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="],
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="],
"@kobalte/core": ["@kobalte/core@0.13.9", "", { "dependencies": { "@floating-ui/dom": "^1.5.1", "@internationalized/date": "^3.4.0", "@internationalized/number": "^3.2.1", "@kobalte/utils": "^0.9.1", "@solid-primitives/props": "^3.1.8", "@solid-primitives/resize-observer": "^2.0.26", "solid-presence": "^0.1.8", "solid-prevent-scroll": "^0.1.4" }, "peerDependencies": { "solid-js": "^1.8.15" } }, "sha512-TkeSpgNy7I5k8jwjqT9CK3teAxN0aFb3yyL9ODb06JVYMwXIk+UKrizoAF1ahLUP85lKnxv44B4Y5cXkHShgqw=="],
"@kobalte/tailwindcss": ["@kobalte/tailwindcss@0.9.0", "", { "peerDependencies": { "tailwindcss": "^3.3.3" } }, "sha512-WbueJTVRiO4yrmfHIBwp07y3M5iibJ/gauEAQ7mOyg1tZulvpO7SM/UdgzX95a9a0KDt1mQFxwO7RmpOUXWOWA=="],
"@kobalte/utils": ["@kobalte/utils@0.9.1", "", { "dependencies": { "@solid-primitives/event-listener": "^2.2.14", "@solid-primitives/keyed": "^1.2.0", "@solid-primitives/map": "^0.4.7", "@solid-primitives/media": "^2.2.4", "@solid-primitives/props": "^3.1.8", "@solid-primitives/refs": "^1.0.5", "@solid-primitives/utils": "^6.2.1" }, "peerDependencies": { "solid-js": "^1.8.8" } }, "sha512-eeU60A3kprIiBDAfv9gUJX1tXGLuZiKMajUfSQURAF2pk4ZoMYiqIzmrMBvzcxP39xnYttgTyQEVLwiTZnrV4w=="],
"@motionone/animation": ["@motionone/animation@10.18.0", "", { "dependencies": { "@motionone/easing": "^10.18.0", "@motionone/types": "^10.17.1", "@motionone/utils": "^10.18.0", "tslib": "^2.3.1" } }, "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw=="],
"@motionone/dom": ["@motionone/dom@10.18.0", "", { "dependencies": { "@motionone/animation": "^10.18.0", "@motionone/generators": "^10.18.0", "@motionone/types": "^10.17.1", "@motionone/utils": "^10.18.0", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A=="],
"@motionone/easing": ["@motionone/easing@10.18.0", "", { "dependencies": { "@motionone/utils": "^10.18.0", "tslib": "^2.3.1" } }, "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg=="],
"@motionone/generators": ["@motionone/generators@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "@motionone/utils": "^10.18.0", "tslib": "^2.3.1" } }, "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg=="],
"@motionone/types": ["@motionone/types@10.17.1", "", {}, "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A=="],
"@motionone/utils": ["@motionone/utils@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
"@rollup/plugin-typescript": ["@rollup/plugin-typescript@11.1.6", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.14.0||^3.0.0||^4.0.0", "tslib": "*", "typescript": ">=3.7.0" }, "optionalPeers": ["rollup", "tslib"] }, "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA=="],
"@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.40.0", "", { "os": "android", "cpu": "arm" }, "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg=="],
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.40.0", "", { "os": "android", "cpu": "arm64" }, "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w=="],
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.40.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ=="],
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.40.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA=="],
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.40.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg=="],
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.40.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw=="],
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.40.0", "", { "os": "linux", "cpu": "arm" }, "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA=="],
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.40.0", "", { "os": "linux", "cpu": "arm" }, "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg=="],
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.40.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg=="],
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.40.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ=="],
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg=="],
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.40.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw=="],
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA=="],
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.40.0", "", { "os": "linux", "cpu": "none" }, "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ=="],
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.40.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw=="],
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.40.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ=="],
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.40.0", "", { "os": "linux", "cpu": "x64" }, "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw=="],
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.40.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ=="],
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.40.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA=="],
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.40.0", "", { "os": "win32", "cpu": "x64" }, "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ=="],
"@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-TSfR1PNTfojFEYGSxSMCnUhXsaYWBo4p+cm73QmWODa9YnaQAk6PB7VjzG2bOT2D817VlvuOqTj0Qdq+MZrdGg=="],
"@solid-primitives/keyed": ["@solid-primitives/keyed@1.5.0", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-g04CXywgWG/7L4sTxQP6q1gdiirItVBq6ZO9YuLTqPFlkX3uD4IEjeL9cLHP6waahrnO8yL3OZl64pcKGYN5Qw=="],
"@solid-primitives/map": ["@solid-primitives/map@0.4.13", "", { "dependencies": { "@solid-primitives/trigger": "^1.1.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew=="],
"@solid-primitives/media": ["@solid-primitives/media@2.3.0", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.0", "@solid-primitives/rootless": "^1.5.0", "@solid-primitives/static-store": "^0.1.0", "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-7+C3wfbWnGE/WPoNsqcp/EeOP2aNNB92RCpsWhBth8E5lZo/J+rK6jMb7umVsK0zguT8HBpeXp1pFyFbcsHStA=="],
"@solid-primitives/props": ["@solid-primitives/props@3.2.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-vEg5yERdXftJz2+A6B0IMYTrPL9SE2DPmpURV/nZyqQ+PXziF02V4b4SDr6JX3jNJxBlY6c17LqwYEw+bIfGRg=="],
"@solid-primitives/refs": ["@solid-primitives/refs@1.1.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-QJ3bTSQOlPdHBP2m6llrT13FvVzAwZfx41lTN8lQrRwwcZoWb7kfCAjhaohPnwkAsQ6nJpLjtGfT5GOyuCA4tA=="],
"@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.0", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.0", "@solid-primitives/rootless": "^1.5.0", "@solid-primitives/static-store": "^0.1.0", "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-tO9MDAc2pNjpcRd5B8LWbiR1qzIgvGZ5BtTuO98N7CLwd+fnuyGwtlQtJpz5hcLcTnoawpQYLpiRGNgaYW+YzQ=="],
"@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-YJ+EveQeDv9DLqfDKfsPAAGy2x3vBruoD23yn+nD2dT84QjoBxWT1T0qA0TMFjek6/xuN3flqnHtQ4r++4zdjg=="],
"@solid-primitives/static-store": ["@solid-primitives/static-store@0.1.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-6Coau0Kv/dF83UQpbBzc+gnJafOQAPe2jCbB4jmTK5UocsR5cWmFBVRm3kin+nZFVaO4WkuELw0cKANWgTVh8Q=="],
"@solid-primitives/transition-group": ["@solid-primitives/transition-group@1.1.0", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-pL1sEPCHuC4V+Yh+SQsKSPuGDYrZbLJYSkk3AB4TZrWhptEJUS0IHoi7BAynYcMiULbvMMVKFbeFHqINZq0+ig=="],
"@solid-primitives/trigger": ["@solid-primitives/trigger@1.2.0", "", { "dependencies": { "@solid-primitives/utils": "^6.3.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-sW4/3cDXSjYQampn8CIFZ11BlxgNf2li8r2fXnb3b3YWE6RdZZCl8PhvpPF38Gzl0CnryrbTPJWM7OIkseCDgQ=="],
"@solid-primitives/utils": ["@solid-primitives/utils@6.3.0", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-e7hTlJ1Ywh2+g/Qug+n4L1mpfxsikoIS4/sHE2EK9WatQt8UJqop/vE6bsLnXlU1xuhb/jo94Ah5Y27rd4wP7A=="],
"@solidjs/router": ["@solidjs/router@0.15.3", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw=="],
"@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="],
"@tabler/icons": ["@tabler/icons@3.31.0", "", {}, "sha512-dblAdeKY3+GA1U+Q9eziZ0ooVlZMHsE8dqP0RkwvRtEsAULoKOYaCUOcJ4oW1DjWegdxk++UAt2SlQVnmeHv+g=="],
"@tabler/icons-solidjs": ["@tabler/icons-solidjs@3.31.0", "", { "dependencies": { "@tabler/icons": "3.31.0" }, "peerDependencies": { "solid-js": "^1.4.7" } }, "sha512-NB0Tk8++ibD7L7qtabzqBs//G5U9mhq3UkTvEjCWnHg/W4TROeUZqksSXZ9venU9iRZ5rPIqkV20DEsIi8z9vw=="],
"@tauri-apps/api": ["@tauri-apps/api@2.5.0", "", {}, "sha512-Ldux4ip+HGAcPUmuLT8EIkk6yafl5vK0P0c0byzAKzxJh7vxelVtdPONjfgTm96PbN24yjZNESY8CKo8qniluA=="],
"@tauri-apps/cli": ["@tauri-apps/cli@2.5.0", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.5.0", "@tauri-apps/cli-darwin-x64": "2.5.0", "@tauri-apps/cli-linux-arm-gnueabihf": "2.5.0", "@tauri-apps/cli-linux-arm64-gnu": "2.5.0", "@tauri-apps/cli-linux-arm64-musl": "2.5.0", "@tauri-apps/cli-linux-riscv64-gnu": "2.5.0", "@tauri-apps/cli-linux-x64-gnu": "2.5.0", "@tauri-apps/cli-linux-x64-musl": "2.5.0", "@tauri-apps/cli-win32-arm64-msvc": "2.5.0", "@tauri-apps/cli-win32-ia32-msvc": "2.5.0", "@tauri-apps/cli-win32-x64-msvc": "2.5.0" }, "bin": { "tauri": "tauri.js" } }, "sha512-rAtHqG0Gh/IWLjN2zTf3nZqYqbo81oMbqop56rGTjrlWk9pTTAjkqOjSL9XQLIMZ3RbeVjveCqqCA0s8RnLdMg=="],
"@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.5.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VuVAeTFq86dfpoBDNYAdtQVLbP0+2EKCHIIhkaxjeoPARR0sLpFHz2zs0PcFU76e+KAaxtEtAJAXGNUc8E1PzQ=="],
"@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.5.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-hUF01sC06cZVa8+I0/VtsHOk9BbO75rd+YdtHJ48xTdcYaQ5QIwL4yZz9OR1AKBTaUYhBam8UX9Pvd5V2/4Dpw=="],
"@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.5.0", "", { "os": "linux", "cpu": "arm" }, "sha512-LQKqttsK252LlqYyX8R02MinUsfFcy3+NZiJwHFgi5Y3+ZUIAED9cSxJkyNtuY5KMnR4RlpgWyLv4P6akN1xhg=="],
"@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.5.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-mTQufsPcpdHg5RW0zypazMo4L55EfeE5snTzrPqbLX4yCK2qalN7+rnP8O8GT06xhp6ElSP/Ku1M2MR297SByQ=="],
"@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.5.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rQO1HhRUQqyEaal5dUVOQruTRda/TD36s9kv1hTxZiFuSq3558lsTjAcUEnMAtBcBkps20sbyTJNMT0AwYIk8Q=="],
"@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.5.0", "", { "os": "linux", "cpu": "none" }, "sha512-7oS18FN46yDxyw1zX/AxhLAd7T3GrLj3Ai6s8hZKd9qFVzrAn36ESL7d3G05s8wEtsJf26qjXnVF4qleS3dYsA=="],
"@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.5.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SG5sFNL7VMmDBdIg3nO3EzNRT306HsiEQ0N90ILe3ZABYAVoPDO/ttpCO37ApLInTzrq/DLN+gOlC/mgZvLw1w=="],
"@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.5.0", "", { "os": "linux", "cpu": "x64" }, "sha512-QXDM8zp/6v05PNWju5ELsVwF0VH1n6b5pk2E6W/jFbbiwz80Vs1lACl9pv5kEHkrxBj+aWU/03JzGuIj2g3SkQ=="],
"@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.5.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-pFSHFK6b+o9y4Un8w0gGLwVyFTZaC3P0kQ7umRt/BLDkzD5RnQ4vBM7CF8BCU5nkwmEBUCZd7Wt3TWZxe41o6Q=="],
"@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.5.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-EArv1IaRlogdLAQyGlKmEqZqm5RfHCUMhJoedWu7GtdbOMUfSAz6FMX2boE1PtEmNO4An+g188flLeVErrxEKg=="],
"@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.5.0", "", { "os": "win32", "cpu": "x64" }, "sha512-lj43EFYbnAta8pd9JnUq87o+xRUR0odz+4rixBtTUwUgdRdwQ2V9CzFtsMu6FQKpFQ6mujRK6P1IEwhL6ADRsQ=="],
"@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.2.1", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-wZmCouo4PgTosh/UoejPw9DPs6RllS5Pp3fuOV2JobCu36mR5AXU2MzU9NZiVaFi/5Zfc8RN0IhcZHnksJ1o8A=="],
"@tauri-apps/plugin-fs": ["@tauri-apps/plugin-fs@2.2.1", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-KdGzvvA4Eg0Dhw55MwczFbjxLxsTx0FvwwC/0StXlr6IxwPUxh5ziZQoaugkBFs8t+wfebdQrjBEzd8NmmDXNw=="],
"@tauri-apps/plugin-http": ["@tauri-apps/plugin-http@2.4.3", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-Us8X+FikzpaZRNr4kH4HLwyXascHbM42p6LxAqRTQnHPrrqp1usaH4vxWAZalPvTbHJ3gBEMJPHusFJgtjGJjA=="],
"@tauri-apps/plugin-log": ["@tauri-apps/plugin-log@2.4.0", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-j7yrDtLNmayCBOO2esl3aZv9jSXy2an8MDLry3Ys9ZXerwUg35n1Y2uD8HoCR+8Ng/EUgx215+qOUfJasjYrHw=="],
"@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.2.6", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-bSdkuP71ZQRepPOn8BOEdBKYJQvl6+jb160QtJX/i2H9BF6ZySY/kYljh76N2Ne5fJMQRge7rlKoStYQY5Jq1w=="],
"@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.2.1", "", { "dependencies": { "@tauri-apps/api": "^2.0.0" } }, "sha512-cNYpNri2CCc6BaNeB6G/mOtLvg8dFyFQyCUdf2y0K8PIAKGEWdEcu8DECkydU2B+oj4OJihDPD2de5K6cbVl9A=="],
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
"@types/babel__traverse": ["@types/babel__traverse@7.20.7", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng=="],
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
"@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="],
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
"arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
"autoprefixer": ["autoprefixer@10.4.21", "", { "dependencies": { "browserslist": "^4.24.4", "caniuse-lite": "^1.0.30001702", "fraction.js": "^4.3.7", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ=="],
"babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.39.7", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2", "validate-html-nesting": "^1.2.1" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-8GzVmFla7jaTNWW8W+lTMl9YGva4/06CtwJjySnkYtt8G1v9weCzc2SuF1DfrudcCNb2Doetc1FRg33swBYZCA=="],
"babel-preset-solid": ["babel-preset-solid@1.9.5", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.39.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-85I3osODJ1LvZbv8wFozROV1vXq32BubqHXAGu73A//TRs3NLI1OFP83AQBUTSQHwgZQmARjHlJciym3we+V+w=="],
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
"brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"browserslist": ["browserslist@4.24.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A=="],
"camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
"caniuse-lite": ["caniuse-lite@1.0.30001715", "", {}, "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw=="],
"character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
"chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
"commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="],
"decode-named-character-reference": ["decode-named-character-reference@1.1.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w=="],
"dependency-graph": ["dependency-graph@1.0.0", "", {}, "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg=="],
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
"didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],
"diff": ["diff@5.2.0", "", {}, "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A=="],
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
"electron-to-chromium": ["electron-to-chromium@1.5.143", "", {}, "sha512-QqklJMOFBMqe46k8iIOwA9l2hz57V2OKMmP5eSWcUvwx+mASAsbU+wkF1pHjn9ZVSBPrsYWr4/W/95y5SwYg2g=="],
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"entities": ["entities@6.0.0", "", {}, "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw=="],
"esbuild": ["esbuild@0.25.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.3", "@esbuild/android-arm": "0.25.3", "@esbuild/android-arm64": "0.25.3", "@esbuild/android-x64": "0.25.3", "@esbuild/darwin-arm64": "0.25.3", "@esbuild/darwin-x64": "0.25.3", "@esbuild/freebsd-arm64": "0.25.3", "@esbuild/freebsd-x64": "0.25.3", "@esbuild/linux-arm": "0.25.3", "@esbuild/linux-arm64": "0.25.3", "@esbuild/linux-ia32": "0.25.3", "@esbuild/linux-loong64": "0.25.3", "@esbuild/linux-mips64el": "0.25.3", "@esbuild/linux-ppc64": "0.25.3", "@esbuild/linux-riscv64": "0.25.3", "@esbuild/linux-s390x": "0.25.3", "@esbuild/linux-x64": "0.25.3", "@esbuild/netbsd-arm64": "0.25.3", "@esbuild/netbsd-x64": "0.25.3", "@esbuild/openbsd-arm64": "0.25.3", "@esbuild/openbsd-x64": "0.25.3", "@esbuild/sunos-x64": "0.25.3", "@esbuild/win32-arm64": "0.25.3", "@esbuild/win32-ia32": "0.25.3", "@esbuild/win32-x64": "0.25.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q=="],
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
"fdir": ["fdir@6.4.4", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
"fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="],
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"fuse.js": ["fuse.js@7.1.0", "", {}, "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ=="],
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
"glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
"globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
"hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@1.2.0", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/unist": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^2.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "style-to-object": "^0.4.1", "unist-util-position": "^4.0.0", "vfile-message": "^3.0.0" } }, "sha512-Y4FB8Dx2k6zJZrwbexkVm6YVRA8Sho2tTwacjDSr/x5c0wioOpc1VIoLyGUSb8+8xkAnQPAtHbdMvzA6bl0F1w=="],
"hast-util-whitespace": ["hast-util-whitespace@2.0.1", "", {}, "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng=="],
"hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="],
"html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="],
"inline-style-parser": ["inline-style-parser@0.1.1", "", {}, "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="],
"is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
"is-buffer": ["is-buffer@2.0.5", "", {}, "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="],
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
"is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="],
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
"jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="],
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
"jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
"jwt-decode": ["jwt-decode@4.0.0", "", {}, "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA=="],
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
"lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="],
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
"mdast-util-definitions": ["mdast-util-definitions@5.1.2", "", { "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", "unist-util-visit": "^4.0.0" } }, "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA=="],
"mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="],
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="],
"mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="],
"merge-anything": ["merge-anything@5.1.7", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ=="],
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
"micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
"micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
"micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="],
"micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="],
"micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="],
"micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="],
"micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="],
"micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="],
"micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="],
"micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="],
"micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="],
"micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="],
"micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="],
"micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="],
"micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="],
"micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="],
"micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="],
"micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="],
"micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="],
"micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="],
"micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
"mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="],
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
"normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="],
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
"object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="],
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
"parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
"pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="],
"pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
"postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
"postcss-cli": ["postcss-cli@11.0.1", "", { "dependencies": { "chokidar": "^3.3.0", "dependency-graph": "^1.0.0", "fs-extra": "^11.0.0", "picocolors": "^1.0.0", "postcss-load-config": "^5.0.0", "postcss-reporter": "^7.0.0", "pretty-hrtime": "^1.0.3", "read-cache": "^1.0.0", "slash": "^5.0.0", "tinyglobby": "^0.2.12", "yargs": "^17.0.0" }, "peerDependencies": { "postcss": "^8.0.0" }, "bin": { "postcss": "index.js" } }, "sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g=="],
"postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="],
"postcss-js": ["postcss-js@4.0.1", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw=="],
"postcss-load-config": ["postcss-load-config@5.1.0", "", { "dependencies": { "lilconfig": "^3.1.1", "yaml": "^2.4.2" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1" }, "optionalPeers": ["jiti", "postcss", "tsx"] }, "sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA=="],
"postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="],
"postcss-reporter": ["postcss-reporter@7.1.0", "", { "dependencies": { "picocolors": "^1.0.0", "thenby": "^1.3.4" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA=="],
"postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
"postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
"pretty-hrtime": ["pretty-hrtime@1.0.3", "", {}, "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A=="],
"property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="],
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
"remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="],
"remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="],
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
"rollup": ["rollup@4.40.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.40.0", "@rollup/rollup-android-arm64": "4.40.0", "@rollup/rollup-darwin-arm64": "4.40.0", "@rollup/rollup-darwin-x64": "4.40.0", "@rollup/rollup-freebsd-arm64": "4.40.0", "@rollup/rollup-freebsd-x64": "4.40.0", "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", "@rollup/rollup-linux-arm-musleabihf": "4.40.0", "@rollup/rollup-linux-arm64-gnu": "4.40.0", "@rollup/rollup-linux-arm64-musl": "4.40.0", "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-gnu": "4.40.0", "@rollup/rollup-linux-riscv64-musl": "4.40.0", "@rollup/rollup-linux-s390x-gnu": "4.40.0", "@rollup/rollup-linux-x64-gnu": "4.40.0", "@rollup/rollup-linux-x64-musl": "4.40.0", "@rollup/rollup-win32-arm64-msvc": "4.40.0", "@rollup/rollup-win32-ia32-msvc": "4.40.0", "@rollup/rollup-win32-x64-msvc": "4.40.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w=="],
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"seroval": ["seroval@1.2.1", "", {}, "sha512-yBxFFs3zmkvKNmR0pFSU//rIsYjuX418TnlDmc2weaq5XFDqDIV/NOMPBoLrbxjLH42p4UzRuXHryXh9dYcKcw=="],
"seroval-plugins": ["seroval-plugins@1.2.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-H5vs53+39+x4Udwp4J5rNZfgFuA+Lt+uU+09w1gYBVWomtAl98B+E9w7yC05Xc81/HgLvJdlyqJbU0fJCKCmdw=="],
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
"slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="],
"solid-js": ["solid-js@1.9.5", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", "seroval-plugins": "^1.1.0" } }, "sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw=="],
"solid-jsx": ["solid-jsx@0.9.1", "", { "peerDependencies": { "solid-js": "^1.4.0" } }, "sha512-HHTx58rx3tqg5LMGuQnaE1vqZjpl+RMP0jYQnBkTY0xKIASVNSLZJCZoPFrpKH8wWWYyTLHdepgzs8u/e6yz5Q=="],
"solid-markdown": ["solid-markdown@2.0.14", "", { "dependencies": { "comma-separated-tokens": "^2.0.3", "property-information": "^6.3.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "space-separated-tokens": "^2.0.2", "style-to-object": "^0.3.0", "unified": "^11.0.5", "unist-util-visit": "^4.1.2", "vfile": "^6.0.3" }, "peerDependencies": { "solid-js": "^1.6.0" } }, "sha512-Ln8R4TsNWySXvKkS80OHV+CSR/mwjk5XfGvC5UjZo/y/rAbbkBoxt6FXoWsfCkTW6GH9yxYvahSMXsUJU/ov4Q=="],
"solid-motionone": ["solid-motionone@1.0.3", "", { "dependencies": { "@motionone/dom": "^10.17.0", "@motionone/utils": "^10.17.0", "@solid-primitives/props": "^3.1.11", "@solid-primitives/refs": "^1.0.8", "@solid-primitives/transition-group": "^1.0.5", "csstype": "^3.1.3" }, "peerDependencies": { "solid-js": "^1.8.0" } }, "sha512-C1XGpbKz7klrYwYPI75X0TJdIIJWMslLPUIgnu9a0jXqN6TWA65+EByBkhVarZeBfNjVg3+uOrIRFewqZkjuFA=="],
"solid-presence": ["solid-presence@0.1.8", "", { "dependencies": { "@corvu/utils": "~0.4.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA=="],
"solid-prevent-scroll": ["solid-prevent-scroll@0.1.10", "", { "dependencies": { "@corvu/utils": "~0.4.1" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-KplGPX2GHiWJLZ6AXYRql4M127PdYzfwvLJJXMkO+CMb8Np4VxqDAg5S8jLdwlEuBis/ia9DKw2M8dFx5u8Mhw=="],
"solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="],
"solidjs-markdown": ["solidjs-markdown@0.2.0", "", { "dependencies": { "hast-util-to-jsx-runtime": "^1.2.0", "remark-parse": "^10.0.1", "remark-rehype": "^10.1.0", "solid-jsx": "^0.9.1", "unified": "^10.1.2", "vfile": "^5.3.7" } }, "sha512-7jiqmM2Z9Z9EFmE7MtI6KJtQboapUyjtu30RvhO00RZWKP04pNxQpDksNnU9ItnMj50/3mNlV0gx2DoqjrxdHA=="],
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
"string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"style-to-object": ["style-to-object@0.3.0", "", { "dependencies": { "inline-style-parser": "0.1.1" } }, "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA=="],
"sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="],
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
"tailwind-scrollbar-hide": ["tailwind-scrollbar-hide@2.0.0", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || >= 4.0.0 || >= 4.0.0-beta.8 || >= 4.0.0-alpha.20" } }, "sha512-lqiIutHliEiODwBRHy4G2+Tcayo2U7+3+4frBmoMETD72qtah+XhOk5XcPzC1nJvXhXUdfl2ajlMhUc2qC6CIg=="],
"tailwindcss": ["tailwindcss@3.4.0", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.19.1", "lilconfig": "^2.1.0", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", "postcss": "^8.4.23", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.1", "postcss-nested": "^6.0.1", "postcss-selector-parser": "^6.0.11", "resolve": "^1.22.2", "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-VigzymniH77knD1dryXbyxR+ePHihHociZbXnLZHUyzf2MMs2ZVqlUrZ3FvpXP8pno9JzmILt1sZPD19M3IxtA=="],
"tauri-plugin-ios-shared-token-api": ["tauri-plugin-ios-shared-token-api@file:../tauri-plugin-ios-shared-token", { "dependencies": { "@tauri-apps/api": ">=2.0.0-beta.6" }, "devDependencies": { "@rollup/plugin-typescript": "^11.1.6", "rollup": "^4.9.6", "tslib": "^2.6.2", "typescript": "^5.3.3" } }],
"tauri-plugin-sharetarget-api": ["tauri-plugin-sharetarget-api@0.1.6", "", { "dependencies": { "@tauri-apps/api": ">=2.0.0-beta.6" } }, "sha512-R9LgXu7hn8LaCW5ll8tJ4es0N2nCNVnptT4v3HTXInDra9pm5CuXalX3m5W7+/XTwOFn0sMRv4eOKz8S5FEy1w=="],
"thenby": ["thenby@1.3.4", "", {}, "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ=="],
"thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
"thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
"tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
"ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="],
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
"unist-util-generated": ["unist-util-generated@2.0.1", "", {}, "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A=="],
"unist-util-is": ["unist-util-is@5.2.1", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw=="],
"unist-util-position": ["unist-util-position@4.0.4", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg=="],
"unist-util-stringify-position": ["unist-util-stringify-position@3.0.3", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg=="],
"unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="],
"unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="],
"universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"uvu": ["uvu@0.5.6", "", { "dependencies": { "dequal": "^2.0.0", "diff": "^5.0.0", "kleur": "^4.0.3", "sade": "^1.7.3" }, "bin": { "uvu": "bin.js" } }, "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA=="],
"valibot": ["valibot@1.0.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-1Hc0ihzWxBar6NGeZv7fPLY0QuxFMyxwYR2sF1Blu7Wq7EnremwY2W02tit2ij2VJT8HcSkHAQqmFfl77f73Yw=="],
"validate-html-nesting": ["validate-html-nesting@1.2.2", "", {}, "sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg=="],
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="],
"vite": ["vite@6.3.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw=="],
"vite-plugin-solid": ["vite-plugin-solid@2.11.6", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-Sl5CTqJTGyEeOsmdH6BOgalIZlwH3t4/y0RQuFLMGnvWMBvxb4+lq7x3BSiAw6etf0QexfNJW7HSOO/Qf7pigg=="],
"vitefu": ["vitefu@1.0.6", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"yaml": ["yaml@2.7.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ=="],
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
"@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="],
"chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"hast-util-to-jsx-runtime/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="],
"hast-util-to-jsx-runtime/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"hast-util-to-jsx-runtime/style-to-object": ["style-to-object@0.4.4", "", { "dependencies": { "inline-style-parser": "0.1.1" } }, "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg=="],
"hast-util-to-jsx-runtime/vfile-message": ["vfile-message@3.1.4", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^3.0.0" } }, "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw=="],
"mdast-util-definitions/@types/mdast": ["@types/mdast@3.0.15", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ=="],
"mdast-util-definitions/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"mdast-util-from-markdown/unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
"mdast-util-to-hast/unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
"mdast-util-to-hast/unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="],
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
"postcss-load-config/lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
"readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"solidjs-markdown/remark-parse": ["remark-parse@10.0.2", "", { "dependencies": { "@types/mdast": "^3.0.0", "mdast-util-from-markdown": "^1.0.0", "unified": "^10.0.0" } }, "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw=="],
"solidjs-markdown/remark-rehype": ["remark-rehype@10.1.0", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/mdast": "^3.0.0", "mdast-util-to-hast": "^12.1.0", "unified": "^10.0.0" } }, "sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw=="],
"solidjs-markdown/unified": ["unified@10.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "bail": "^2.0.0", "extend": "^3.0.0", "is-buffer": "^2.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^5.0.0" } }, "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q=="],
"solidjs-markdown/vfile": ["vfile@5.3.7", "", { "dependencies": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", "unist-util-stringify-position": "^3.0.0", "vfile-message": "^3.0.0" } }, "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g=="],
"tailwindcss/postcss-load-config": ["postcss-load-config@4.0.2", "", { "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ=="],
"unist-util-is/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"unist-util-position/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"unist-util-stringify-position/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"unist-util-visit/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"unist-util-visit-parents/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"vfile-message/unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
"@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
"@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
"mdast-util-to-hast/unist-util-visit/unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="],
"mdast-util-to-hast/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="],
"solidjs-markdown/remark-parse/@types/mdast": ["@types/mdast@3.0.15", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown": ["mdast-util-from-markdown@1.3.1", "", { "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", "decode-named-character-reference": "^1.0.0", "mdast-util-to-string": "^3.1.0", "micromark": "^3.0.0", "micromark-util-decode-numeric-character-reference": "^1.0.0", "micromark-util-decode-string": "^1.0.0", "micromark-util-normalize-identifier": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0", "unist-util-stringify-position": "^3.0.0", "uvu": "^0.5.0" } }, "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww=="],
"solidjs-markdown/remark-rehype/@types/hast": ["@types/hast@2.3.10", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw=="],
"solidjs-markdown/remark-rehype/@types/mdast": ["@types/mdast@3.0.15", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ=="],
"solidjs-markdown/remark-rehype/mdast-util-to-hast": ["mdast-util-to-hast@12.3.0", "", { "dependencies": { "@types/hast": "^2.0.0", "@types/mdast": "^3.0.0", "mdast-util-definitions": "^5.0.0", "micromark-util-sanitize-uri": "^1.1.0", "trim-lines": "^3.0.0", "unist-util-generated": "^2.0.0", "unist-util-position": "^4.0.0", "unist-util-visit": "^4.0.0" } }, "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw=="],
"solidjs-markdown/unified/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"solidjs-markdown/vfile/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"solidjs-markdown/vfile/vfile-message": ["vfile-message@3.1.4", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^3.0.0" } }, "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw=="],
"tailwindcss/postcss-load-config/lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
"solidjs-markdown/remark-parse/@types/mdast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/mdast-util-to-string": ["mdast-util-to-string@3.2.0", "", { "dependencies": { "@types/mdast": "^3.0.0" } }, "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark": ["micromark@3.2.0", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "micromark-core-commonmark": "^1.0.1", "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-chunked": "^1.0.0", "micromark-util-combine-extensions": "^1.0.0", "micromark-util-decode-numeric-character-reference": "^1.0.0", "micromark-util-encode": "^1.0.0", "micromark-util-normalize-identifier": "^1.0.0", "micromark-util-resolve-all": "^1.0.0", "micromark-util-sanitize-uri": "^1.0.0", "micromark-util-subtokenize": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.1", "uvu": "^0.5.0" } }, "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@1.1.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0" } }, "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark-util-decode-string": ["micromark-util-decode-string@1.1.0", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-decode-numeric-character-reference": "^1.0.0", "micromark-util-symbol": "^1.0.0" } }, "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@1.1.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0" } }, "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark-util-symbol": ["micromark-util-symbol@1.1.0", "", {}, "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark-util-types": ["micromark-util-types@1.1.0", "", {}, "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg=="],
"solidjs-markdown/remark-rehype/@types/hast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"solidjs-markdown/remark-rehype/@types/mdast/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
"solidjs-markdown/remark-rehype/mdast-util-to-hast/micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@1.2.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-encode": "^1.0.0", "micromark-util-symbol": "^1.0.0" } }, "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-core-commonmark": ["micromark-core-commonmark@1.1.0", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-factory-destination": "^1.0.0", "micromark-factory-label": "^1.0.0", "micromark-factory-space": "^1.0.0", "micromark-factory-title": "^1.0.0", "micromark-factory-whitespace": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-chunked": "^1.0.0", "micromark-util-classify-character": "^1.0.0", "micromark-util-html-tag-name": "^1.0.0", "micromark-util-normalize-identifier": "^1.0.0", "micromark-util-resolve-all": "^1.0.0", "micromark-util-subtokenize": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.1", "uvu": "^0.5.0" } }, "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-factory-space": ["micromark-factory-space@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-util-character": ["micromark-util-character@1.2.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-util-chunked": ["micromark-util-chunked@1.1.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0" } }, "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-util-combine-extensions": ["micromark-util-combine-extensions@1.1.0", "", { "dependencies": { "micromark-util-chunked": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-util-encode": ["micromark-util-encode@1.1.0", "", {}, "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-util-resolve-all": ["micromark-util-resolve-all@1.1.0", "", { "dependencies": { "micromark-util-types": "^1.0.0" } }, "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@1.2.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-encode": "^1.0.0", "micromark-util-symbol": "^1.0.0" } }, "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-util-subtokenize": ["micromark-util-subtokenize@1.1.0", "", { "dependencies": { "micromark-util-chunked": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0", "uvu": "^0.5.0" } }, "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark-util-decode-string/micromark-util-character": ["micromark-util-character@1.2.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg=="],
"solidjs-markdown/remark-rehype/mdast-util-to-hast/micromark-util-sanitize-uri/micromark-util-character": ["micromark-util-character@1.2.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg=="],
"solidjs-markdown/remark-rehype/mdast-util-to-hast/micromark-util-sanitize-uri/micromark-util-encode": ["micromark-util-encode@1.1.0", "", {}, "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw=="],
"solidjs-markdown/remark-rehype/mdast-util-to-hast/micromark-util-sanitize-uri/micromark-util-symbol": ["micromark-util-symbol@1.1.0", "", {}, "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-core-commonmark/micromark-factory-destination": ["micromark-factory-destination@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-core-commonmark/micromark-factory-label": ["micromark-factory-label@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0", "uvu": "^0.5.0" } }, "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-core-commonmark/micromark-factory-title": ["micromark-factory-title@1.1.0", "", { "dependencies": { "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-core-commonmark/micromark-factory-whitespace": ["micromark-factory-whitespace@1.1.0", "", { "dependencies": { "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-core-commonmark/micromark-util-classify-character": ["micromark-util-classify-character@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw=="],
"solidjs-markdown/remark-parse/mdast-util-from-markdown/micromark/micromark-core-commonmark/micromark-util-html-tag-name": ["micromark-util-html-tag-name@1.2.0", "", {}, "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q=="],
"solidjs-markdown/remark-rehype/mdast-util-to-hast/micromark-util-sanitize-uri/micromark-util-character/micromark-util-types": ["micromark-util-types@1.1.0", "", {}, "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg=="],
}
}

Binary file not shown.

View File

@ -1,48 +1,51 @@
{ {
"name": "haystack", "name": "haystack",
"version": "0.1.0", "version": "0.1.0",
"description": "Screenshots that organize themselves", "description": "Screenshots that organize themselves",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "vite", "start": "vite",
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"serve": "vite preview", "serve": "vite preview",
"tauri": "tauri", "tauri": "tauri",
"lint": "bunx @biomejs/biome lint .", "lint": "bunx @biomejs/biome lint .",
"format": "bunx @biomejs/biome format . --write" "format": "bunx @biomejs/biome format . --write"
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@kobalte/core": "^0.13.9", "@kobalte/core": "^0.13.9",
"@kobalte/tailwindcss": "^0.9.0", "@kobalte/tailwindcss": "^0.9.0",
"@solidjs/router": "^0.15.3", "@solidjs/router": "^0.15.3",
"@tabler/icons-solidjs": "^3.30.0", "@tabler/icons-solidjs": "^3.30.0",
"@tauri-apps/api": "^2", "@tauri-apps/api": "^2",
"@tauri-apps/plugin-dialog": "~2", "@tauri-apps/plugin-dialog": "~2",
"@tauri-apps/plugin-fs": "~2", "@tauri-apps/plugin-fs": "~2",
"@tauri-apps/plugin-http": "~2", "@tauri-apps/plugin-http": "2.4.3",
"@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-log": "~2",
"clsx": "^2.1.1", "@tauri-apps/plugin-opener": "^2",
"fuse.js": "^7.1.0", "@tauri-apps/plugin-os": "2.2.1",
"jwt-decode": "^4.0.0", "clsx": "^2.1.1",
"solid-js": "^1.9.3", "fuse.js": "^7.1.0",
"solid-markdown": "^2.0.14", "jwt-decode": "^4.0.0",
"solid-motionone": "^1.0.3", "solid-js": "^1.9.3",
"solidjs-markdown": "^0.2.0", "solid-markdown": "^2.0.14",
"tailwind-scrollbar-hide": "^2.0.0", "solid-motionone": "^1.0.3",
"tauri-plugin-sharetarget-api": "^0.1.6", "solidjs-markdown": "^0.2.0",
"valibot": "^1.0.0-rc.2" "tailwind-scrollbar-hide": "^2.0.0",
}, "tauri-plugin-ios-shared-token-api": "file:../tauri-plugin-ios-shared-token",
"devDependencies": { "tauri-plugin-sharetarget-api": "^0.1.6",
"@biomejs/biome": "^1.9.4", "valibot": "^1.0.0-rc.2"
"@tauri-apps/cli": "^2", },
"autoprefixer": "^10.4.20", "devDependencies": {
"postcss": "^8.5.3", "@biomejs/biome": "^1.9.4",
"postcss-cli": "^11.0.0", "@tauri-apps/cli": "^2.5.0",
"tailwindcss": "3.4.0", "autoprefixer": "^10.4.20",
"typescript": "~5.6.2", "postcss": "^8.5.3",
"vite": "^6.0.3", "postcss-cli": "^11.0.0",
"vite-plugin-solid": "^2.11.0" "tailwindcss": "3.4.0",
} "typescript": "~5.6.2",
"vite": "^6.0.3",
"vite-plugin-solid": "^2.11.0"
}
} }

BIN
frontend/src-tauri/.DS_Store vendored Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -15,27 +15,31 @@ name = "haystack_lib"
crate-type = ["staticlib", "cdylib", "rlib"] crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies] [build-dependencies]
tauri-build = { version = "2.0.0-beta.12", features = [] } tauri-build = { version = "2", features = [] }
[dependencies] [dependencies]
tauri = { version = "2.0.0-beta.12", features = ["macos-private-api"] } tauri = { version = "2", features = ["macos-private-api", "tray-icon"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
notify = "6.1.1" notify = "6.1.1"
base64 = "0.21.7" base64 = "0.21.7"
tokio = { version = "1.36.0", features = ["full"] } tokio = { version = "1.36.0", features = ["full"] }
tauri-plugin-store = "2.0.0-beta.12" chrono = "0.4"
tauri-plugin-http = "2.0.0-beta.12" log = "0.4"
tauri-plugin-http = "2.4.3"
tauri-plugin-log = "2"
tauri-plugin-fs = "2" tauri-plugin-fs = "2"
tauri-plugin-dialog = "2.2.1" tauri-plugin-os = "2.2.1"
tauri-plugin-opener = "2.2.6" tauri-plugin-store = "2"
tauri-plugin-sharetarget = "0.1.6"
[target."cfg(target_os = \"macos\")".dependencies] [target."cfg(target_os = \"macos\")".dependencies]
cocoa = "0.26" cocoa = "0.26"
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] [target."cfg(any(target_os = \"macos\", target_os = \"linux\", target_os = \"windows\"))".dependencies]
tauri-plugin-global-shortcut = "2.0.0-beta.12" tauri-plugin-global-shortcut = "2"
[target."cfg(target_os = \"android\")".dependencies] [target."cfg(target_os = \"android\")".dependencies]
tauri-plugin-sharetarget = "0.1.6" tauri-plugin-sharetarget = "0.1.6"
[target."cfg(any(target_os = \"ios\"))".dependencies]
tauri-plugin-ios-shared-token = { path = "../../tauri-plugin-ios-shared-token"}

View File

@ -0,0 +1,8 @@
identifier = "android"
description = "Capabilities for Android platforms"
windows = ["main"]
platforms = ["android"]
permissions = [
"sharetarget:default"
]

View File

@ -6,8 +6,10 @@ platforms = ["linux", "macOS", "windows"]
permissions = [ permissions = [
"core:default", "core:default",
"core:window:allow-start-dragging", "core:window:allow-start-dragging",
"core:window:allow-show",
"core:window:allow-set-focus",
"fs:default", "fs:default",
"http:default", "os:default",
{ identifier = "http:default", allow = [ { identifier = "http:default", allow = [
{ url = "https://haystack.johncosta.tech" }, { url = "https://haystack.johncosta.tech" },
{ url = "http://localhost:3040" }, { url = "http://localhost:3040" },

View File

@ -0,0 +1,8 @@
identifier = "iOS"
description = "Capabilities for iOS platforms"
windows = ["main"]
platforms = ["iOS"]
permissions = [
"ios-shared-token:default"
]

View File

@ -7,7 +7,7 @@ permissions = [
"core:default", "core:default",
"fs:default", "fs:default",
"http:default", "http:default",
"sharetarget:default", "os:default",
{ identifier = "http:default", allow = [ { identifier = "http:default", allow = [
{ url = "https://haystack.johncosta.tech" }, { url = "https://haystack.johncosta.tech" },
{ url = "http://localhost:3040" }, { url = "http://localhost:3040" },

View File

@ -3,4 +3,5 @@
/src/main/assets/tauri.conf.json /src/main/assets/tauri.conf.json
/tauri.build.gradle.kts /tauri.build.gradle.kts
/proguard-tauri.pro /proguard-tauri.pro
/tauri.properties /tauri.properties
upload_certificate.pem

View File

@ -23,7 +23,7 @@ android {
namespace = "com.haystack.app" namespace = "com.haystack.app"
defaultConfig { defaultConfig {
manifestPlaceholders["usesCleartextTraffic"] = "false" manifestPlaceholders["usesCleartextTraffic"] = "false"
applicationId = "com.haystack.app" applicationId = "com.screenshot.haystack.app"
minSdk = 21 minSdk = 21
targetSdk = 34 targetSdk = 34
versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt()

View File

@ -26,6 +26,12 @@
<!-- AndroidTV support --> <!-- AndroidTV support -->
<category android:name="android.intent.category.LEANBACK_LAUNCHER" /> <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.BROWSABLE" />
</intent-filter>
</activity> </activity>
<provider <provider

View File

@ -22,4 +22,4 @@ kotlin.code.style=official
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.nonFinalResIds=false android.nonFinalResIds=false
org.gradle.java.home=/usr/lib/jvm/java-21-openjdk # org.gradle.java.home=/usr/lib/jvm/java-21-openjdk

BIN
frontend/src-tauri/gen/apple/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
xcuserdata/
build/
Externals/

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,116 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "AppIcon-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "AppIcon-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29x29@2x-1.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "AppIcon-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "AppIcon-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "AppIcon-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "AppIcon-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "AppIcon-20x20@2x-1.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "AppIcon-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "AppIcon-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "AppIcon-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "AppIcon-40x40@2x-1.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "AppIcon-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "AppIcon-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "AppIcon-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "AppIcon-512@2x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>debugging</string>
</dict>
</plist>

Binary file not shown.

View File

@ -0,0 +1,766 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 70;
objects = {
/* Begin PBXBuildFile section */
16C383BC47682E60119C08CB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21497598D6296AB30C0EBA84 /* UIKit.framework */; };
28AC4E4A2DD0E21600A78D36 /* Sharing.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 28AC4E282DCFF4B000A78D36 /* Sharing.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4CF1B89C17C5E734976BEFBE /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C6D4774DE6800DAE9E77C70 /* Metal.framework */; };
6AAF6095EAF01A93F2CE8305 /* libapp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C62A99D37C1C342BB06981B /* libapp.a */; };
7123EC8A6063C72E5DA3E659 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE76A4E4971EE0237680C836 /* QuartzCore.framework */; };
721E69F824DAAA8F37A0B200 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3B744E798409E96A0E89BC52 /* main.mm */; };
963FC20F9ACC71A08235E8FE /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 821EF15B40968C544308C548 /* assets */; };
9CD4A99062C9C9E459750476 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1C223AE96283F8269EFE1D03 /* Assets.xcassets */; };
A447CC741463FB47911E4B24 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A96F98DDB426B456946F1D11 /* MetalKit.framework */; };
BE9C241792BABFDF1D2DDE4F /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ECBDB6420B28D950ADFD5BD /* WebKit.framework */; };
CF2CEA32AF7EA58A3A0F365B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F2840E2A8444B5D60F2DCC9C /* Security.framework */; };
E13ADF7A534E46B1449CB980 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DB38655A555F328EC1BB430 /* CoreGraphics.framework */; };
E41492640ABA177519E3F513 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2CE665AA7ABC7563C685FAA6 /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
28AC4E302DCFF4B000A78D36 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 193F5589816ED16BC8109D31 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 28AC4E272DCFF4B000A78D36;
remoteInfo = Sharing;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
283EED912DC6170E00943E7E /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = "";
dstSubfolderSpec = 13;
files = (
28AC4E4A2DD0E21600A78D36 /* Sharing.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0A480F5846CD211418A57C1C /* shortcut.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = shortcut.rs; sourceTree = "<group>"; };
0AF1829A934DE85E03752468 /* utils.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = utils.rs; sourceTree = "<group>"; };
0C62A99D37C1C342BB06981B /* libapp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libapp.a; sourceTree = "<group>"; };
1C223AE96283F8269EFE1D03 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
1ECBDB6420B28D950ADFD5BD /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
21497598D6296AB30C0EBA84 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
28AC4E282DCFF4B000A78D36 /* Sharing.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Sharing.appex; sourceTree = BUILT_PRODUCTS_DIR; };
2CE665AA7ABC7563C685FAA6 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
3ADC946E8026E7A68FA70BFA /* main.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = main.rs; sourceTree = "<group>"; };
3B744E798409E96A0E89BC52 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
3DB38655A555F328EC1BB430 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
470BC2848DBE1D2B07A68E45 /* Haystack_iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Haystack_iOS.entitlements; sourceTree = "<group>"; };
4BA36EE3303714FB12529F11 /* lib.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = lib.rs; sourceTree = "<group>"; };
4C6D4774DE6800DAE9E77C70 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
57AA2068BB6F43E241AB4438 /* state.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = state.rs; sourceTree = "<group>"; };
6E834838D3CA26B3762E5A2C /* bindings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings.h; sourceTree = "<group>"; };
7135138DF06A04E380F056CD /* window.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = window.rs; sourceTree = "<group>"; };
7B915725F1CF75963D589426 /* commands.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = commands.rs; sourceTree = "<group>"; };
821EF15B40968C544308C548 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = SOURCE_ROOT; };
A96F98DDB426B456946F1D11 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
BE76A4E4971EE0237680C836 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
CD15C8A888D518BB414EB1DE /* screenshot.rs */ = {isa = PBXFileReference; lastKnownFileType = text; path = screenshot.rs; sourceTree = "<group>"; };
D4A71980828D15BC10ECF3D2 /* Haystack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Haystack.app; sourceTree = BUILT_PRODUCTS_DIR; };
EBD929FA6D544E53CE3E43F0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
F2840E2A8444B5D60F2DCC9C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
28AC4E332DCFF4B000A78D36 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = 28AC4E272DCFF4B000A78D36 /* Sharing */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
28AC4E292DCFF4B000A78D36 /* Sharing */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (28AC4E332DCFF4B000A78D36 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = Sharing; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
26393DAD0BBD67E4F16745AC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6AAF6095EAF01A93F2CE8305 /* libapp.a in Frameworks */,
E13ADF7A534E46B1449CB980 /* CoreGraphics.framework in Frameworks */,
4CF1B89C17C5E734976BEFBE /* Metal.framework in Frameworks */,
A447CC741463FB47911E4B24 /* MetalKit.framework in Frameworks */,
7123EC8A6063C72E5DA3E659 /* QuartzCore.framework in Frameworks */,
CF2CEA32AF7EA58A3A0F365B /* Security.framework in Frameworks */,
16C383BC47682E60119C08CB /* UIKit.framework in Frameworks */,
BE9C241792BABFDF1D2DDE4F /* WebKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
28AC4E252DCFF4B000A78D36 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
37817BC58F972A116E99B5A4 /* bindings */ = {
isa = PBXGroup;
children = (
6E834838D3CA26B3762E5A2C /* bindings.h */,
);
path = bindings;
sourceTree = "<group>";
};
3976EF9B359101EBE231CF77 /* src */ = {
isa = PBXGroup;
children = (
7B915725F1CF75963D589426 /* commands.rs */,
4BA36EE3303714FB12529F11 /* lib.rs */,
3ADC946E8026E7A68FA70BFA /* main.rs */,
CD15C8A888D518BB414EB1DE /* screenshot.rs */,
0A480F5846CD211418A57C1C /* shortcut.rs */,
57AA2068BB6F43E241AB4438 /* state.rs */,
0AF1829A934DE85E03752468 /* utils.rs */,
7135138DF06A04E380F056CD /* window.rs */,
);
name = src;
path = ../../src;
sourceTree = "<group>";
};
5157718C625E46F07FAC4F7C /* Frameworks */ = {
isa = PBXGroup;
children = (
3DB38655A555F328EC1BB430 /* CoreGraphics.framework */,
0C62A99D37C1C342BB06981B /* libapp.a */,
4C6D4774DE6800DAE9E77C70 /* Metal.framework */,
A96F98DDB426B456946F1D11 /* MetalKit.framework */,
BE76A4E4971EE0237680C836 /* QuartzCore.framework */,
F2840E2A8444B5D60F2DCC9C /* Security.framework */,
21497598D6296AB30C0EBA84 /* UIKit.framework */,
1ECBDB6420B28D950ADFD5BD /* WebKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
5D14D0B3A1E4F17999F21EC3 /* Haystack_iOS */ = {
isa = PBXGroup;
children = (
470BC2848DBE1D2B07A68E45 /* Haystack_iOS.entitlements */,
EBD929FA6D544E53CE3E43F0 /* Info.plist */,
);
path = Haystack_iOS;
sourceTree = "<group>";
};
84D53E3A8587FE554E32F5F0 /* Products */ = {
isa = PBXGroup;
children = (
D4A71980828D15BC10ECF3D2 /* Haystack.app */,
28AC4E282DCFF4B000A78D36 /* Sharing.appex */,
);
name = Products;
sourceTree = "<group>";
};
99B42F02A0EEA086F70E7F36 /* Sources */ = {
isa = PBXGroup;
children = (
F653AB1F253719325B2BC8D0 /* Haystack */,
);
path = Sources;
sourceTree = "<group>";
};
A9913F960CDB1010002108D3 = {
isa = PBXGroup;
children = (
821EF15B40968C544308C548 /* assets */,
1C223AE96283F8269EFE1D03 /* Assets.xcassets */,
2CE665AA7ABC7563C685FAA6 /* LaunchScreen.storyboard */,
D4E3C8CB60536F9D70BE2F89 /* Externals */,
5D14D0B3A1E4F17999F21EC3 /* Haystack_iOS */,
99B42F02A0EEA086F70E7F36 /* Sources */,
3976EF9B359101EBE231CF77 /* src */,
28AC4E292DCFF4B000A78D36 /* Sharing */,
5157718C625E46F07FAC4F7C /* Frameworks */,
84D53E3A8587FE554E32F5F0 /* Products */,
);
sourceTree = "<group>";
};
D4E3C8CB60536F9D70BE2F89 /* Externals */ = {
isa = PBXGroup;
children = (
);
path = Externals;
sourceTree = "<group>";
};
F653AB1F253719325B2BC8D0 /* Haystack */ = {
isa = PBXGroup;
children = (
3B744E798409E96A0E89BC52 /* main.mm */,
37817BC58F972A116E99B5A4 /* bindings */,
);
path = Haystack;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
28AC4E272DCFF4B000A78D36 /* Sharing */ = {
isa = PBXNativeTarget;
buildConfigurationList = 28AC4E342DCFF4B000A78D36 /* Build configuration list for PBXNativeTarget "Sharing" */;
buildPhases = (
28AC4E242DCFF4B000A78D36 /* Sources */,
28AC4E252DCFF4B000A78D36 /* Frameworks */,
28AC4E262DCFF4B000A78D36 /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
28AC4E292DCFF4B000A78D36 /* Sharing */,
);
name = Sharing;
packageProductDependencies = (
);
productName = Sharing;
productReference = 28AC4E282DCFF4B000A78D36 /* Sharing.appex */;
productType = "com.apple.product-type.app-extension";
};
28B448F5673D227E72859E56 /* Haystack_iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 58C375D27CA00AE30B18A640 /* Build configuration list for PBXNativeTarget "Haystack_iOS" */;
buildPhases = (
6DAC3F72C0E614FB63E90870 /* Build Rust Code */,
2B0A32A8DA58C48417D38579 /* Sources */,
2A76C4DB730794FBF1561ED7 /* Resources */,
26393DAD0BBD67E4F16745AC /* Frameworks */,
283EED912DC6170E00943E7E /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
28AC4E312DCFF4B000A78D36 /* PBXTargetDependency */,
);
name = Haystack_iOS;
packageProductDependencies = (
);
productName = Haystack_iOS;
productReference = D4A71980828D15BC10ECF3D2 /* Haystack.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
193F5589816ED16BC8109D31 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1630;
LastUpgradeCheck = 1430;
TargetAttributes = {
28AC4E272DCFF4B000A78D36 = {
CreatedOnToolsVersion = 16.3;
};
};
};
buildConfigurationList = C9EDF156AB15AE44726AF02B /* Build configuration list for PBXProject "Haystack" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
Base,
en,
);
mainGroup = A9913F960CDB1010002108D3;
minimizedProjectReferenceProxies = 1;
projectDirPath = "";
projectRoot = "";
targets = (
28B448F5673D227E72859E56 /* Haystack_iOS */,
28AC4E272DCFF4B000A78D36 /* Sharing */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
28AC4E262DCFF4B000A78D36 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2A76C4DB730794FBF1561ED7 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9CD4A99062C9C9E459750476 /* Assets.xcassets in Resources */,
E41492640ABA177519E3F513 /* LaunchScreen.storyboard in Resources */,
963FC20F9ACC71A08235E8FE /* assets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
6DAC3F72C0E614FB63E90870 /* Build Rust Code */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Build Rust Code";
outputFileListPaths = (
);
outputPaths = (
"$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a",
"$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "source ~/.zprofile\n\nbun tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths \"${FRAMEWORK_SEARCH_PATHS:?}\" --header-search-paths \"${HEADER_SEARCH_PATHS:?}\" --gcc-preprocessor-definitions \"${GCC_PREPROCESSOR_DEFINITIONS:-}\" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?}\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
28AC4E242DCFF4B000A78D36 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
2B0A32A8DA58C48417D38579 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
721E69F824DAAA8F37A0B200 /* main.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
28AC4E312DCFF4B000A78D36 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 28AC4E272DCFF4B000A78D36 /* Sharing */;
targetProxy = 28AC4E302DCFF4B000A78D36 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
17EFD3F6173E3547D2B12EE3 /* release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = arm64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Haystack_iOS/Haystack_iOS.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = RNK8266B74;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\".\"",
);
INFOPLIST_FILE = Haystack_iOS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
"LIBRARY_SEARCH_PATHS[arch=arm64]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
);
"LIBRARY_SEARCH_PATHS[arch=x86_64]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.haystack.app;
PRODUCT_NAME = Haystack;
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64;
};
name = release;
};
28AC4E352DCFF4B000A78D36 /* debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = Sharing/Sharingdebug.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = RNK8266B74;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Sharing/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Sharing;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.haystack.app.Sharing;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = debug;
};
28AC4E362DCFF4B000A78D36 /* release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = Sharing/Sharingrelease.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = RNK8266B74;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Sharing/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Sharing;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.haystack.app.Sharing;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = release;
};
4E8349933047E0253470E886 /* release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
};
name = release;
};
9506B521E6F9B2716C8C2B1D /* debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
"DEBUG=1",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = debug;
};
C03D1D76D6D372BC34FF4DFD /* debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = arm64;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Haystack_iOS/Haystack_iOS.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = RNK8266B74;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\".\"",
);
INFOPLIST_FILE = Haystack_iOS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
"LIBRARY_SEARCH_PATHS[arch=arm64]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
);
"LIBRARY_SEARCH_PATHS[arch=x86_64]" = (
"$(inherited)",
"$(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION)",
"$(SDKROOT)/usr/lib/swift",
"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)",
"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.haystack.app;
PRODUCT_NAME = Haystack;
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = arm64;
};
name = debug;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
28AC4E342DCFF4B000A78D36 /* Build configuration list for PBXNativeTarget "Sharing" */ = {
isa = XCConfigurationList;
buildConfigurations = (
28AC4E352DCFF4B000A78D36 /* debug */,
28AC4E362DCFF4B000A78D36 /* release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = debug;
};
58C375D27CA00AE30B18A640 /* Build configuration list for PBXNativeTarget "Haystack_iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C03D1D76D6D372BC34FF4DFD /* debug */,
17EFD3F6173E3547D2B12EE3 /* release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = debug;
};
C9EDF156AB15AE44726AF02B /* Build configuration list for PBXProject "Haystack" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9506B521E6F9B2716C8C2B1D /* debug */,
4E8349933047E0253470E886 /* release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = debug;
};
/* End XCConfigurationList section */
};
rootObject = 193F5589816ED16BC8109D31 /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
<key>DisableBuildSystemDeprecationDiagnostic</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "28B448F5673D227E72859E56"
BuildableName = "Haystack.app"
BlueprintName = "Haystack_iOS"
ReferencedContainer = "container:Haystack.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "NO">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "28B448F5673D227E72859E56"
BuildableName = "Haystack.app"
BlueprintName = "Haystack_iOS"
ReferencedContainer = "container:Haystack.xcodeproj">
</BuildableReference>
</MacroExpansion>
<EnvironmentVariables>
<EnvironmentVariable
key = "RUST_BACKTRACE"
value = "full"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "RUST_LOG"
value = "info"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "28B448F5673D227E72859E56"
BuildableName = "Haystack.app"
BlueprintName = "Haystack_iOS"
ReferencedContainer = "container:Haystack.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "RUST_BACKTRACE"
value = "full"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "RUST_LOG"
value = "info"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "release"
shouldUseLaunchSchemeArgsEnv = "NO"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "28B448F5673D227E72859E56"
BuildableName = "Haystack.app"
BlueprintName = "Haystack_iOS"
ReferencedContainer = "container:Haystack.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "RUST_BACKTRACE"
value = "full"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "RUST_LOG"
value = "info"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Share View Controller-->
<scene sceneID="ceB-am-kn3">
<objects>
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.haystack.app</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>Haystack</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsImage</key>
<true/>
<key>NSExtensionActivationSupportsMovie</key>
<false/>
<key>NSExtensionActivationSupportsText</key>
<false/>
<key>NSExtensionActivationSupportsURL</key>
<false/>
<key>NSExtensionActivationSupportsWebPageWithText</key>
<false/>
<key>NSExtensionActivationSupportsAttachmentsWithMaxCount</key>
<integer>0</integer>
<key>NSExtensionActivationSupportsAttachmentsWithMinCount</key>
<integer>1</integer>
</dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.share-services</string>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.ui-services</string>
<key>NSExtensionPrincipalClass</key>
<string>Haystack.ShareViewController</string>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,171 @@
//
//  ShareViewController.swift
//  Haystack
//
//  Created by Rio Keefe on 03/05/2025.
//
import UIKit
import Social
import MobileCoreServices
class ShareViewController: SLComposeServiceViewController {
let appGroupName = "group.com.haystack.app" // Replace with your actual App Group identifier
let tokenKey = "sharedAuthToken"
let uploadURL = URL(string: "https://haystack.johncosta.tech/image/")!
var bearerToken: String?
// Store the item provider to access it later in didSelectPost
private var imageItemProvider: NSItemProvider?
private var extractedImageName: String = "image" // Default name
override func viewDidLoad() {
super.viewDidLoad()
// Load the bearer token from the App Group in viewDidLoad
// This is okay as reading from UserDefaults is fast
if let sharedDefaults = UserDefaults(suiteName: appGroupName) {
bearerToken = sharedDefaults.string(forKey: tokenKey)
print("Retrieved bearer token: \(bearerToken ?? "nil")")
} else {
print("Error accessing App Group UserDefaults.")
// Optionally inform the user or disable posting if token is crucial
// self.isContentValid() could check if bearerToken is nil
}
// Store the item provider, but don't load the data synchronously yet
if let item = extensionContext?.inputItems.first as? NSExtensionItem,
let provider = item.attachments?.first as? NSItemProvider {
if provider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
self.imageItemProvider = provider
// Attempt to get a suggested name early if available
extractedImageName = provider.suggestedName ?? "image"
if let dotRange = extractedImageName.range(of: ".", options: .backwards) {
extractedImageName = String(extractedImageName[..<dotRange.lowerBound])
}
} else {
print("No image found.")
// If no image is found, the content is not valid for this extension
// You might want to adjust isContentValid() based on this
}
}
}
override func isContentValid() -> Bool {
// Content is valid only if we have an item provider for an image AND a bearer token
return imageItemProvider != nil && bearerToken != nil
}
override func didSelectPost() {
// This method is called when the user taps the "Post" button.
// Start the asynchronous operation here.
guard let provider = imageItemProvider else {
print("Error: No image item provider found when posting.")
// Inform the user or log an error
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
return
}
guard let token = bearerToken else {
print("Error: Bearer token is missing when posting.")
// Inform the user or log an error
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
return
}
// Load the image data asynchronously
provider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil) { [weak self] (item, error) in
guard let self = self else { return }
if let error = error {
print("Error loading image data for upload: \(error.localizedDescription)")
// Inform the user about the failure
self.extensionContext!.cancelRequest(withError: error)
return
}
var rawImageData: Data?
var finalImageName = self.extractedImageName // Use the name extracted earlier
if let url = item as? URL, let data = try? Data(contentsOf: url) {
rawImageData = data
// Refine the name extraction here if necessary, though doing it in viewDidLoad is also an option
finalImageName = url.lastPathComponent
if let dotRange = finalImageName.range(of: ".", options: .backwards) {
finalImageName = String(finalImageName[..<dotRange.lowerBound])
}
} else if let data = item as? Data {
rawImageData = data
// Use the suggested name if available, fallback to default
finalImageName = provider.suggestedName ?? "image"
} else {
print("Error: Could not get image data in a usable format.")
// Inform the user about the failure
self.extensionContext!.cancelRequest(withError: NSError(domain: "ShareExtension", code: -4, userInfo: [NSLocalizedDescriptionKey: "Could not process image data."]))
return
}
guard let dataToUpload = rawImageData else {
print("Error: No image data to upload.")
// Inform the user about the failure
self.extensionContext!.cancelRequest(withError: NSError(domain: "ShareExtension", code: -5, userInfo: [NSLocalizedDescriptionKey: "Image data is missing."]))
return
}
// Now perform the upload asynchronously
self.uploadRawData(dataToUpload, imageName: finalImageName, bearerToken: token)
}
// Do not complete the request here.
// The request will be completed in the uploadRawData completion handler.
}
func uploadRawData(_ rawData: Data, imageName: String, bearerToken: String) {
// bearerToken is guaranteed to be non-nil here due to the guard in didSelectPost
let uploadURLwithName = uploadURL.appendingPathComponent(imageName)
var request = URLRequest(url: uploadURLwithName)
request.httpMethod = "POST"
request.httpBody = rawData
request.setValue("application/oclet-stream", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in
// **IMPORTANT:** Complete the extension request on the main thread
DispatchQueue.main.async {
print("Upload finished. Error: \(error?.localizedDescription ?? "None"), Response: \(response?.description ?? "None")")
if let error = error {
// Handle upload error (e.g., show an alert to the user)
print("Upload failed: \(error.localizedDescription)")
self?.extensionContext!.cancelRequest(withError: error)
} else if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) {
// Handle non-success HTTP status codes
let errorDescription = "Server returned status code \(httpResponse.statusCode)"
print(errorDescription)
self?.extensionContext!.cancelRequest(withError: NSError(domain: "ShareExtension", code: httpResponse.statusCode, userInfo: [NSLocalizedDescriptionKey: errorDescription]))
}
else {
// Upload was successful
print("Upload successful")
// Complete the request when the upload is done
self?.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
}
}
task.resume()
}
override func configurationItems() -> [Any]! {
// You can add items here if you want to allow the user to enter additional info
// e.g., a text field for a caption.
// This example only handles image upload, so no config items are needed.
return []
}
}

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